diff --git a/trunk/src/app/srs_app_hls.cpp b/trunk/src/app/srs_app_hls.cpp index af30d4809f..83326fd6c1 100644 --- a/trunk/src/app/srs_app_hls.cpp +++ b/trunk/src/app/srs_app_hls.cpp @@ -1071,7 +1071,7 @@ int SrsHlsCache::write_video(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t // 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->has_non_idr && !sample->has_idr && muxer->wait_keyframe()) { + 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); } @@ -1274,6 +1274,8 @@ 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 f0e05ced14..a1537a32be 100644 --- a/trunk/src/kernel/srs_kernel_codec.cpp +++ b/trunk/src/kernel/srs_kernel_codec.cpp @@ -324,13 +324,20 @@ SrsCodecSampleUnit::~SrsCodecSampleUnit() SrsCodecSample::SrsCodecSample() { - clear(); + reset(); } SrsCodecSample::~SrsCodecSample() { } +void SrsCodecSample::reset() +{ + clear(); + + open_gop = false; +} + void SrsCodecSample::clear() { is_video = false; @@ -339,7 +346,7 @@ void SrsCodecSample::clear() cts = 0; frame_type = SrsCodecVideoAVCFrameReserved; avc_packet_type = SrsCodecVideoAVCTypeReserved; - has_aud = has_sei = has_non_idr = has_idr = false; + has_aud = has_idr = false; first_nalu_type = SrsAvcNaluTypeReserved; acodec = SrsCodecAudioReserved1; @@ -370,10 +377,6 @@ int SrsCodecSample::add_sample_unit(char* bytes, int size) if (nal_unit_type == SrsAvcNaluTypeIDR) { has_idr = true; - } else if (nal_unit_type == SrsAvcNaluTypeNonIDR) { - has_non_idr = true; - } else if (nal_unit_type == SrsAvcNaluTypeSEI) { - has_sei = true; } else if (nal_unit_type == SrsAvcNaluTypeAccessUnitDelimiter) { has_aud = true; } @@ -698,66 +701,82 @@ int SrsAvcAacCodec::video_avc_demux(char* data, int size, SrsCodecSample* sample return ret; } } else if (avc_packet_type == SrsCodecVideoAVCTypeNALU){ - // ensure the sequence header demuxed - if (!is_avc_codec_ok()) { - srs_warn("avc ignore type=%d for no sequence header. ret=%d", avc_packet_type, ret); + if ((ret = video_nalu_demux(stream, sample)) != ERROR_SUCCESS) { return ret; } + } else { + // ignored. + } + + srs_info("avc decoded, type=%d, codec=%d, avc=%d, cts=%d, size=%d", + frame_type, video_codec_id, avc_packet_type, composition_time, size); + + return ret; +} - // guess for the first time. - if (payload_format == SrsAvcPayloadFormatGuess) { - // One or more NALUs (Full frames are required) - // try "AnnexB" from H.264-AVC-ISO_IEC_14496-10.pdf, page 211. - if ((ret = avc_demux_annexb_format(stream, sample)) != ERROR_SUCCESS) { - // stop try when system error. - if (ret != ERROR_HLS_AVC_TRY_OTHERS) { - srs_error("avc demux for annexb failed. ret=%d", ret); - return ret; - } - - // try "ISO Base Media File Format" from H.264-AVC-ISO_IEC_14496-15.pdf, page 20 - if ((ret = avc_demux_ibmf_format(stream, sample)) != ERROR_SUCCESS) { - return ret; - } else { - payload_format = SrsAvcPayloadFormatIbmf; - srs_info("hls guess avc payload is ibmf format."); - } - } else { - payload_format = SrsAvcPayloadFormatAnnexb; - srs_info("hls guess avc payload is annexb format."); +int SrsAvcAacCodec::video_nalu_demux(SrsStream* stream, SrsCodecSample* sample) +{ + int ret = ERROR_SUCCESS; + + // ensure the sequence header demuxed + if (!is_avc_codec_ok()) { + srs_warn("avc ignore type=%d for no sequence header. ret=%d", SrsCodecVideoAVCTypeNALU, ret); + return ret; + } + + // guess for the first time. + if (payload_format == SrsAvcPayloadFormatGuess) { + // One or more NALUs (Full frames are required) + // try "AnnexB" from H.264-AVC-ISO_IEC_14496-10.pdf, page 211. + if ((ret = avc_demux_annexb_format(stream, sample)) != ERROR_SUCCESS) { + // stop try when system error. + if (ret != ERROR_HLS_AVC_TRY_OTHERS) { + srs_error("avc demux for annexb failed. ret=%d", ret); + return ret; } - } else if (payload_format == SrsAvcPayloadFormatIbmf) { + // try "ISO Base Media File Format" from H.264-AVC-ISO_IEC_14496-15.pdf, page 20 if ((ret = avc_demux_ibmf_format(stream, sample)) != ERROR_SUCCESS) { return ret; + } else { + payload_format = SrsAvcPayloadFormatIbmf; + srs_info("hls guess avc payload is ibmf format."); } - srs_info("hls decode avc payload in ibmf format."); } else { - // One or more NALUs (Full frames are required) - // try "AnnexB" from H.264-AVC-ISO_IEC_14496-10.pdf, page 211. - if ((ret = avc_demux_annexb_format(stream, sample)) != ERROR_SUCCESS) { - // ok, we guess out the payload is annexb, but maybe changed to ibmf. - if (ret != ERROR_HLS_AVC_TRY_OTHERS) { - srs_error("avc demux for annexb failed. ret=%d", ret); - return ret; - } - - // try "ISO Base Media File Format" from H.264-AVC-ISO_IEC_14496-15.pdf, page 20 - if ((ret = avc_demux_ibmf_format(stream, sample)) != ERROR_SUCCESS) { - return ret; - } else { - payload_format = SrsAvcPayloadFormatIbmf; - srs_warn("hls avc payload change from annexb to ibmf format."); - } - } - srs_info("hls decode avc payload in annexb format."); + payload_format = SrsAvcPayloadFormatAnnexb; + srs_info("hls guess avc payload is annexb format."); } + } else if (payload_format == SrsAvcPayloadFormatIbmf) { + // try "ISO Base Media File Format" from H.264-AVC-ISO_IEC_14496-15.pdf, page 20 + if ((ret = avc_demux_ibmf_format(stream, sample)) != ERROR_SUCCESS) { + return ret; + } + srs_info("hls decode avc payload in ibmf format."); } else { - // ignored. + // One or more NALUs (Full frames are required) + // try "AnnexB" from H.264-AVC-ISO_IEC_14496-10.pdf, page 211. + if ((ret = avc_demux_annexb_format(stream, sample)) != ERROR_SUCCESS) { + // ok, we guess out the payload is annexb, but maybe changed to ibmf. + if (ret != ERROR_HLS_AVC_TRY_OTHERS) { + srs_error("avc demux for annexb failed. ret=%d", ret); + return ret; + } + + // try "ISO Base Media File Format" from H.264-AVC-ISO_IEC_14496-15.pdf, page 20 + if ((ret = avc_demux_ibmf_format(stream, sample)) != ERROR_SUCCESS) { + return ret; + } else { + payload_format = SrsAvcPayloadFormatIbmf; + srs_warn("hls avc payload change from annexb to ibmf format."); + } + } + srs_info("hls decode avc payload in annexb format."); } - srs_info("avc decoded, type=%d, codec=%d, avc=%d, cts=%d, size=%d", - frame_type, video_codec_id, avc_packet_type, composition_time, size); + // 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 362196af55..450bfc77b7 100644 --- a/trunk/src/kernel/srs_kernel_codec.hpp +++ b/trunk/src/kernel/srs_kernel_codec.hpp @@ -385,14 +385,14 @@ class SrsCodecSample SrsCodecVideoAVCType avc_packet_type; // whether sample_units contains IDR frame. bool has_idr; - // Whether exists NonIDR NALU. - bool has_non_idr; - // Whether exists SEI NALU. - bool has_sei; // Whether exists AUD NALU. bool has_aud; // 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,6 +405,8 @@ class SrsCodecSample 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, @@ -637,6 +639,8 @@ class SrsAvcAacCodec * demux the h.264 NALUs to sampe units. */ virtual int video_avc_demux(char* data, int size, SrsCodecSample* sample); +private: + virtual int video_nalu_demux(SrsStream* stream, SrsCodecSample* sample); public: /** * directly demux the sequence header, without RTMP packet header. diff --git a/trunk/src/kernel/srs_kernel_ts.cpp b/trunk/src/kernel/srs_kernel_ts.cpp index d0ac1e4953..969949a032 100644 --- a/trunk/src/kernel/srs_kernel_ts.cpp +++ b/trunk/src/kernel/srs_kernel_ts.cpp @@ -3010,7 +3010,7 @@ int SrsTsCache::do_cache_avc(SrsAvcAacCodec* codec, SrsCodecSample* sample) static u_int8_t aud_nalu_7[] = { 0x09, 0xf0}; // For NonIDR(open gop), we directly appends all frames. - if (sample->has_non_idr || (sample->has_aud && sample->has_sei)) { + 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; @@ -3132,6 +3132,8 @@ int SrsTsEncoder::initialize(SrsFileWriter* fw) return ret; } + sample->reset(); + return ret; }