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:
parent
9614af070c
commit
26bcc09017
4 changed files with 547 additions and 468 deletions
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue