From c9a71b7fb2f39240ce4cdc03860e3f4908fc05d8 Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 10 Jan 2017 11:14:20 +0800 Subject: [PATCH] fix #635, hls support NonIDR(open gop). 2.0.226 --- README.md | 2 ++ trunk/src/app/srs_app_hls.cpp | 4 ++-- trunk/src/core/srs_core.hpp | 2 +- trunk/src/kernel/srs_kernel_codec.cpp | 8 +++++++- trunk/src/kernel/srs_kernel_codec.hpp | 7 +++++++ trunk/src/kernel/srs_kernel_ts.cpp | 26 ++++++++++++++++++++++++++ 6 files changed, 45 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 64e346db0e..0c843ed602 100755 --- a/README.md +++ b/README.md @@ -345,6 +345,7 @@ Remark: ## History +* v2.0, 2017-01-10, fix [#635][bug #635], hls support NonIDR(open gop). 2.0.226 * v2.0, 2017-01-06, for [#730][bug #730], reset ack follow flash player rules. 2.0.225 * v2.0, 2016-12-15, for [#513][bug #513], remove hls ram from srs2 to srs3+. 2.0.224 * v2.0, 2016-12-13, [2.0 beta3(2.0.223)][r2.0b3] released. 86685 lines. @@ -1268,6 +1269,7 @@ Winlin [bug #713]: https://github.com/ossrs/srs/issues/713 [bug #513]: https://github.com/ossrs/srs/issues/513 [bug #730]: https://github.com/ossrs/srs/issues/730 +[bug #635]: https://github.com/ossrs/srs/issues/635 [bug #xxxxxxxxxx]: https://github.com/ossrs/srs/issues/xxxxxxxxxx [exo #828]: https://github.com/google/ExoPlayer/pull/828 diff --git a/trunk/src/app/srs_app_hls.cpp b/trunk/src/app/srs_app_hls.cpp index 70b764c32b..af30d4809f 100644 --- a/trunk/src/app/srs_app_hls.cpp +++ b/trunk/src/app/srs_app_hls.cpp @@ -1070,8 +1070,8 @@ 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. - if (!sample->has_idr && muxer->wait_keyframe()) { + // 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()) { srs_warn("hls: ts starts without IDR, first nalu=%d, idr=%d", sample->first_nalu_type, sample->has_idr); } diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp index 88f280a601..cb1d5aac68 100644 --- a/trunk/src/core/srs_core.hpp +++ b/trunk/src/core/srs_core.hpp @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // current release version #define VERSION_MAJOR 2 #define VERSION_MINOR 0 -#define VERSION_REVISION 225 +#define VERSION_REVISION 226 // generated by configure, only macros. #include diff --git a/trunk/src/kernel/srs_kernel_codec.cpp b/trunk/src/kernel/srs_kernel_codec.cpp index b5da5871ba..f0e05ced14 100644 --- a/trunk/src/kernel/srs_kernel_codec.cpp +++ b/trunk/src/kernel/srs_kernel_codec.cpp @@ -339,7 +339,7 @@ void SrsCodecSample::clear() cts = 0; frame_type = SrsCodecVideoAVCFrameReserved; avc_packet_type = SrsCodecVideoAVCTypeReserved; - has_idr = false; + has_aud = has_sei = has_non_idr = has_idr = false; first_nalu_type = SrsAvcNaluTypeReserved; acodec = SrsCodecAudioReserved1; @@ -370,6 +370,12 @@ 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; } if (first_nalu_type == SrsAvcNaluTypeReserved) { diff --git a/trunk/src/kernel/srs_kernel_codec.hpp b/trunk/src/kernel/srs_kernel_codec.hpp index 0de1ddaa1d..362196af55 100644 --- a/trunk/src/kernel/srs_kernel_codec.hpp +++ b/trunk/src/kernel/srs_kernel_codec.hpp @@ -385,6 +385,13 @@ 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: // audio specified diff --git a/trunk/src/kernel/srs_kernel_ts.cpp b/trunk/src/kernel/srs_kernel_ts.cpp index 0085480221..d0ac1e4953 100644 --- a/trunk/src/kernel/srs_kernel_ts.cpp +++ b/trunk/src/kernel/srs_kernel_ts.cpp @@ -3009,6 +3009,32 @@ int SrsTsCache::do_cache_avc(SrsAvcAacCodec* codec, SrsCodecSample* sample) // 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->has_non_idr || (sample->has_aud && sample->has_sei)) { + 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; + } + // 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);