From 8982c87e132b1caaca275af512afc4d983894778 Mon Sep 17 00:00:00 2001 From: "Michael.Ma" Date: Wed, 24 Jan 2018 15:13:03 +0800 Subject: [PATCH] fix hevc hls msg error PPS id out of range: 0 Invalid NAL unit 4, skipping --- trunk/src/kernel/srs_kernel_codec.cpp | 47 ++++++++++++++++++------- trunk/src/kernel/srs_kernel_codec.hpp | 50 +++++++++++++++++++++++++++ trunk/src/kernel/srs_kernel_ts.cpp | 23 +++++++----- 3 files changed, 100 insertions(+), 20 deletions(-) diff --git a/trunk/src/kernel/srs_kernel_codec.cpp b/trunk/src/kernel/srs_kernel_codec.cpp index ef27b6bb181..ead8d8d210d 100644 --- a/trunk/src/kernel/srs_kernel_codec.cpp +++ b/trunk/src/kernel/srs_kernel_codec.cpp @@ -369,6 +369,7 @@ SrsCodecSample::~SrsCodecSample() void SrsCodecSample::clear() { is_video = false; + is_hevc = false; nb_sample_units = 0; cts = 0; @@ -401,19 +402,40 @@ int SrsCodecSample::add_sample_unit(char* bytes, int size) // for video, parse the nalu type, set the IDR flag. if (is_video) { - SrsAvcNaluType nal_unit_type = (SrsAvcNaluType)(bytes[0] & 0x1f); + if (is_hevc) + { + SrsHevcNaluType nal_unit_type = (SrsHevcNaluType)((bytes[0] & 0x7e) >> 1); + + if (nal_unit_type == HEVC_NAL_IDR_W_RADL || nal_unit_type == HEVC_NAL_IDR_N_LP) { + has_idr = true; + } else if (nal_unit_type == HEVC_NAL_VPS || nal_unit_type == HEVC_NAL_SPS || nal_unit_type == HEVC_NAL_PPS) { + has_sps_pps = true; + } else if (nal_unit_type == HEVC_NAL_AUD) { + has_aud = true; + } + + // fix me. useless code? + /*if (first_nalu_type == SrsAvcNaluTypeReserved) { + first_nalu_type = nal_unit_type; + }*/ + } + else + { + SrsAvcNaluType nal_unit_type = (SrsAvcNaluType)(bytes[0] & 0x1f); + + 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; + } + + if (first_nalu_type == SrsAvcNaluTypeReserved) { + first_nalu_type = nal_unit_type; + } + } - 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; - } - - if (first_nalu_type == SrsAvcNaluTypeReserved) { - first_nalu_type = nal_unit_type; - } } return ret; @@ -701,6 +723,7 @@ int SrsAvcAacCodec::video_avc_demux(char* data, int size, SrsCodecSample* sample frame_type = (frame_type >> 4) & 0x0f; sample->frame_type = (SrsCodecVideoAVCFrame)frame_type; + sample->is_hevc = (codec_id == SrsCodecVideoHEVC); // ignore info frame without error, // @see https://github.com/ossrs/srs/issues/288#issuecomment-69863909 diff --git a/trunk/src/kernel/srs_kernel_codec.hpp b/trunk/src/kernel/srs_kernel_codec.hpp index 926192b46ca..6247c3145dd 100644 --- a/trunk/src/kernel/srs_kernel_codec.hpp +++ b/trunk/src/kernel/srs_kernel_codec.hpp @@ -331,6 +331,52 @@ enum SrsAvcNaluType }; std::string srs_codec_avc_nalu2str(SrsAvcNaluType nalu_type); +enum SrsHevcNaluType +{ + HEVC_NAL_TRAIL_N = 0, + HEVC_NAL_TRAIL_R = 1, + HEVC_NAL_TSA_N = 2, + HEVC_NAL_TSA_R = 3, + HEVC_NAL_STSA_N = 4, + HEVC_NAL_STSA_R = 5, + HEVC_NAL_RADL_N = 6, + HEVC_NAL_RADL_R = 7, + HEVC_NAL_RASL_N = 8, + HEVC_NAL_RASL_R = 9, + HEVC_NAL_VCL_N10 = 10, + HEVC_NAL_VCL_R11 = 11, + HEVC_NAL_VCL_N12 = 12, + HEVC_NAL_VCL_R13 = 13, + HEVC_NAL_VCL_N14 = 14, + HEVC_NAL_VCL_R15 = 15, + HEVC_NAL_BLA_W_LP = 16, + HEVC_NAL_BLA_W_RADL = 17, + HEVC_NAL_BLA_N_LP = 18, + HEVC_NAL_IDR_W_RADL = 19, + HEVC_NAL_IDR_N_LP = 20, + HEVC_NAL_CRA_NUT = 21, + HEVC_NAL_IRAP_VCL22 = 22, + HEVC_NAL_IRAP_VCL23 = 23, + HEVC_NAL_RSV_VCL24 = 24, + HEVC_NAL_RSV_VCL25 = 25, + HEVC_NAL_RSV_VCL26 = 26, + HEVC_NAL_RSV_VCL27 = 27, + HEVC_NAL_RSV_VCL28 = 28, + HEVC_NAL_RSV_VCL29 = 29, + HEVC_NAL_RSV_VCL30 = 30, + HEVC_NAL_RSV_VCL31 = 31, + HEVC_NAL_VPS = 32, + HEVC_NAL_SPS = 33, + HEVC_NAL_PPS = 34, + HEVC_NAL_AUD = 35, + HEVC_NAL_EOS_NUT = 36, + HEVC_NAL_EOB_NUT = 37, + HEVC_NAL_FD_NUT = 38, + HEVC_NAL_SEI_PREFIX = 39, + HEVC_NAL_SEI_SUFFIX = 40, +}; + + /** * the codec sample unit. * for h.264 video packet, a NALU is a sample unit. @@ -381,6 +427,10 @@ class SrsCodecSample * whether the sample is video sample which demux from video packet. */ bool is_video; + /** + * whether the sample is hevc video sample. + */ + bool is_hevc; /** * CompositionTime, video_file_format_spec_v10_1.pdf, page 78. * cts = pts - dts, where dts = flvheader->timestamp. diff --git a/trunk/src/kernel/srs_kernel_ts.cpp b/trunk/src/kernel/srs_kernel_ts.cpp index 25cbb4761ba..d5caa6fe1c1 100644 --- a/trunk/src/kernel/srs_kernel_ts.cpp +++ b/trunk/src/kernel/srs_kernel_ts.cpp @@ -3018,7 +3018,7 @@ int SrsTsCache::do_cache_avc(SrsAvcAacCodec* codec, SrsCodecSample* sample) bool aud_inserted = false; // Insert a default AUD NALU when no AUD in samples. - if (!sample->has_aud) { + if (!sample->has_aud && (SrsCodecVideo)codec->video_codec_id == SrsCodecVideoAVC) { // 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. @@ -3088,13 +3088,14 @@ int SrsTsCache::do_cache_avc(SrsAvcAacCodec* codec, SrsCodecSample* sample) } else if (codec->video_codec_id == SrsCodecVideoHEVC) { - // 5bits, 7.3.1 NAL unit syntax, - // H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 83. - SrsAvcNaluType nal_unit_type = (SrsAvcNaluType)((sample_unit->bytes[0] & 0x7e) >> 1); + SrsHevcNaluType nal_unit_type = (SrsHevcNaluType)((sample_unit->bytes[0] & 0x7e) >> 1); - // 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 >= 16 && nal_unit_type <= 21 && !sample->has_sps_pps && !is_sps_pps_appended) { + // Insert vps/sps/pps before IDR when there is no vps/sps/pps in samples. + // The vps/sps/pps is parsed from sequence header(generally the first flv packet). + //if (nal_unit_type >= 16 && nal_unit_type <= 21 && !sample->has_sps_pps && !is_sps_pps_appended) { + if ((nal_unit_type == HEVC_NAL_IDR_W_RADL || nal_unit_type == HEVC_NAL_IDR_N_LP) && + !sample->has_sps_pps && !is_sps_pps_appended) + { if (codec->videoParameterSetLength > 0) { srs_avc_insert_aud(video->payload, aud_inserted); video->payload->append(codec->videoParameterSetNALUnit, codec->videoParameterSetLength); @@ -3232,7 +3233,13 @@ int SrsTsEncoder::write_video(int64_t timestamp, char* data, int size) if (codec->video_codec_id != SrsCodecVideoAVC && codec->video_codec_id != SrsCodecVideoHEVC) { return ret; } - + + // when codec changed, write new header. + if ((ret = muxer->update_vcodec(vcodec)) != ERROR_SUCCESS) { + srs_error("http: ts video write header failed. ret=%d", ret); + return ret; + } + // ignore sequence header if (sample->frame_type == SrsCodecVideoAVCFrameKeyFrame && sample->avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader) {