1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

Refine on_rtcp for RTC

This commit is contained in:
winlin 2020-05-08 16:25:09 +08:00
parent 9614af070c
commit 26bcc09017
4 changed files with 547 additions and 468 deletions

View file

@ -1550,6 +1550,149 @@ void SrsRtcPlayer::simulate_drop_packet(SrsRtpHeader* h, int nn_bytes)
nn_simulate_nack_drop--; nn_simulate_nack_drop--;
} }
srs_error_t SrsRtcPlayer::on_rtcp(char* data, int nb_data)
{
srs_error_t err = srs_success;
char* ph = data;
int nb_left = nb_data;
while (nb_left) {
uint8_t payload_type = ph[1];
uint16_t length_4bytes = (((uint16_t)ph[2]) << 8) | ph[3];
int length = (length_4bytes + 1) * 4;
if (length > nb_data) {
return srs_error_new(ERROR_RTC_RTCP, "invalid rtcp packet, length=%u", length);
}
srs_verbose("on rtcp, payload_type=%u", payload_type);
switch (payload_type) {
case kSR: {
err = on_rtcp_sr(ph, length);
break;
}
case kRR: {
err = on_rtcp_rr(ph, length);
break;
}
case kSDES: {
break;
}
case kBye: {
break;
}
case kApp: {
break;
}
case kRtpFb: {
err = on_rtcp_feedback(ph, length);
break;
}
case kPsFb: {
err = on_rtcp_ps_feedback(ph, length);
break;
}
case kXR: {
err = on_rtcp_xr(ph, length);
break;
}
default:{
return srs_error_new(ERROR_RTC_RTCP_CHECK, "unknown rtcp type=%u", payload_type);
break;
}
}
if (err != srs_success) {
return srs_error_wrap(err, "rtcp");
}
ph += length;
nb_left -= length;
}
return err;
}
srs_error_t SrsRtcPlayer::on_rtcp_sr(char* buf, int nb_buf)
{
srs_error_t err = srs_success;
// TODO: FIXME: Implements it.
return err;
}
srs_error_t SrsRtcPlayer::on_rtcp_xr(char* buf, int nb_buf)
{
srs_error_t err = srs_success;
// TODO: FIXME: Implements it.
return err;
}
srs_error_t SrsRtcPlayer::on_rtcp_feedback(char* data, int nb_data)
{
srs_error_t err = srs_success;
// TODO: FIXME: Implements it.
return err;
}
srs_error_t SrsRtcPlayer::on_rtcp_ps_feedback(char* buf, int nb_buf)
{
srs_error_t err = srs_success;
if (nb_buf < 12) {
return srs_error_new(ERROR_RTC_RTCP_CHECK, "invalid rtp feedback packet, nb_buf=%d", nb_buf);
}
SrsBuffer* stream = new SrsBuffer(buf, nb_buf);
SrsAutoFree(SrsBuffer, stream);
uint8_t first = stream->read_1bytes();
//uint8_t version = first & 0xC0;
//uint8_t padding = first & 0x20;
uint8_t fmt = first & 0x1F;
/*uint8_t payload_type = */stream->read_1bytes();
/*uint16_t length = */stream->read_2bytes();
/*uint32_t ssrc_of_sender = */stream->read_4bytes();
/*uint32_t ssrc_of_media_source = */stream->read_4bytes();
switch (fmt) {
case kPLI: {
SrsRtcPublisher* publisher = session_->source_->rtc_publisher();
if (publisher) {
publisher->request_keyframe();
srs_trace("RTC request PLI");
}
break;
}
case kSLI: {
srs_verbose("sli");
break;
}
case kRPSI: {
srs_verbose("rpsi");
break;
}
case kAFB: {
srs_verbose("afb");
break;
}
default: {
return srs_error_new(ERROR_RTC_RTCP, "unknown payload specific feedback=%u", fmt);
}
}
return err;
}
srs_error_t SrsRtcPlayer::on_rtcp_rr(char* data, int nb_data)
{
srs_error_t err = srs_success;
// TODO: FIXME: Implements it.
return err;
}
SrsRtcPublisher::SrsRtcPublisher(SrsRtcSession* session) SrsRtcPublisher::SrsRtcPublisher(SrsRtcSession* session)
{ {
report_timer = new SrsHourGlass(this, 200 * SRS_UTIME_MILLISECONDS); report_timer = new SrsHourGlass(this, 200 * SRS_UTIME_MILLISECONDS);
@ -1620,160 +1763,6 @@ srs_error_t SrsRtcPublisher::initialize(uint32_t vssrc, uint32_t assrc, SrsReque
return err; return err;
} }
srs_error_t SrsRtcPublisher::on_rtcp_sender_report(char* buf, int nb_buf)
{
srs_error_t err = srs_success;
if (nb_buf < 28) {
return srs_error_new(ERROR_RTC_RTCP_CHECK, "invalid rtp sender report packet, nb_buf=%d", nb_buf);
}
SrsBuffer* stream = new SrsBuffer(buf, nb_buf);
SrsAutoFree(SrsBuffer, stream);
// @see: https://tools.ietf.org/html/rfc3550#section-6.4.1
/*
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
header |V=2|P| RC | PT=SR=200 | length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| SSRC of sender |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
sender | NTP timestamp, most significant word |
info +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NTP timestamp, least significant word |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| RTP timestamp |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| sender's packet count |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| sender's octet count |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
report | SSRC_1 (SSRC of first source) |
block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1 | fraction lost | cumulative number of packets lost |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| extended highest sequence number received |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| interarrival jitter |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| last SR (LSR) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| delay since last SR (DLSR) |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
report | SSRC_2 (SSRC of second source) |
block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2 : ... :
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
| profile-specific extensions |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
uint8_t first = stream->read_1bytes();
uint8_t rc = first & 0x1F;
uint8_t payload_type = stream->read_1bytes();
srs_assert(payload_type == kSR);
uint16_t length = stream->read_2bytes();
if (((length + 1) * 4) != (rc * 24 + 28)) {
return srs_error_new(ERROR_RTC_RTCP_CHECK, "invalid rtcp sender report packet, length=%u, rc=%u", length, rc);
}
uint32_t ssrc_of_sender = stream->read_4bytes();
uint64_t ntp = stream->read_8bytes();
SrsNtp srs_ntp = SrsNtp::to_time_ms(ntp);
uint32_t rtp_time = stream->read_4bytes();
uint32_t sender_packet_count = stream->read_4bytes();
uint32_t sender_octec_count = stream->read_4bytes();
(void)sender_packet_count; (void)sender_octec_count; (void)rtp_time;
srs_verbose("sender report, ssrc_of_sender=%u, rtp_time=%u, sender_packet_count=%u, sender_octec_count=%u",
ssrc_of_sender, rtp_time, sender_packet_count, sender_octec_count);
for (int i = 0; i < rc; ++i) {
uint32_t ssrc = stream->read_4bytes();
uint8_t fraction_lost = stream->read_1bytes();
uint32_t cumulative_number_of_packets_lost = stream->read_3bytes();
uint32_t highest_seq = stream->read_4bytes();
uint32_t jitter = stream->read_4bytes();
uint32_t lst = stream->read_4bytes();
uint32_t dlsr = stream->read_4bytes();
(void)ssrc; (void)fraction_lost; (void)cumulative_number_of_packets_lost; (void)highest_seq; (void)jitter; (void)lst; (void)dlsr;
srs_verbose("sender report, ssrc=%u, fraction_lost=%u, cumulative_number_of_packets_lost=%u, highest_seq=%u, jitter=%u, lst=%u, dlst=%u",
ssrc, fraction_lost, cumulative_number_of_packets_lost, highest_seq, jitter, lst, dlsr);
}
last_sender_report_ntp[ssrc_of_sender] = srs_ntp;
last_sender_report_sys_time[ssrc_of_sender] = srs_update_system_time();
return err;
}
srs_error_t SrsRtcPublisher::on_rtcp_xr(char* buf, int nb_buf)
{
srs_error_t err = srs_success;
/*
@see: http://www.rfc-editor.org/rfc/rfc3611.html#section-2
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P|reserved | PT=XR=207 | length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| SSRC |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: report blocks :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
SrsBuffer stream(buf, nb_buf);
/*uint8_t first = */stream.read_1bytes();
uint8_t pt = stream.read_1bytes();
srs_assert(pt == kXR);
uint16_t length = (stream.read_2bytes() + 1) * 4;
/*uint32_t ssrc = */stream.read_4bytes();
if (length != nb_buf) {
return srs_error_new(ERROR_RTC_RTCP_CHECK, "invalid XR packet, length=%u, nb_buf=%d", length, nb_buf);
}
while (stream.pos() + 4 < length) {
uint8_t bt = stream.read_1bytes();
stream.skip(1);
uint16_t block_length = (stream.read_2bytes() + 1) * 4;
if (stream.pos() + block_length - 4 > nb_buf) {
return srs_error_new(ERROR_RTC_RTCP_CHECK, "invalid XR packet block, block_length=%u, nb_buf=%d", block_length, nb_buf);
}
if (bt == 5) {
for (int i = 4; i < block_length; i += 12) {
uint32_t ssrc = stream.read_4bytes();
uint32_t lrr = stream.read_4bytes();
uint32_t dlrr = stream.read_4bytes();
SrsNtp cur_ntp = SrsNtp::from_time_ms(srs_update_system_time() / 1000);
uint32_t compact_ntp = (cur_ntp.ntp_second_ << 16) | (cur_ntp.ntp_fractions_ >> 16);
int rtt_ntp = compact_ntp - lrr - dlrr;
int rtt = ((rtt_ntp * 1000) >> 16) + ((rtt_ntp >> 16) * 1000);
srs_verbose("ssrc=%u, compact_ntp=%u, lrr=%u, dlrr=%u, rtt=%d",
ssrc, compact_ntp, lrr, dlrr, rtt);
if (ssrc == video_ssrc) {
video_nack_->update_rtt(rtt);
} else if (ssrc == audio_ssrc) {
audio_nack_->update_rtt(rtt);
}
}
}
}
return err;
}
void SrsRtcPublisher::check_send_nacks(SrsRtpNackForReceiver* nack, uint32_t ssrc) void SrsRtcPublisher::check_send_nacks(SrsRtpNackForReceiver* nack, uint32_t ssrc)
{ {
// If DTLS is not OK, drop all messages. // If DTLS is not OK, drop all messages.
@ -1781,6 +1770,7 @@ void SrsRtcPublisher::check_send_nacks(SrsRtpNackForReceiver* nack, uint32_t ssr
return; return;
} }
// @see: https://tools.ietf.org/html/rfc4585#section-6.1
vector<uint16_t> nack_seqs; vector<uint16_t> nack_seqs;
nack->get_nack_seqs(nack_seqs); nack->get_nack_seqs(nack_seqs);
vector<uint16_t>::iterator iter = nack_seqs.begin(); vector<uint16_t>::iterator iter = nack_seqs.begin();
@ -1791,8 +1781,8 @@ void SrsRtcPublisher::check_send_nacks(SrsRtpNackForReceiver* nack, uint32_t ssr
stream.write_1bytes(0x81); stream.write_1bytes(0x81);
stream.write_1bytes(kRtpFb); stream.write_1bytes(kRtpFb);
stream.write_2bytes(3); stream.write_2bytes(3);
stream.write_4bytes(ssrc); stream.write_4bytes(ssrc); // TODO: FIXME: Should be 1?
stream.write_4bytes(ssrc); stream.write_4bytes(ssrc); // TODO: FIXME: Should be 0?
uint16_t pid = *iter; uint16_t pid = *iter;
uint16_t blp = 0; uint16_t blp = 0;
while (iter + 1 != nack_seqs.end() && (*(iter + 1) - pid <= 15)) { while (iter + 1 != nack_seqs.end() && (*(iter + 1) - pid <= 15)) {
@ -1831,12 +1821,13 @@ srs_error_t SrsRtcPublisher::send_rtcp_rr(uint32_t ssrc, SrsRtpQueue* rtp_queue)
return err; return err;
} }
// @see https://tools.ietf.org/html/rfc3550#section-6.4.2
char buf[kRtpPacketSize]; char buf[kRtpPacketSize];
SrsBuffer stream(buf, sizeof(buf)); SrsBuffer stream(buf, sizeof(buf));
stream.write_1bytes(0x81); stream.write_1bytes(0x81);
stream.write_1bytes(kRR); stream.write_1bytes(kRR);
stream.write_2bytes(7); stream.write_2bytes(7);
stream.write_4bytes(ssrc); stream.write_4bytes(ssrc); // TODO: FIXME: Should be 1?
uint8_t fraction_lost = rtp_queue->get_fraction_lost(); uint8_t fraction_lost = rtp_queue->get_fraction_lost();
uint32_t cumulative_number_of_packets_lost = rtp_queue->get_cumulative_number_of_packets_lost() & 0x7FFFFF; uint32_t cumulative_number_of_packets_lost = rtp_queue->get_cumulative_number_of_packets_lost() & 0x7FFFFF;
@ -2029,6 +2020,71 @@ void SrsRtcPublisher::on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* bu
} }
} }
srs_error_t SrsRtcPublisher::on_rtcp(char* data, int nb_data)
{
srs_error_t err = srs_success;
char* ph = data;
int nb_left = nb_data;
while (nb_left) {
uint8_t payload_type = ph[1];
uint16_t length_4bytes = (((uint16_t)ph[2]) << 8) | ph[3];
int length = (length_4bytes + 1) * 4;
if (length > nb_data) {
return srs_error_new(ERROR_RTC_RTCP, "invalid rtcp packet, length=%u", length);
}
srs_verbose("on rtcp, payload_type=%u", payload_type);
switch (payload_type) {
case kSR: {
err = on_rtcp_sr(ph, length);
break;
}
case kRR: {
err = on_rtcp_rr(ph, length);
break;
}
case kSDES: {
break;
}
case kBye: {
break;
}
case kApp: {
break;
}
case kRtpFb: {
err = on_rtcp_feedback(ph, length);
break;
}
case kPsFb: {
err = on_rtcp_ps_feedback(ph, length);
break;
}
case kXR: {
err = on_rtcp_xr(ph, length);
break;
}
default:{
return srs_error_new(ERROR_RTC_RTCP_CHECK, "unknown rtcp type=%u", payload_type);
break;
}
}
if (err != srs_success) {
return srs_error_wrap(err, "rtcp");
}
ph += length;
nb_left -= length;
}
return err;
}
srs_error_t SrsRtcPublisher::on_audio(SrsRtpPacket2* pkt) srs_error_t SrsRtcPublisher::on_audio(SrsRtpPacket2* pkt)
{ {
srs_error_t err = srs_success; srs_error_t err = srs_success;
@ -2247,6 +2303,283 @@ srs_error_t SrsRtcPublisher::on_video_frame(SrsRtpPacket2* frame)
return source->on_video(shared_video); return source->on_video(shared_video);
} }
srs_error_t SrsRtcPublisher::on_rtcp_sr(char* buf, int nb_buf)
{
srs_error_t err = srs_success;
if (nb_buf < 28) {
return srs_error_new(ERROR_RTC_RTCP_CHECK, "invalid rtp sender report packet, nb_buf=%d", nb_buf);
}
SrsBuffer* stream = new SrsBuffer(buf, nb_buf);
SrsAutoFree(SrsBuffer, stream);
// @see: https://tools.ietf.org/html/rfc3550#section-6.4.1
/*
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
header |V=2|P| RC | PT=SR=200 | length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| SSRC of sender |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
sender | NTP timestamp, most significant word |
info +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NTP timestamp, least significant word |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| RTP timestamp |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| sender's packet count |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| sender's octet count |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
report | SSRC_1 (SSRC of first source) |
block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1 | fraction lost | cumulative number of packets lost |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| extended highest sequence number received |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| interarrival jitter |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| last SR (LSR) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| delay since last SR (DLSR) |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
report | SSRC_2 (SSRC of second source) |
block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2 : ... :
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
| profile-specific extensions |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
uint8_t first = stream->read_1bytes();
uint8_t rc = first & 0x1F;
uint8_t payload_type = stream->read_1bytes();
srs_assert(payload_type == kSR);
uint16_t length = stream->read_2bytes();
if (((length + 1) * 4) != (rc * 24 + 28)) {
return srs_error_new(ERROR_RTC_RTCP_CHECK, "invalid rtcp sender report packet, length=%u, rc=%u", length, rc);
}
uint32_t ssrc_of_sender = stream->read_4bytes();
uint64_t ntp = stream->read_8bytes();
SrsNtp srs_ntp = SrsNtp::to_time_ms(ntp);
uint32_t rtp_time = stream->read_4bytes();
uint32_t sender_packet_count = stream->read_4bytes();
uint32_t sender_octec_count = stream->read_4bytes();
(void)sender_packet_count; (void)sender_octec_count; (void)rtp_time;
srs_verbose("sender report, ssrc_of_sender=%u, rtp_time=%u, sender_packet_count=%u, sender_octec_count=%u",
ssrc_of_sender, rtp_time, sender_packet_count, sender_octec_count);
for (int i = 0; i < rc; ++i) {
uint32_t ssrc = stream->read_4bytes();
uint8_t fraction_lost = stream->read_1bytes();
uint32_t cumulative_number_of_packets_lost = stream->read_3bytes();
uint32_t highest_seq = stream->read_4bytes();
uint32_t jitter = stream->read_4bytes();
uint32_t lst = stream->read_4bytes();
uint32_t dlsr = stream->read_4bytes();
(void)ssrc; (void)fraction_lost; (void)cumulative_number_of_packets_lost; (void)highest_seq; (void)jitter; (void)lst; (void)dlsr;
srs_verbose("sender report, ssrc=%u, fraction_lost=%u, cumulative_number_of_packets_lost=%u, highest_seq=%u, jitter=%u, lst=%u, dlst=%u",
ssrc, fraction_lost, cumulative_number_of_packets_lost, highest_seq, jitter, lst, dlsr);
}
last_sender_report_ntp[ssrc_of_sender] = srs_ntp;
last_sender_report_sys_time[ssrc_of_sender] = srs_update_system_time();
return err;
}
srs_error_t SrsRtcPublisher::on_rtcp_xr(char* buf, int nb_buf)
{
srs_error_t err = srs_success;
/*
@see: http://www.rfc-editor.org/rfc/rfc3611.html#section-2
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P|reserved | PT=XR=207 | length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| SSRC |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: report blocks :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
SrsBuffer stream(buf, nb_buf);
/*uint8_t first = */stream.read_1bytes();
uint8_t pt = stream.read_1bytes();
srs_assert(pt == kXR);
uint16_t length = (stream.read_2bytes() + 1) * 4;
/*uint32_t ssrc = */stream.read_4bytes();
if (length != nb_buf) {
return srs_error_new(ERROR_RTC_RTCP_CHECK, "invalid XR packet, length=%u, nb_buf=%d", length, nb_buf);
}
while (stream.pos() + 4 < length) {
uint8_t bt = stream.read_1bytes();
stream.skip(1);
uint16_t block_length = (stream.read_2bytes() + 1) * 4;
if (stream.pos() + block_length - 4 > nb_buf) {
return srs_error_new(ERROR_RTC_RTCP_CHECK, "invalid XR packet block, block_length=%u, nb_buf=%d", block_length, nb_buf);
}
if (bt == 5) {
for (int i = 4; i < block_length; i += 12) {
uint32_t ssrc = stream.read_4bytes();
uint32_t lrr = stream.read_4bytes();
uint32_t dlrr = stream.read_4bytes();
SrsNtp cur_ntp = SrsNtp::from_time_ms(srs_update_system_time() / 1000);
uint32_t compact_ntp = (cur_ntp.ntp_second_ << 16) | (cur_ntp.ntp_fractions_ >> 16);
int rtt_ntp = compact_ntp - lrr - dlrr;
int rtt = ((rtt_ntp * 1000) >> 16) + ((rtt_ntp >> 16) * 1000);
srs_verbose("ssrc=%u, compact_ntp=%u, lrr=%u, dlrr=%u, rtt=%d",
ssrc, compact_ntp, lrr, dlrr, rtt);
if (ssrc == video_ssrc) {
video_nack_->update_rtt(rtt);
} else if (ssrc == audio_ssrc) {
audio_nack_->update_rtt(rtt);
}
}
}
}
return err;
}
srs_error_t SrsRtcPublisher::on_rtcp_feedback(char* buf, int nb_buf)
{
srs_error_t err = srs_success;
// TODO: FIXME: Implements it.
return err;
}
srs_error_t SrsRtcPublisher::on_rtcp_ps_feedback(char* buf, int nb_buf)
{
srs_error_t err = srs_success;
if (nb_buf < 12) {
return srs_error_new(ERROR_RTC_RTCP_CHECK, "invalid rtp feedback packet, nb_buf=%d", nb_buf);
}
SrsBuffer* stream = new SrsBuffer(buf, nb_buf);
SrsAutoFree(SrsBuffer, stream);
uint8_t first = stream->read_1bytes();
//uint8_t version = first & 0xC0;
//uint8_t padding = first & 0x20;
uint8_t fmt = first & 0x1F;
/*uint8_t payload_type = */stream->read_1bytes();
/*uint16_t length = */stream->read_2bytes();
/*uint32_t ssrc_of_sender = */stream->read_4bytes();
/*uint32_t ssrc_of_media_source = */stream->read_4bytes();
switch (fmt) {
case kPLI: {
srs_verbose("pli");
break;
}
case kSLI: {
srs_verbose("sli");
break;
}
case kRPSI: {
srs_verbose("rpsi");
break;
}
case kAFB: {
srs_verbose("afb");
break;
}
default: {
return srs_error_new(ERROR_RTC_RTCP, "unknown payload specific feedback=%u", fmt);
}
}
return err;
}
srs_error_t SrsRtcPublisher::on_rtcp_rr(char* buf, int nb_buf)
{
srs_error_t err = srs_success;
if (nb_buf < 8) {
return srs_error_new(ERROR_RTC_RTCP_CHECK, "invalid rtp receiver report packet, nb_buf=%d", nb_buf);
}
SrsBuffer* stream = new SrsBuffer(buf, nb_buf);
SrsAutoFree(SrsBuffer, stream);
// @see: https://tools.ietf.org/html/rfc3550#section-6.4.2
/*
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
header |V=2|P| RC | PT=RR=201 | length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| SSRC of packet sender |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
report | SSRC_1 (SSRC of first source) |
block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1 | fraction lost | cumulative number of packets lost |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| extended highest sequence number received |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| interarrival jitter |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| last SR (LSR) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| delay since last SR (DLSR) |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
report | SSRC_2 (SSRC of second source) |
block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2 : ... :
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
| profile-specific extensions |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
uint8_t first = stream->read_1bytes();
//uint8_t version = first & 0xC0;
//uint8_t padding = first & 0x20;
uint8_t rc = first & 0x1F;
/*uint8_t payload_type = */stream->read_1bytes();
uint16_t length = stream->read_2bytes();
/*uint32_t ssrc_of_sender = */stream->read_4bytes();
if (((length + 1) * 4) != (rc * 24 + 8)) {
return srs_error_new(ERROR_RTC_RTCP_CHECK, "invalid rtcp receiver packet, length=%u, rc=%u", length, rc);
}
for (int i = 0; i < rc; ++i) {
uint32_t ssrc = stream->read_4bytes();
uint8_t fraction_lost = stream->read_1bytes();
uint32_t cumulative_number_of_packets_lost = stream->read_3bytes();
uint32_t highest_seq = stream->read_4bytes();
uint32_t jitter = stream->read_4bytes();
uint32_t lst = stream->read_4bytes();
uint32_t dlsr = stream->read_4bytes();
(void)ssrc; (void)fraction_lost; (void)cumulative_number_of_packets_lost; (void)highest_seq; (void)jitter; (void)lst; (void)dlsr;
srs_verbose("ssrc=%u, fraction_lost=%u, cumulative_number_of_packets_lost=%u, highest_seq=%u, jitter=%u, lst=%u, dlst=%u",
ssrc, fraction_lost, cumulative_number_of_packets_lost, highest_seq, jitter, lst, dlsr);
}
return err;
}
void SrsRtcPublisher::request_keyframe() void SrsRtcPublisher::request_keyframe()
{ {
int scid = _srs_context->get_id(); int scid = _srs_context->get_id();
@ -2483,62 +2816,12 @@ srs_error_t SrsRtcSession::on_rtcp(char* data, int nb_data)
srs_sendto(blackhole_stfd, p, len, (sockaddr*)blackhole_addr, sizeof(sockaddr_in), SRS_UTIME_NO_TIMEOUT); srs_sendto(blackhole_stfd, p, len, (sockaddr*)blackhole_addr, sizeof(sockaddr_in), SRS_UTIME_NO_TIMEOUT);
} }
char* ph = unprotected_buf; if (player_) {
int nb_left = nb_unprotected_buf; return player_->on_rtcp(unprotected_buf, nb_unprotected_buf);
while (nb_left) { }
uint8_t payload_type = ph[1];
uint16_t length_4bytes = (((uint16_t)ph[2]) << 8) | ph[3];
int length = (length_4bytes + 1) * 4; if (publisher_) {
return publisher_->on_rtcp(unprotected_buf, nb_unprotected_buf);
if (length > nb_unprotected_buf) {
return srs_error_new(ERROR_RTC_RTCP, "invalid rtcp packet, length=%u", length);
}
srs_verbose("on rtcp, payload_type=%u", payload_type);
switch (payload_type) {
case kSR: {
err = on_rtcp_sender_report(ph, length);
break;
}
case kRR: {
err = on_rtcp_receiver_report(ph, length);
break;
}
case kSDES: {
break;
}
case kBye: {
break;
}
case kApp: {
break;
}
case kRtpFb: {
err = on_rtcp_feedback(ph, length);
break;
}
case kPsFb: {
err = on_rtcp_ps_feedback(ph, length);
break;
}
case kXR: {
err = on_rtcp_xr(ph, length);
break;
}
default:{
return srs_error_new(ERROR_RTC_RTCP_CHECK, "unknown rtcp type=%u", payload_type);
break;
}
}
if (err != srs_success) {
return srs_error_wrap(err, "rtcp");
}
ph += length;
nb_left -= length;
} }
return err; return err;
@ -2742,231 +3025,6 @@ srs_error_t SrsRtcSession::on_binding_request(SrsStunPacket* r)
return err; return err;
} }
srs_error_t SrsRtcSession::on_rtcp_feedback(char* buf, int nb_buf)
{
srs_error_t err = srs_success;
if (!dtls_) {
return err;
}
if (nb_buf < 12) {
return srs_error_new(ERROR_RTC_RTCP_CHECK, "invalid rtp feedback packet, nb_buf=%d", nb_buf);
}
SrsBuffer* stream = new SrsBuffer(buf, nb_buf);
SrsAutoFree(SrsBuffer, stream);
// @see: https://tools.ietf.org/html/rfc4585#section-6.1
/*
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P| FMT | PT | length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| SSRC of packet sender |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| SSRC of media source |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: Feedback Control Information (FCI) :
: :
*/
/*uint8_t first = */stream->read_1bytes();
//uint8_t version = first & 0xC0;
//uint8_t padding = first & 0x20;
//uint8_t fmt = first & 0x1F;
/*uint8_t payload_type = */stream->read_1bytes();
/*uint16_t length = */stream->read_2bytes();
/*uint32_t ssrc_of_sender = */stream->read_4bytes();
uint32_t ssrc_of_media_source = stream->read_4bytes();
/*
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| PID | BLP |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
uint16_t pid = stream->read_2bytes();
int blp = stream->read_2bytes();
// TODO: FIXME: Support ARQ.
vector<SrsRtpPacket2*> resend_pkts;
if (player_) {
player_->nack_fetch(resend_pkts, ssrc_of_media_source, pid);
}
uint16_t mask = 0x01;
for (int i = 1; i < 16 && blp; ++i, mask <<= 1) {
if (!(blp & mask)) {
continue;
}
uint32_t loss_seq = pid + i;
if (player_) {
player_->nack_fetch(resend_pkts, ssrc_of_media_source, loss_seq);
}
}
for (int i = 0; i < (int)resend_pkts.size(); ++i) {
SrsRtpPacket2* pkt = resend_pkts[i];
char* data = new char[pkt->nb_bytes()];
SrsAutoFreeA(char, data);
SrsBuffer buf(data, pkt->nb_bytes());
// TODO: FIXME: Check error.
pkt->encode(&buf);
sendonly_skt->sendto(data, pkt->nb_bytes(), 0);
SrsRtpHeader* h = &pkt->rtp_header;
srs_trace("RTC NACK ARQ seq=%u, ssrc=%u, ts=%u, %d bytes", h->get_sequence(),
h->get_ssrc(), h->get_timestamp(), pkt->nb_bytes());
}
return err;
}
srs_error_t SrsRtcSession::on_rtcp_ps_feedback(char* buf, int nb_buf)
{
srs_error_t err = srs_success;
if (nb_buf < 12) {
return srs_error_new(ERROR_RTC_RTCP_CHECK, "invalid rtp feedback packet, nb_buf=%d", nb_buf);
}
SrsBuffer* stream = new SrsBuffer(buf, nb_buf);
SrsAutoFree(SrsBuffer, stream);
uint8_t first = stream->read_1bytes();
//uint8_t version = first & 0xC0;
//uint8_t padding = first & 0x20;
uint8_t fmt = first & 0x1F;
/*uint8_t payload_type = */stream->read_1bytes();
/*uint16_t length = */stream->read_2bytes();
/*uint32_t ssrc_of_sender = */stream->read_4bytes();
/*uint32_t ssrc_of_media_source = */stream->read_4bytes();
switch (fmt) {
case kPLI: {
SrsRtcPublisher* publisher = source_->rtc_publisher();
if (publisher) {
publisher->request_keyframe();
srs_trace("RTC request PLI");
}
break;
}
case kSLI: {
srs_verbose("sli");
break;
}
case kRPSI: {
srs_verbose("rpsi");
break;
}
case kAFB: {
srs_verbose("afb");
break;
}
default: {
return srs_error_new(ERROR_RTC_RTCP, "unknown payload specific feedback=%u", fmt);
}
}
return err;
}
srs_error_t SrsRtcSession::on_rtcp_xr(char* buf, int nb_buf)
{
if (publisher_ == NULL) {
return srs_error_new(ERROR_RTC_RTCP, "rtc publisher null");
}
return publisher_->on_rtcp_xr(buf, nb_buf);
}
srs_error_t SrsRtcSession::on_rtcp_sender_report(char* buf, int nb_buf)
{
if (publisher_ == NULL) {
return srs_error_new(ERROR_RTC_RTCP, "rtc publisher null");
}
return publisher_->on_rtcp_sender_report(buf, nb_buf);
}
srs_error_t SrsRtcSession::on_rtcp_receiver_report(char* buf, int nb_buf)
{
srs_error_t err = srs_success;
if (nb_buf < 8) {
return srs_error_new(ERROR_RTC_RTCP_CHECK, "invalid rtp receiver report packet, nb_buf=%d", nb_buf);
}
SrsBuffer* stream = new SrsBuffer(buf, nb_buf);
SrsAutoFree(SrsBuffer, stream);
// @see: https://tools.ietf.org/html/rfc3550#section-6.4.2
/*
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
header |V=2|P| RC | PT=RR=201 | length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| SSRC of packet sender |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
report | SSRC_1 (SSRC of first source) |
block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1 | fraction lost | cumulative number of packets lost |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| extended highest sequence number received |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| interarrival jitter |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| last SR (LSR) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| delay since last SR (DLSR) |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
report | SSRC_2 (SSRC of second source) |
block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2 : ... :
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
| profile-specific extensions |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
uint8_t first = stream->read_1bytes();
//uint8_t version = first & 0xC0;
//uint8_t padding = first & 0x20;
uint8_t rc = first & 0x1F;
/*uint8_t payload_type = */stream->read_1bytes();
uint16_t length = stream->read_2bytes();
/*uint32_t ssrc_of_sender = */stream->read_4bytes();
if (((length + 1) * 4) != (rc * 24 + 8)) {
return srs_error_new(ERROR_RTC_RTCP_CHECK, "invalid rtcp receiver packet, length=%u, rc=%u", length, rc);
}
for (int i = 0; i < rc; ++i) {
uint32_t ssrc = stream->read_4bytes();
uint8_t fraction_lost = stream->read_1bytes();
uint32_t cumulative_number_of_packets_lost = stream->read_3bytes();
uint32_t highest_seq = stream->read_4bytes();
uint32_t jitter = stream->read_4bytes();
uint32_t lst = stream->read_4bytes();
uint32_t dlsr = stream->read_4bytes();
(void)ssrc; (void)fraction_lost; (void)cumulative_number_of_packets_lost; (void)highest_seq; (void)jitter; (void)lst; (void)dlsr;
srs_verbose("ssrc=%u, fraction_lost=%u, cumulative_number_of_packets_lost=%u, highest_seq=%u, jitter=%u, lst=%u, dlst=%u",
ssrc, fraction_lost, cumulative_number_of_packets_lost, highest_seq, jitter, lst, dlsr);
}
return err;
}
SrsUdpMuxSender::SrsUdpMuxSender(SrsRtcServer* s) SrsUdpMuxSender::SrsUdpMuxSender(SrsRtcServer* s)
{ {
lfd = NULL; lfd = NULL;

View file

@ -267,6 +267,14 @@ public:
void simulate_nack_drop(int nn); void simulate_nack_drop(int nn);
private: private:
void simulate_drop_packet(SrsRtpHeader* h, int nn_bytes); void simulate_drop_packet(SrsRtpHeader* h, int nn_bytes);
public:
srs_error_t on_rtcp(char* data, int nb_data);
private:
srs_error_t on_rtcp_sr(char* buf, int nb_buf);
srs_error_t on_rtcp_xr(char* buf, int nb_buf);
srs_error_t on_rtcp_feedback(char* data, int nb_data);
srs_error_t on_rtcp_ps_feedback(char* data, int nb_data);
srs_error_t on_rtcp_rr(char* data, int nb_data);
}; };
class SrsRtcPublisher : virtual public ISrsHourGlass, virtual public ISrsRtpPacketDecodeHandler class SrsRtcPublisher : virtual public ISrsHourGlass, virtual public ISrsRtpPacketDecodeHandler
@ -298,8 +306,6 @@ public:
virtual ~SrsRtcPublisher(); virtual ~SrsRtcPublisher();
public: public:
srs_error_t initialize(uint32_t vssrc, uint32_t assrc, SrsRequest* req); srs_error_t initialize(uint32_t vssrc, uint32_t assrc, SrsRequest* req);
srs_error_t on_rtcp_sender_report(char* buf, int nb_buf);
srs_error_t on_rtcp_xr(char* buf, int nb_buf);
private: private:
void check_send_nacks(SrsRtpNackForReceiver* nack, uint32_t ssrc); void check_send_nacks(SrsRtpNackForReceiver* nack, uint32_t ssrc);
srs_error_t send_rtcp_rr(uint32_t ssrc, SrsRtpQueue* rtp_queue); srs_error_t send_rtcp_rr(uint32_t ssrc, SrsRtpQueue* rtp_queue);
@ -308,11 +314,17 @@ private:
public: public:
srs_error_t on_rtp(char* buf, int nb_buf); srs_error_t on_rtp(char* buf, int nb_buf);
virtual void on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* buf, ISrsCodec** ppayload); virtual void on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* buf, ISrsCodec** ppayload);
srs_error_t on_rtcp(char* data, int nb_data);
private: private:
srs_error_t on_audio(SrsRtpPacket2* pkt); srs_error_t on_audio(SrsRtpPacket2* pkt);
srs_error_t on_audio_frame(SrsRtpPacket2* frame); srs_error_t on_audio_frame(SrsRtpPacket2* frame);
srs_error_t on_video(SrsRtpPacket2* pkt); srs_error_t on_video(SrsRtpPacket2* pkt);
srs_error_t on_video_frame(SrsRtpPacket2* frame); srs_error_t on_video_frame(SrsRtpPacket2* frame);
srs_error_t on_rtcp_sr(char* buf, int nb_buf);
srs_error_t on_rtcp_xr(char* buf, int nb_buf);
srs_error_t on_rtcp_feedback(char* data, int nb_data);
srs_error_t on_rtcp_ps_feedback(char* data, int nb_data);
srs_error_t on_rtcp_rr(char* data, int nb_data);
public: public:
void request_keyframe(); void request_keyframe();
// interface ISrsHourGlass // interface ISrsHourGlass
@ -382,8 +394,8 @@ public:
// The peer address may change, we can identify that by STUN messages. // The peer address may change, we can identify that by STUN messages.
srs_error_t on_stun(SrsUdpMuxSocket* skt, SrsStunPacket* r); srs_error_t on_stun(SrsUdpMuxSocket* skt, SrsStunPacket* r);
srs_error_t on_dtls(char* data, int nb_data); srs_error_t on_dtls(char* data, int nb_data);
srs_error_t on_rtcp(char* data, int nb_data);
srs_error_t on_rtp(char* data, int nb_data); srs_error_t on_rtp(char* data, int nb_data);
srs_error_t on_rtcp(char* data, int nb_data);
public: public:
srs_error_t on_connection_established(); srs_error_t on_connection_established();
srs_error_t start_play(); srs_error_t start_play();
@ -395,11 +407,6 @@ public:
void simulate_nack_drop(int nn); void simulate_nack_drop(int nn);
private: private:
srs_error_t on_binding_request(SrsStunPacket* r); srs_error_t on_binding_request(SrsStunPacket* r);
srs_error_t on_rtcp_feedback(char* data, int nb_data);
srs_error_t on_rtcp_ps_feedback(char* data, int nb_data);
srs_error_t on_rtcp_xr(char* data, int nb_data);
srs_error_t on_rtcp_sender_report(char* data, int nb_data);
srs_error_t on_rtcp_receiver_report(char* data, int nb_data);
}; };
class SrsUdpMuxSender : virtual public ISrsUdpSender, virtual public ISrsCoroutineHandler, virtual public ISrsReloadHandler class SrsUdpMuxSender : virtual public ISrsUdpSender, virtual public ISrsCoroutineHandler, virtual public ISrsReloadHandler

View file

@ -226,9 +226,26 @@ void SrsRtpQueue::insert_into_nack_list(SrsRtpNackForReceiver* nack, uint16_t fi
nack->check_queue_size(); nack->check_queue_size();
} }
SrsRtpAudioPacket::SrsRtpAudioPacket()
{
pkt = NULL;
}
SrsRtpAudioPacket::~SrsRtpAudioPacket()
{
srs_freep(pkt);
}
SrsRtpPacket2* SrsRtpAudioPacket::detach()
{
SrsRtpPacket2* p = pkt;
pkt = NULL;
return p;
}
SrsRtpAudioQueue::SrsRtpAudioQueue(int capacity) SrsRtpAudioQueue::SrsRtpAudioQueue(int capacity)
{ {
queue_ = new SrsRtpRingBuffer<SrsRtpPacket2*>(capacity); queue_ = new SrsRtpRingBuffer<SrsRtpAudioPacket*>(capacity);
} }
SrsRtpAudioQueue::~SrsRtpAudioQueue() SrsRtpAudioQueue::~SrsRtpAudioQueue()
@ -287,7 +304,9 @@ srs_error_t SrsRtpAudioQueue::consume(SrsRtpNackForReceiver* nack, SrsRtpPacket2
} }
// Save packet at the position seq. // Save packet at the position seq.
queue_->set(seq, pkt); SrsRtpAudioPacket* apkt = new SrsRtpAudioPacket();
apkt->pkt = pkt;
queue_->set(seq, apkt);
return err; return err;
} }
@ -300,14 +319,14 @@ void SrsRtpAudioQueue::collect_frames(SrsRtpNackForReceiver* nack, vector<SrsRtp
// If nack disabled, we ignore any empty packet. // If nack disabled, we ignore any empty packet.
if (!nack) { if (!nack) {
for (; next != queue_->end; ++next) { for (; next != queue_->end; ++next) {
SrsRtpPacket2* pkt = queue_->at(next); SrsRtpAudioPacket* pkt = queue_->at(next);
if (pkt) { if (pkt) {
frames.push_back(pkt); frames.push_back(pkt->detach());
} }
} }
} else { } else {
for (; next != queue_->end; ++next) { for (; next != queue_->end; ++next) {
SrsRtpPacket2* pkt = queue_->at(next); SrsRtpAudioPacket* pkt = queue_->at(next);
// TODO: FIXME: Should not wait for NACK packets. // TODO: FIXME: Should not wait for NACK packets.
// Not found or in NACK, stop collecting frame. // Not found or in NACK, stop collecting frame.
@ -316,15 +335,12 @@ void SrsRtpAudioQueue::collect_frames(SrsRtpNackForReceiver* nack, vector<SrsRtp
break; break;
} }
frames.push_back(pkt); frames.push_back(pkt->detach());
} }
} }
// Reap packets from begin to next. // Reap packets from begin to next.
if (next != queue_->begin) { if (next != queue_->begin) {
// Reset the range of packets to NULL in buffer.
queue_->reset(queue_->begin, next);
srs_verbose("RTC collect audio [%u, %u, %u]", queue_->begin, next, queue_->end); srs_verbose("RTC collect audio [%u, %u, %u]", queue_->begin, next, queue_->end);
queue_->advance_to(next); queue_->advance_to(next);
} }
@ -562,9 +578,6 @@ void SrsRtpVideoQueue::collect_frame(SrsRtpNackForReceiver* nack, SrsRtpPacket2*
} }
if (next != queue_->begin) { if (next != queue_->begin) {
// Reset the range of packets to NULL in buffer.
queue_->reset(queue_->begin, next);
srs_verbose("RTC collect video [%u, %u, %u]", queue_->begin, next, queue_->end); srs_verbose("RTC collect video [%u, %u, %u]", queue_->begin, next, queue_->end);
queue_->advance_to(next); queue_->advance_to(next);
} }
@ -572,10 +585,6 @@ void SrsRtpVideoQueue::collect_frame(SrsRtpNackForReceiver* nack, SrsRtpPacket2*
// Merge packets to one packet. // Merge packets to one packet.
covert_frame(frame, ppkt); covert_frame(frame, ppkt);
for (int i = 0; i < (int)frame.size(); i++) {
SrsRtpVideoPacket* pkt = frame[i];
srs_freep(pkt);
}
return; return;
} }

