diff --git a/trunk/src/app/srs_app_hls.cpp b/trunk/src/app/srs_app_hls.cpp index 83326fd6c..221f6a2fe 100644 --- a/trunk/src/app/srs_app_hls.cpp +++ b/trunk/src/app/srs_app_hls.cpp @@ -1070,11 +1070,6 @@ int SrsHlsCache::write_video(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t // a. wait keyframe and got keyframe. // b. always reap when not wait keyframe. if (!muxer->wait_keyframe() || sample->frame_type == SrsCodecVideoAVCFrameKeyFrame) { - // when wait keyframe, there must exists idr frame in sample, or NonIDR(open gop) specified. - if (!sample->open_gop && !sample->has_idr && muxer->wait_keyframe()) { - srs_warn("hls: ts starts without IDR, first nalu=%d, idr=%d", sample->first_nalu_type, sample->has_idr); - } - // reap the segment, which will also flush the video. if ((ret = reap_segment("video", muxer, cache->video->dts)) != ERROR_SUCCESS) { return ret; @@ -1274,8 +1269,6 @@ void SrsHls::on_unpublish() srs_error("ignore m3u8 muxer flush/close audio failed. ret=%d", ret); } - sample->reset(); - hls_enabled = false; } diff --git a/trunk/src/kernel/srs_kernel_codec.cpp b/trunk/src/kernel/srs_kernel_codec.cpp index a1537a32b..42d577204 100644 --- a/trunk/src/kernel/srs_kernel_codec.cpp +++ b/trunk/src/kernel/srs_kernel_codec.cpp @@ -324,20 +324,13 @@ SrsCodecSampleUnit::~SrsCodecSampleUnit() SrsCodecSample::SrsCodecSample() { - reset(); + clear(); } SrsCodecSample::~SrsCodecSample() { } -void SrsCodecSample::reset() -{ - clear(); - - open_gop = false; -} - void SrsCodecSample::clear() { is_video = false; @@ -346,7 +339,7 @@ void SrsCodecSample::clear() cts = 0; frame_type = SrsCodecVideoAVCFrameReserved; avc_packet_type = SrsCodecVideoAVCTypeReserved; - has_aud = has_idr = false; + has_sps_pps = has_aud = has_idr = false; first_nalu_type = SrsAvcNaluTypeReserved; acodec = SrsCodecAudioReserved1; @@ -377,6 +370,8 @@ int SrsCodecSample::add_sample_unit(char* bytes, int size) if (nal_unit_type == SrsAvcNaluTypeIDR) { has_idr = true; + } else if (nal_unit_type == SrsAvcNaluTypeSPS || nal_unit_type == SrsAvcNaluTypePPS) { + has_sps_pps = true; } else if (nal_unit_type == SrsAvcNaluTypeAccessUnitDelimiter) { has_aud = true; } @@ -773,11 +768,6 @@ int SrsAvcAacCodec::video_nalu_demux(SrsStream* stream, SrsCodecSample* sample) srs_info("hls decode avc payload in annexb format."); } - // for keyframe, but not IDR, it's open gop. - if (sample->frame_type == SrsCodecVideoAVCFrameKeyFrame && !sample->has_idr) { - sample->open_gop = true; - } - return ret; } diff --git a/trunk/src/kernel/srs_kernel_codec.hpp b/trunk/src/kernel/srs_kernel_codec.hpp index 450bfc77b..e64c635de 100644 --- a/trunk/src/kernel/srs_kernel_codec.hpp +++ b/trunk/src/kernel/srs_kernel_codec.hpp @@ -387,12 +387,10 @@ public: bool has_idr; // Whether exists AUD NALU. bool has_aud; + // Whether exists SPS/PPS NALU. + bool has_sps_pps; // The first nalu type. SrsAvcNaluType first_nalu_type; -public: - // Whether stream is open gop, which means the keyframe is not IDR but NonIDR. - // @remark we will identify whether stream is open-gop util reset. - bool open_gop; public: // audio specified SrsCodecAudio acodec; @@ -405,8 +403,6 @@ public: SrsCodecSample(); virtual ~SrsCodecSample(); public: - // Reset the sample, clear the sample-base and stream-base data. - void reset(); /** * clear all samples. * the sample units never copy the bytes, it directly use the ptr, diff --git a/trunk/src/kernel/srs_kernel_ts.cpp b/trunk/src/kernel/srs_kernel_ts.cpp index 969949a03..8335fc2ac 100644 --- a/trunk/src/kernel/srs_kernel_ts.cpp +++ b/trunk/src/kernel/srs_kernel_ts.cpp @@ -2927,10 +2927,8 @@ int SrsTsCache::do_cache_aac(SrsAvcAacCodec* codec, SrsCodecSample* sample) return ret; } -int SrsTsCache::do_cache_avc(SrsAvcAacCodec* codec, SrsCodecSample* sample) +void srs_avc_insert_aud(SrsSimpleBuffer* payload, bool& aud_inserted) { - int ret = ERROR_SUCCESS; - // mux the samples in annexb format, // H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 324. /** @@ -2977,84 +2975,56 @@ int SrsTsCache::do_cache_avc(SrsAvcAacCodec* codec, SrsCodecSample* sample) static u_int8_t fresh_nalu_header[] = { 0x00, 0x00, 0x00, 0x01 }; static u_int8_t cont_nalu_header[] = { 0x00, 0x00, 0x01 }; - // the aud(access unit delimiter) before each frame. - // 7.3.2.4 Access unit delimiter RBSP syntax - // H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 66. - // - // primary_pic_type u(3), the first 3bits, primary_pic_type indicates that the slice_type values - // for all slices of the primary coded picture are members of the set listed in Table 7-5 for - // the given value of primary_pic_type. - // 0, slice_type 2, 7 - // 1, slice_type 0, 2, 5, 7 - // 2, slice_type 0, 1, 2, 5, 6, 7 - // 3, slice_type 4, 9 - // 4, slice_type 3, 4, 8, 9 - // 5, slice_type 2, 4, 7, 9 - // 6, slice_type 0, 2, 3, 4, 5, 7, 8, 9 - // 7, slice_type 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 - // 7.4.2.4 Access unit delimiter RBSP semantics - // H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 102. - // - // slice_type specifies the coding type of the slice according to Table 7-6. - // 0, P (P slice) - // 1, B (B slice) - // 2, I (I slice) - // 3, SP (SP slice) - // 4, SI (SI slice) - // 5, P (P slice) - // 6, B (B slice) - // 7, I (I slice) - // 8, SP (SP slice) - // 9, SI (SI slice) - // H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 105. - static u_int8_t aud_nalu_7[] = { 0x09, 0xf0}; - - // For NonIDR(open gop), we directly appends all frames. - if (sample->open_gop) { - for (int i = 0; i < sample->nb_sample_units; i++) { - SrsCodecSampleUnit* sample_unit = &sample->sample_units[i]; - int32_t size = sample_unit->size; - - if (!sample_unit->bytes || size <= 0) { - ret = ERROR_HLS_AVC_SAMPLE_SIZE; - srs_error("invalid avc sample length=%d, ret=%d", size, ret); - return ret; - } - - // insert nalu header before rbsp. - if (i == 0) { - video->payload->append((const char*)fresh_nalu_header, 4); - } else { - video->payload->append((const char*)cont_nalu_header, 3); - } - - // sample data - video->payload->append(sample_unit->bytes, sample_unit->size); - } - - return ret; + if (!aud_inserted) { + aud_inserted = true; + payload->append((const char*)fresh_nalu_header, 4); + } else { + payload->append((const char*)cont_nalu_header, 3); } +} + +int SrsTsCache::do_cache_avc(SrsAvcAacCodec* codec, SrsCodecSample* sample) +{ + int ret = ERROR_SUCCESS; - // always append a aud nalu for each frame. - video->payload->append((const char*)fresh_nalu_header, 4); - video->payload->append((const char*)aud_nalu_7, 2); + // Whether aud inserted. + bool aud_inserted = false; - // when ts message(samples) contains IDR, insert sps+pps. - if (sample->has_idr) { - // fresh nalu header before sps. - if (codec->sequenceParameterSetLength > 0) { - // AnnexB prefix, for sps always 4 bytes header - video->payload->append((const char*)fresh_nalu_header, 4); - // sps - video->payload->append(codec->sequenceParameterSetNALUnit, codec->sequenceParameterSetLength); - } - // cont nalu header before pps. - if (codec->pictureParameterSetLength > 0) { - // AnnexB prefix, for pps always 3 bytes header - video->payload->append((const char*)cont_nalu_header, 3); - // pps - video->payload->append(codec->pictureParameterSetNALUnit, codec->pictureParameterSetLength); - } + // Insert a default AUD NALU when no AUD in samples. + if (!sample->has_aud) { + // the aud(access unit delimiter) before each frame. + // 7.3.2.4 Access unit delimiter RBSP syntax + // H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 66. + // + // primary_pic_type u(3), the first 3bits, primary_pic_type indicates that the slice_type values + // for all slices of the primary coded picture are members of the set listed in Table 7-5 for + // the given value of primary_pic_type. + // 0, slice_type 2, 7 + // 1, slice_type 0, 2, 5, 7 + // 2, slice_type 0, 1, 2, 5, 6, 7 + // 3, slice_type 4, 9 + // 4, slice_type 3, 4, 8, 9 + // 5, slice_type 2, 4, 7, 9 + // 6, slice_type 0, 2, 3, 4, 5, 7, 8, 9 + // 7, slice_type 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 + // 7.4.2.4 Access unit delimiter RBSP semantics + // H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 102. + // + // slice_type specifies the coding type of the slice according to Table 7-6. + // 0, P (P slice) + // 1, B (B slice) + // 2, I (I slice) + // 3, SP (SP slice) + // 4, SI (SI slice) + // 5, P (P slice) + // 6, B (B slice) + // 7, I (I slice) + // 8, SP (SP slice) + // 9, SI (SI slice) + // H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 105. + static u_int8_t default_aud_nalu[] = { 0x09, 0xf0}; + srs_avc_insert_aud(video->payload, aud_inserted); + video->payload->append((const char*)default_aud_nalu, 2); } // all sample use cont nalu header, except the sps-pps before IDR frame. @@ -3072,20 +3042,21 @@ int SrsTsCache::do_cache_avc(SrsAvcAacCodec* codec, SrsCodecSample* sample) // H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 83. SrsAvcNaluType nal_unit_type = (SrsAvcNaluType)(sample_unit->bytes[0] & 0x1f); - // ignore SPS/PPS/AUD - switch (nal_unit_type) { - case SrsAvcNaluTypeSPS: - case SrsAvcNaluTypePPS: - case SrsAvcNaluTypeAccessUnitDelimiter: - continue; - default: - break; + // Insert sps/pps before IDR when there is no sps/pps in samples. + // The sps/pps is parsed from sequence header(generally the first flv packet). + if (nal_unit_type == SrsAvcNaluTypeIDR && !sample->has_sps_pps) { + if (codec->sequenceParameterSetLength > 0) { + srs_avc_insert_aud(video->payload, aud_inserted); + video->payload->append(codec->sequenceParameterSetNALUnit, codec->sequenceParameterSetLength); + } + if (codec->pictureParameterSetLength > 0) { + srs_avc_insert_aud(video->payload, aud_inserted); + video->payload->append(codec->pictureParameterSetNALUnit, codec->pictureParameterSetLength); + } } - // insert cont nalu header before frame. - video->payload->append((const char*)cont_nalu_header, 3); - - // sample data + // Insert the NALU to video in annexb. + srs_avc_insert_aud(video->payload, aud_inserted); video->payload->append(sample_unit->bytes, sample_unit->size); } @@ -3132,8 +3103,6 @@ int SrsTsEncoder::initialize(SrsFileWriter* fw) return ret; } - sample->reset(); - return ret; }