Create new RTP Frame structure with separate header field

This commit is contained in:
Aaro Altonen 2019-07-24 09:50:27 +03:00
parent fa1c82fb0f
commit 839285b0dd
4 changed files with 68 additions and 31 deletions

View File

@ -5,6 +5,21 @@
#include "send.hh"
#include "util.hh"
kvz_rtp::frame::rtp_frame *kvz_rtp::frame::alloc_rtp_frame()
{
kvz_rtp::frame::rtp_frame *frame = new kvz_rtp::frame::rtp_frame;
if (!frame) {
rtp_errno = RTP_MEMORY_ERROR;
return nullptr;
}
std::memset(&frame->header, 0, sizeof(kvz_rtp::frame::rtp_header));
std::memset(frame, 0, sizeof(kvz_rtp::frame::rtp_frame));
return frame;
}
kvz_rtp::frame::rtp_frame *kvz_rtp::frame::alloc_rtp_frame(size_t payload_len, rtp_type_t type)
{
if (payload_len == 0 || INVALID_FRAME_TYPE(type)) {
@ -34,10 +49,8 @@ kvz_rtp::frame::rtp_frame *kvz_rtp::frame::alloc_rtp_frame(size_t payload_len, r
break;
}
if ((frame = new kvz_rtp::frame::rtp_frame) == nullptr) {
rtp_errno = RTP_MEMORY_ERROR;
if ((frame = kvz_rtp::frame::alloc_rtp_frame()) == nullptr)
return nullptr;
}
if ((frame->data = new uint8_t[payload_len + header_len]) == nullptr) {
rtp_errno = RTP_MEMORY_ERROR;
@ -45,7 +58,6 @@ kvz_rtp::frame::rtp_frame *kvz_rtp::frame::alloc_rtp_frame(size_t payload_len, r
return nullptr;
}
frame->header_len = header_len;
frame->payload_len = payload_len;
frame->total_len = payload_len + header_len;
frame->payload = frame->data + header_len;

View File

@ -29,20 +29,28 @@ namespace kvz_rtp {
FRAME_TYPE_APP = 204 /* Application-specific message */
} rtcp_type_t;
/* TODO: is this actually a useful struct? */
struct rtp_frame {
PACKED_STRUCT(rtp_header) {
uint8_t version:2;
uint8_t padding:1;
uint8_t ext:1;
uint8_t cc:4;
uint8_t marker:1;
uint8_t payload:7;
uint16_t seq;
uint32_t timestamp;
uint32_t ssrc;
uint16_t seq;
uint8_t ptype;
uint8_t marker;
};
size_t total_len; /* total length of the frame (payload length + header length) */
size_t header_len; /* length of header (varies based on the type of the frame) */
size_t payload_len; /* length of the payload */
struct rtp_frame {
struct rtp_header header;
uint32_t *csrc;
uint8_t *data; /* pointer to the start of the whole buffer */
uint8_t *payload; /* pointer to actual payload */
size_t total_len; /* total length of the frame (including padding) */
size_t padding_len; /* non-zero if frame is padded */
size_t payload_len; /* payload_len: total_len - header_len - padding length (if padded) */
uint8_t *data;
uint8_t *payload;
rtp_format_t format;
rtp_type_t type;
@ -116,6 +124,7 @@ namespace kvz_rtp {
uint8_t payload[0];
};
rtp_frame *alloc_rtp_frame();
rtp_frame *alloc_rtp_frame(size_t payload_len, rtp_type_t type);
rtcp_app_frame *alloc_rtcp_app_frame(std::string name, uint8_t subtype, size_t payload_len);
rtcp_sdes_frame *alloc_rtcp_sdes_frame(size_t ssrc_count, size_t total_len);
@ -123,7 +132,7 @@ namespace kvz_rtp {
rtcp_sender_frame *alloc_rtcp_sender_frame(size_t nblocks);
rtcp_bye_frame *alloc_rtcp_bye_frame(size_t ssrc_count);
rtp_error_t dealloc_frame(rtp_frame *frame);
rtp_error_t dealloc_frame(kvz_rtp::frame::rtp_frame *frame);
/* TODO: template??? */
rtp_error_t dealloc_frame(rtcp_sender_frame *frame);

View File

@ -202,7 +202,7 @@ void kvz_rtp::rtcp::sender_update_stats(kvz_rtp::frame::rtp_frame *frame)
sender_stats.sent_pkts += 1;
sender_stats.sent_bytes += frame->payload_len;
sender_stats.max_seq = frame->seq;
sender_stats.max_seq = frame->header.seq;
}
void kvz_rtp::rtcp::receiver_inc_sent_bytes(uint32_t sender_ssrc, size_t n)
@ -229,19 +229,19 @@ void kvz_rtp::rtcp::init_new_participant(kvz_rtp::frame::rtp_frame *frame)
{
assert(frame != nullptr);
kvz_rtp::rtcp::add_participant(frame->ssrc);
kvz_rtp::rtcp::init_participant_seq(frame->ssrc, frame->seq);
kvz_rtp::rtcp::add_participant(frame->header.ssrc);
kvz_rtp::rtcp::init_participant_seq(frame->header.ssrc, frame->header.seq);
/* Set the probation to MIN_SEQUENTIAL (2)
*
* What this means is that we must receive at least two packets from SSRC
* with sequential RTP sequence numbers for this peer to be considered valid */
participants_[frame->ssrc]->probation = MIN_SEQUENTIAL;
participants_[frame->header.ssrc]->probation = MIN_SEQUENTIAL;
/* This is the first RTP frame from remote to frame->timestamp represents t = 0
/* This is the first RTP frame from remote to frame->header.timestamp represents t = 0
* Save the timestamp and current NTP timestamp so we can do jitter calculations later on */
participants_[frame->ssrc]->stats.initial_rtp = frame->timestamp;
participants_[frame->ssrc]->stats.initial_ntp = kvz_rtp::clock::now_ntp();
participants_[frame->header.ssrc]->stats.initial_rtp = frame->header.timestamp;
participants_[frame->header.ssrc]->stats.initial_ntp = kvz_rtp::clock::now_ntp();
senders_++;
}
@ -311,17 +311,17 @@ void kvz_rtp::rtcp::receiver_update_stats(kvz_rtp::frame::rtp_frame *frame)
if (!frame)
return;
if (!is_participant(frame->ssrc)) {
LOG_WARN("Got RTP packet from unknown source: 0x%x", frame->ssrc);
if (!is_participant(frame->header.ssrc)) {
LOG_WARN("Got RTP packet from unknown source: 0x%x", frame->header.ssrc);
init_new_participant(frame);
}
if (kvz_rtp::rtcp::update_participant_seq(frame->ssrc, frame->seq) != RTP_OK) {
if (kvz_rtp::rtcp::update_participant_seq(frame->header.ssrc, frame->header.seq) != RTP_OK) {
LOG_DEBUG("Invalid packet received from remote!");
return;
}
auto p = participants_[frame->ssrc];
auto p = participants_[frame->header.ssrc];
p->stats.received_pkts += 1;
p->stats.received_bytes += frame->payload_len;
@ -339,7 +339,7 @@ void kvz_rtp::rtcp::receiver_update_stats(kvz_rtp::frame::rtp_frame *frame)
/ 1000);
/* calculate interarrival jitter */
int transit = arrival - frame->timestamp;
int transit = arrival - frame->header.timestamp;
int d = std::abs((int)(transit - p->stats.transit));
p->stats.transit = transit;
@ -672,6 +672,15 @@ rtp_error_t kvz_rtp::rtcp::handle_receiver_report_packet(kvz_rtp::frame::rtcp_re
return RTP_INVALID_VALUE;
}
for (int i = 0; i < frame->header.count; ++i) {
fprintf(stderr, "-------\n");
fprintf(stderr, "lost: %d\n", frame->blocks[i].lost); /* TODO: */
fprintf(stderr, "last_seq: %u\n", ntohl(frame->blocks[i].last_seq));
fprintf(stderr, "last sr: %u\n", ntohl(frame->blocks[i].lsr));
fprintf(stderr, "dlsr: %u\n", ntohl(frame->blocks[i].dlsr));
fprintf(stderr, "-------\n");
}
/* TODO: 6.4.4 Analyzing Sender and Receiver Reports */
return RTP_OK;

View File

@ -207,10 +207,17 @@ kvz_rtp::frame::rtp_frame *kvz_rtp::hevc::process_hevc_frame(
}
if (!fu.second.empty()) {
if (frame->timestamp != fu.second.at(0)->timestamp) {
if (frame->header.timestamp != fu.second.at(0)->header.timestamp) {
LOG_ERROR("Timestamp mismatch for fragmentation units!");
/* TODO: update rtcp stats for dropped packets */
if (frame->header.timestamp > fu.second.at(0)->header.timestamp) {
LOG_ERROR("packet was dropped: %u %u | %u %u", frame->header.timestamp, fu.second.at(0)->header.timestamp,
frame->header.seq, fu.second.at(fu.second.size() - 1)->header.seq);
} else {
LOG_ERROR("packet came in late: %u %u", frame->header.timestamp, fu.second.at(0)->header.timestamp);
}
LOG_WARN("removing %u frames", fu.second.size());
/* push the frame to fu vector so deallocation is cleaner */
fu.second.push_back(frame);
@ -273,7 +280,7 @@ kvz_rtp::frame::rtp_frame *kvz_rtp::hevc::process_hevc_frame(
while (fu.second.size() != 0) {
auto tmp = fu.second.back();
fu.second.pop_back();
kvz_rtp::frame::dealloc_frame(tmp);
(void)kvz_rtp::frame::dealloc_frame(tmp);
}
/* reset the total size of fragmentation units */
@ -286,7 +293,7 @@ error:
while (fu.second.size() != 0) {
auto tmp = fu.second.back();
fu.second.pop_back();
kvz_rtp::frame::dealloc_frame(tmp);
(void)kvz_rtp::frame::dealloc_frame(tmp);
}
/* reset the total size of fragmentation units */