View file

@ -173,12 +173,6 @@ public:
void remove(uint16_t at) { void remove(uint16_t at) {
set(at, NULL); set(at, NULL);
} }
// Directly reset range [first, last) to NULL.
void reset(uint16_t first, uint16_t last) {
for (uint16_t s = first; s != last; ++s) {
queue_[s % capacity_] = NULL;
}
}
// Whether queue overflow or heavy(too many packets and need clear). // Whether queue overflow or heavy(too many packets and need clear).
bool overflow() { bool overflow() {
return srs_rtp_seq_distance(begin, end) >= capacity_; return srs_rtp_seq_distance(begin, end) >= capacity_;
@ -254,10 +248,21 @@ protected:
void insert_into_nack_list(SrsRtpNackForReceiver* nack, uint16_t first, uint16_t last); void insert_into_nack_list(SrsRtpNackForReceiver* nack, uint16_t first, uint16_t last);
}; };
class SrsRtpAudioPacket
{
public:
SrsRtpPacket2* pkt;
public:
SrsRtpAudioPacket();
virtual ~SrsRtpAudioPacket();
public:
SrsRtpPacket2* detach();
};
class SrsRtpAudioQueue : public SrsRtpQueue class SrsRtpAudioQueue : public SrsRtpQueue
{ {
private: private:
SrsRtpRingBuffer<SrsRtpPacket2*>* queue_; SrsRtpRingBuffer<SrsRtpAudioPacket*>* queue_;
public: public:
SrsRtpAudioQueue(int capacity); SrsRtpAudioQueue(int capacity);
virtual ~SrsRtpAudioQueue(); virtual ~SrsRtpAudioQueue();