From 719c0ae85b26cef60c6109a975d103f0346a0725 Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 11 Apr 2020 13:10:27 +0800 Subject: [PATCH] For #307, refactor SPS/PPS only before IDR, not each FUA --- trunk/src/app/srs_app_rtc.cpp | 34 ++++++++++++--------------- trunk/src/app/srs_app_sdp.cpp | 8 +++++++ trunk/src/kernel/srs_kernel_codec.cpp | 7 ++++++ trunk/src/kernel/srs_kernel_codec.hpp | 2 ++ 4 files changed, 32 insertions(+), 19 deletions(-) diff --git a/trunk/src/app/srs_app_rtc.cpp b/trunk/src/app/srs_app_rtc.cpp index e734e1e5e..c44d203df 100644 --- a/trunk/src/app/srs_app_rtc.cpp +++ b/trunk/src/app/srs_app_rtc.cpp @@ -115,16 +115,23 @@ srs_error_t SrsRtpH264Muxer::frame_to_packet(SrsSharedPtrMessage* shared_frame, vector rtp_packets; - for (int i = 0; i < format->video->nb_samples; ++i) { - SrsSample sample = format->video->samples[i]; + // Well, for each IDR, we append a SPS/PPS before it, which is packaged in STAP-A. + if (format->video && format->video->has_idr) { + if ((err = packet_stap_a(sps, pps, shared_frame, rtp_packets)) != srs_success) { + return srs_error_wrap(err, "packet stap-a"); + } + } - uint8_t header = sample.bytes[0]; + for (int i = 0; i < format->video->nb_samples; ++i) { + SrsSample* sample = &format->video->samples[i]; + + uint8_t header = sample->bytes[0]; uint8_t nal_type = header & kNalTypeMask; // Because RTC does not support B-frame, so we will drop them. // TODO: Drop B-frame in better way, which not cause picture corruption. if (discard_bframe && (nal_type == SrsAvcNaluTypeNonIDR || nal_type == SrsAvcNaluTypeDataPartitionA || nal_type == SrsAvcNaluTypeIDR)) { - SrsBuffer* stream = new SrsBuffer(sample.bytes, sample.size); + SrsBuffer* stream = new SrsBuffer(sample->bytes, sample->size); SrsAutoFree(SrsBuffer, stream); // Skip nalu header. @@ -147,12 +154,12 @@ srs_error_t SrsRtpH264Muxer::frame_to_packet(SrsSharedPtrMessage* shared_frame, } } - if (sample.size <= kRtpMaxPayloadSize) { - if ((err = packet_single_nalu(shared_frame, format, &sample, rtp_packets)) != srs_success) { + if (sample->size <= kRtpMaxPayloadSize) { + if ((err = packet_single_nalu(shared_frame, format, sample, rtp_packets)) != srs_success) { return srs_error_wrap(err, "packet single nalu"); } } else { - if ((err = packet_fu_a(shared_frame, format, &sample, rtp_packets)) != srs_success) { + if ((err = packet_fu_a(shared_frame, format, sample, rtp_packets)) != srs_success) { return srs_error_wrap(err, "packet fu-a"); } } @@ -180,12 +187,6 @@ srs_error_t SrsRtpH264Muxer::packet_fu_a(SrsSharedPtrMessage* shared_frame, SrsF uint8_t header = sample->bytes[0]; uint8_t nal_type = header & kNalTypeMask; - if (nal_type == SrsAvcNaluTypeIDR) { - if ((err = packet_stap_a(sps, pps, shared_frame, rtp_packets)) != srs_success) { - return srs_error_wrap(err, "packet stap-a"); - } - } - int num_of_packet = (sample->size - 1 + kRtpMaxPayloadSize) / kRtpMaxPayloadSize; for (int i = 0; i < num_of_packet; ++i) { char buf[kRtpPacketSize]; @@ -223,6 +224,7 @@ srs_error_t SrsRtpH264Muxer::packet_fu_a(SrsSharedPtrMessage* shared_frame, SrsF return err; } +// Single NAL Unit Packet @see https://tools.ietf.org/html/rfc6184#section-5.6 srs_error_t SrsRtpH264Muxer::packet_single_nalu(SrsSharedPtrMessage* shared_frame, SrsFormat* format, SrsSample* sample, vector& rtp_packets) { srs_error_t err = srs_success; @@ -230,12 +232,6 @@ srs_error_t SrsRtpH264Muxer::packet_single_nalu(SrsSharedPtrMessage* shared_fram uint8_t header = sample->bytes[0]; uint8_t nal_type = header & kNalTypeMask; - if (nal_type == SrsAvcNaluTypeIDR) { - if ((err = packet_stap_a(sps, pps, shared_frame, rtp_packets)) != srs_success) { - return srs_error_wrap(err, "packet stap-a"); - } - } - srs_verbose("rtp single nalu, size=%u, seq=%u, timestamp=%lu", sample->size, sequence, (shared_frame->timestamp * 90)); SrsRtpSharedPacket* packet = new SrsRtpSharedPacket(); diff --git a/trunk/src/app/srs_app_sdp.cpp b/trunk/src/app/srs_app_sdp.cpp index f5f4ee47f..c67dbd9a4 100644 --- a/trunk/src/app/srs_app_sdp.cpp +++ b/trunk/src/app/srs_app_sdp.cpp @@ -78,6 +78,14 @@ srs_error_t parse_h264_fmtp(const std::string& fmtp, H264SpecificParam& h264_par if (kv[0] == "profile-level-id") { h264_param.profile_level_id = kv[1]; } else if (kv[0] == "packetization-mode") { + // 6.3. Non-Interleaved Mode + // This mode is in use when the value of the OPTIONAL packetization-mode + // media type parameter is equal to 1. This mode SHOULD be supported. + // It is primarily intended for low-delay applications. Only single NAL + // unit packets, STAP-As, and FU-As MAY be used in this mode. STAP-Bs, + // MTAPs, and FU-Bs MUST NOT be used. The transmission order of NAL + // units MUST comply with the NAL unit decoding order. + // @see https://tools.ietf.org/html/rfc6184#section-6.3 h264_param.packetization_mode = kv[1]; } else if (kv[0] == "level-asymmetry-allowed") { h264_param.level_asymmerty_allow = kv[1]; diff --git a/trunk/src/kernel/srs_kernel_codec.cpp b/trunk/src/kernel/srs_kernel_codec.cpp index 2f6c14bff..8b4b8c41e 100644 --- a/trunk/src/kernel/srs_kernel_codec.cpp +++ b/trunk/src/kernel/srs_kernel_codec.cpp @@ -488,6 +488,13 @@ SrsVideoFrame::~SrsVideoFrame() { } +srs_error_t SrsVideoFrame::initialize(SrsCodecConfig* c) +{ + first_nalu_type = SrsAvcNaluTypeForbidden; + has_idr = has_sps_pps = has_aud = false; + return SrsFrame::initialize(c); +} + srs_error_t SrsVideoFrame::add_sample(char* bytes, int size) { srs_error_t err = srs_success; diff --git a/trunk/src/kernel/srs_kernel_codec.hpp b/trunk/src/kernel/srs_kernel_codec.hpp index c820cbeef..bffeee505 100644 --- a/trunk/src/kernel/srs_kernel_codec.hpp +++ b/trunk/src/kernel/srs_kernel_codec.hpp @@ -703,6 +703,8 @@ public: SrsVideoFrame(); virtual ~SrsVideoFrame(); public: + // Initialize the frame, to parse sampels. + virtual srs_error_t initialize(SrsCodecConfig* c); // Add the sample without ANNEXB or IBMF header, or RAW AAC or MP3 data. virtual srs_error_t add_sample(char* bytes, int size); public: