diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index d7d613db8..12f478b04 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1550,6 +1550,149 @@ void SrsRtcPlayer::simulate_drop_packet(SrsRtpHeader* h, int nn_bytes) 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) { report_timer = new SrsHourGlass(this, 200 * SRS_UTIME_MILLISECONDS); @@ -1620,209 +1763,56 @@ srs_error_t SrsRtcPublisher::initialize(uint32_t vssrc, uint32_t assrc, SrsReque return err; } -srs_error_t SrsRtcPublisher::on_rtcp_sender_report(char* buf, int nb_buf) +void SrsRtcPublisher::check_send_nacks(SrsRtpNackForReceiver* nack, uint32_t ssrc) { - 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); + // If DTLS is not OK, drop all messages. + if (!session_->dtls_) { + return; } - 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(); + // @see: https://tools.ietf.org/html/rfc4585#section-6.1 + vector nack_seqs; + nack->get_nack_seqs(nack_seqs); + vector::iterator iter = nack_seqs.begin(); + while (iter != nack_seqs.end()) { + char buf[kRtpPacketSize]; + SrsBuffer stream(buf, sizeof(buf)); + // FIXME: Replace magic number. + stream.write_1bytes(0x81); + stream.write_1bytes(kRtpFb); + stream.write_2bytes(3); + stream.write_4bytes(ssrc); // TODO: FIXME: Should be 1? + stream.write_4bytes(ssrc); // TODO: FIXME: Should be 0? + uint16_t pid = *iter; + uint16_t blp = 0; + while (iter + 1 != nack_seqs.end() && (*(iter + 1) - pid <= 15)) { + blp |= (1 << (*(iter + 1) - pid - 1)); + ++iter; + } - 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); - } + stream.write_2bytes(pid); + stream.write_2bytes(blp); - 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(); + if (session_->blackhole && session_->blackhole_addr && session_->blackhole_stfd) { + // Ignore any error for black-hole. + void* p = stream.data(); int len = stream.pos(); SrsRtcSession* s = session_; + srs_sendto(s->blackhole_stfd, p, len, (sockaddr*)s->blackhole_addr, sizeof(sockaddr_in), SRS_UTIME_NO_TIMEOUT); + } - (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); + char protected_buf[kRtpPacketSize]; + int nb_protected_buf = stream.pos(); - 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(); + // FIXME: Merge nack rtcp into one packets. + if (session_->dtls_->protect_rtcp(protected_buf, stream.data(), nb_protected_buf) == srs_success) { + // TODO: FIXME: Check error. + session_->sendonly_skt->sendto(protected_buf, nb_protected_buf, 0); + } - (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); + ++iter; } - - 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) -{ - // If DTLS is not OK, drop all messages. - if (!session_->dtls_) { - return; - } - - vector nack_seqs; - nack->get_nack_seqs(nack_seqs); - vector::iterator iter = nack_seqs.begin(); - while (iter != nack_seqs.end()) { - char buf[kRtpPacketSize]; - SrsBuffer stream(buf, sizeof(buf)); - // FIXME: Replace magic number. - stream.write_1bytes(0x81); - stream.write_1bytes(kRtpFb); - stream.write_2bytes(3); - stream.write_4bytes(ssrc); - stream.write_4bytes(ssrc); - uint16_t pid = *iter; - uint16_t blp = 0; - while (iter + 1 != nack_seqs.end() && (*(iter + 1) - pid <= 15)) { - blp |= (1 << (*(iter + 1) - pid - 1)); - ++iter; - } - - stream.write_2bytes(pid); - stream.write_2bytes(blp); - - if (session_->blackhole && session_->blackhole_addr && session_->blackhole_stfd) { - // Ignore any error for black-hole. - void* p = stream.data(); int len = stream.pos(); SrsRtcSession* s = session_; - srs_sendto(s->blackhole_stfd, p, len, (sockaddr*)s->blackhole_addr, sizeof(sockaddr_in), SRS_UTIME_NO_TIMEOUT); - } - - char protected_buf[kRtpPacketSize]; - int nb_protected_buf = stream.pos(); - - // FIXME: Merge nack rtcp into one packets. - if (session_->dtls_->protect_rtcp(protected_buf, stream.data(), nb_protected_buf) == srs_success) { - // TODO: FIXME: Check error. - session_->sendonly_skt->sendto(protected_buf, nb_protected_buf, 0); - } - - ++iter; - } -} - -srs_error_t SrsRtcPublisher::send_rtcp_rr(uint32_t ssrc, SrsRtpQueue* rtp_queue) +srs_error_t SrsRtcPublisher::send_rtcp_rr(uint32_t ssrc, SrsRtpQueue* rtp_queue) { srs_error_t err = srs_success; @@ -1831,12 +1821,13 @@ srs_error_t SrsRtcPublisher::send_rtcp_rr(uint32_t ssrc, SrsRtpQueue* rtp_queue) return err; } + // @see https://tools.ietf.org/html/rfc3550#section-6.4.2 char buf[kRtpPacketSize]; SrsBuffer stream(buf, sizeof(buf)); stream.write_1bytes(0x81); stream.write_1bytes(kRR); 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(); 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 err = srs_success; @@ -2233,18 +2289,295 @@ srs_error_t SrsRtcPublisher::on_video_frame(SrsRtpPacket2* frame) buf.write_1bytes(0x01); // Not-SequenceHeader. buf.write_3bytes(0x00); // CTS. - buf.write_4bytes(payload->nn_payload); // Size of NALU. - buf.write_bytes(payload->payload, payload->nn_payload); // NALU. + buf.write_4bytes(payload->nn_payload); // Size of NALU. + buf.write_bytes(payload->payload, payload->nn_payload); // NALU. + + SrsMessageHeader header; + header.message_type = RTMP_MSG_VideoMessage; + // TODO: FIXME: Maybe the tbn is not 90k. + header.timestamp = (timestamp / 90) & 0x3fffffff; + SrsCommonMessage* shared_video = new SrsCommonMessage(); + SrsAutoFree(SrsCommonMessage, shared_video); + // TODO: FIXME: Check error. + shared_video->create(&header, data, nn_payload); + 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); + } - SrsMessageHeader header; - header.message_type = RTMP_MSG_VideoMessage; - // TODO: FIXME: Maybe the tbn is not 90k. - header.timestamp = (timestamp / 90) & 0x3fffffff; - SrsCommonMessage* shared_video = new SrsCommonMessage(); - SrsAutoFree(SrsCommonMessage, shared_video); - // TODO: FIXME: Check error. - shared_video->create(&header, data, nn_payload); - return source->on_video(shared_video); + return err; } void SrsRtcPublisher::request_keyframe() @@ -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); } - char* ph = unprotected_buf; - int nb_left = 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 (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"); - } + if (player_) { + return player_->on_rtcp(unprotected_buf, nb_unprotected_buf); + } - ph += length; - nb_left -= length; + if (publisher_) { + return publisher_->on_rtcp(unprotected_buf, nb_unprotected_buf); } return err; @@ -2742,231 +3025,6 @@ srs_error_t SrsRtcSession::on_binding_request(SrsStunPacket* r) 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 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) { lfd = NULL; diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 2dbd1b0ad..88fc44908 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -267,6 +267,14 @@ public: void simulate_nack_drop(int nn); private: 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 @@ -298,8 +306,6 @@ public: virtual ~SrsRtcPublisher(); public: 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: void check_send_nacks(SrsRtpNackForReceiver* nack, uint32_t ssrc); srs_error_t send_rtcp_rr(uint32_t ssrc, SrsRtpQueue* rtp_queue); @@ -308,11 +314,17 @@ private: public: srs_error_t on_rtp(char* buf, int nb_buf); virtual void on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* buf, ISrsCodec** ppayload); + srs_error_t on_rtcp(char* data, int nb_data); private: srs_error_t on_audio(SrsRtpPacket2* pkt); srs_error_t on_audio_frame(SrsRtpPacket2* frame); srs_error_t on_video(SrsRtpPacket2* pkt); 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: void request_keyframe(); // interface ISrsHourGlass @@ -382,8 +394,8 @@ public: // 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_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_rtcp(char* data, int nb_data); public: srs_error_t on_connection_established(); srs_error_t start_play(); @@ -395,11 +407,6 @@ public: void simulate_nack_drop(int nn); private: 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 diff --git a/trunk/src/app/srs_app_rtp_queue.cpp b/trunk/src/app/srs_app_rtp_queue.cpp index eb2389760..700eabc92 100644 --- a/trunk/src/app/srs_app_rtp_queue.cpp +++ b/trunk/src/app/srs_app_rtp_queue.cpp @@ -226,9 +226,26 @@ void SrsRtpQueue::insert_into_nack_list(SrsRtpNackForReceiver* nack, uint16_t fi 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) { - queue_ = new SrsRtpRingBuffer(capacity); + queue_ = new SrsRtpRingBuffer(capacity); } SrsRtpAudioQueue::~SrsRtpAudioQueue() @@ -287,7 +304,9 @@ srs_error_t SrsRtpAudioQueue::consume(SrsRtpNackForReceiver* nack, SrsRtpPacket2 } // Save packet at the position seq. - queue_->set(seq, pkt); + SrsRtpAudioPacket* apkt = new SrsRtpAudioPacket(); + apkt->pkt = pkt; + queue_->set(seq, apkt); return err; } @@ -300,14 +319,14 @@ void SrsRtpAudioQueue::collect_frames(SrsRtpNackForReceiver* nack, vectorend; ++next) { - SrsRtpPacket2* pkt = queue_->at(next); + SrsRtpAudioPacket* pkt = queue_->at(next); if (pkt) { - frames.push_back(pkt); + frames.push_back(pkt->detach()); } } } else { for (; next != queue_->end; ++next) { - SrsRtpPacket2* pkt = queue_->at(next); + SrsRtpAudioPacket* pkt = queue_->at(next); // TODO: FIXME: Should not wait for NACK packets. // Not found or in NACK, stop collecting frame. @@ -316,15 +335,12 @@ void SrsRtpAudioQueue::collect_frames(SrsRtpNackForReceiver* nack, vectordetach()); } } // Reap packets from begin to next. 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); queue_->advance_to(next); } @@ -562,9 +578,6 @@ void SrsRtpVideoQueue::collect_frame(SrsRtpNackForReceiver* nack, SrsRtpPacket2* } 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); queue_->advance_to(next); } @@ -572,10 +585,6 @@ void SrsRtpVideoQueue::collect_frame(SrsRtpNackForReceiver* nack, SrsRtpPacket2* // Merge packets to one packet. covert_frame(frame, ppkt); - for (int i = 0; i < (int)frame.size(); i++) { - SrsRtpVideoPacket* pkt = frame[i]; - srs_freep(pkt); - } return; } diff --git a/trunk/src/app/srs_app_rtp_queue.hpp b/trunk/src/app/srs_app_rtp_queue.hpp index b8424f39f..85f9a7f79 100644 --- a/trunk/src/app/srs_app_rtp_queue.hpp +++ b/trunk/src/app/srs_app_rtp_queue.hpp @@ -173,12 +173,6 @@ public: void remove(uint16_t at) { 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). bool overflow() { 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); }; +class SrsRtpAudioPacket +{ +public: + SrsRtpPacket2* pkt; +public: + SrsRtpAudioPacket(); + virtual ~SrsRtpAudioPacket(); +public: + SrsRtpPacket2* detach(); +}; + class SrsRtpAudioQueue : public SrsRtpQueue { private: - SrsRtpRingBuffer* queue_; + SrsRtpRingBuffer* queue_; public: SrsRtpAudioQueue(int capacity); virtual ~SrsRtpAudioQueue();