正在显示
5 个修改的文件
包含
44 行增加
和
3 行删除
| @@ -204,6 +204,7 @@ Please select your language: | @@ -204,6 +204,7 @@ Please select your language: | ||
| 204 | 204 | ||
| 205 | ### V2 changes | 205 | ### V2 changes |
| 206 | 206 | ||
| 207 | +* v2.0, 2017-01-10, fix [#635][bug #635], hls support NonIDR(open gop). 2.0.226 | ||
| 207 | * v2.0, 2017-01-06, for [#730][bug #730], reset ack follow flash player rules. 2.0.225 | 208 | * v2.0, 2017-01-06, for [#730][bug #730], reset ack follow flash player rules. 2.0.225 |
| 208 | * v2.0, 2016-12-15, for [#513][bug #513], remove hls ram from srs2 to srs3+. 2.0.224 | 209 | * v2.0, 2016-12-15, for [#513][bug #513], remove hls ram from srs2 to srs3+. 2.0.224 |
| 209 | * <strong>v2.0, 2016-12-13, [2.0 beta3(2.0.223)][r2.0b3] released. 86685 lines.</strong> | 210 | * <strong>v2.0, 2016-12-13, [2.0 beta3(2.0.223)][r2.0b3] released. 86685 lines.</strong> |
| @@ -1363,6 +1364,7 @@ Winlin | @@ -1363,6 +1364,7 @@ Winlin | ||
| 1363 | [bug #713]: https://github.com/ossrs/srs/issues/713 | 1364 | [bug #713]: https://github.com/ossrs/srs/issues/713 |
| 1364 | [bug #513]: https://github.com/ossrs/srs/issues/513 | 1365 | [bug #513]: https://github.com/ossrs/srs/issues/513 |
| 1365 | [bug #730]: https://github.com/ossrs/srs/issues/730 | 1366 | [bug #730]: https://github.com/ossrs/srs/issues/730 |
| 1367 | +[bug #635]: https://github.com/ossrs/srs/issues/635 | ||
| 1366 | [bug #xxxxxxxxxx]: https://github.com/ossrs/srs/issues/xxxxxxxxxx | 1368 | [bug #xxxxxxxxxx]: https://github.com/ossrs/srs/issues/xxxxxxxxxx |
| 1367 | 1369 | ||
| 1368 | [exo #828]: https://github.com/google/ExoPlayer/pull/828 | 1370 | [exo #828]: https://github.com/google/ExoPlayer/pull/828 |
| @@ -1070,8 +1070,8 @@ int SrsHlsCache::write_video(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t | @@ -1070,8 +1070,8 @@ int SrsHlsCache::write_video(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t | ||
| 1070 | // a. wait keyframe and got keyframe. | 1070 | // a. wait keyframe and got keyframe. |
| 1071 | // b. always reap when not wait keyframe. | 1071 | // b. always reap when not wait keyframe. |
| 1072 | if (!muxer->wait_keyframe() || sample->frame_type == SrsCodecVideoAVCFrameKeyFrame) { | 1072 | if (!muxer->wait_keyframe() || sample->frame_type == SrsCodecVideoAVCFrameKeyFrame) { |
| 1073 | - // when wait keyframe, there must exists idr frame in sample. | ||
| 1074 | - if (!sample->has_idr && muxer->wait_keyframe()) { | 1073 | + // when wait keyframe, there must exists idr frame in sample, or NonIDR(open gop) specified. |
| 1074 | + if (!sample->has_non_idr && !sample->has_idr && muxer->wait_keyframe()) { | ||
| 1075 | srs_warn("hls: ts starts without IDR, first nalu=%d, idr=%d", sample->first_nalu_type, sample->has_idr); | 1075 | srs_warn("hls: ts starts without IDR, first nalu=%d, idr=%d", sample->first_nalu_type, sample->has_idr); |
| 1076 | } | 1076 | } |
| 1077 | 1077 |
| @@ -339,7 +339,7 @@ void SrsCodecSample::clear() | @@ -339,7 +339,7 @@ void SrsCodecSample::clear() | ||
| 339 | cts = 0; | 339 | cts = 0; |
| 340 | frame_type = SrsCodecVideoAVCFrameReserved; | 340 | frame_type = SrsCodecVideoAVCFrameReserved; |
| 341 | avc_packet_type = SrsCodecVideoAVCTypeReserved; | 341 | avc_packet_type = SrsCodecVideoAVCTypeReserved; |
| 342 | - has_idr = false; | 342 | + has_aud = has_sei = has_non_idr = has_idr = false; |
| 343 | first_nalu_type = SrsAvcNaluTypeReserved; | 343 | first_nalu_type = SrsAvcNaluTypeReserved; |
| 344 | 344 | ||
| 345 | acodec = SrsCodecAudioReserved1; | 345 | acodec = SrsCodecAudioReserved1; |
| @@ -370,6 +370,12 @@ int SrsCodecSample::add_sample_unit(char* bytes, int size) | @@ -370,6 +370,12 @@ int SrsCodecSample::add_sample_unit(char* bytes, int size) | ||
| 370 | 370 | ||
| 371 | if (nal_unit_type == SrsAvcNaluTypeIDR) { | 371 | if (nal_unit_type == SrsAvcNaluTypeIDR) { |
| 372 | has_idr = true; | 372 | has_idr = true; |
| 373 | + } else if (nal_unit_type == SrsAvcNaluTypeNonIDR) { | ||
| 374 | + has_non_idr = true; | ||
| 375 | + } else if (nal_unit_type == SrsAvcNaluTypeSEI) { | ||
| 376 | + has_sei = true; | ||
| 377 | + } else if (nal_unit_type == SrsAvcNaluTypeAccessUnitDelimiter) { | ||
| 378 | + has_aud = true; | ||
| 373 | } | 379 | } |
| 374 | 380 | ||
| 375 | if (first_nalu_type == SrsAvcNaluTypeReserved) { | 381 | if (first_nalu_type == SrsAvcNaluTypeReserved) { |
| @@ -385,6 +385,13 @@ public: | @@ -385,6 +385,13 @@ public: | ||
| 385 | SrsCodecVideoAVCType avc_packet_type; | 385 | SrsCodecVideoAVCType avc_packet_type; |
| 386 | // whether sample_units contains IDR frame. | 386 | // whether sample_units contains IDR frame. |
| 387 | bool has_idr; | 387 | bool has_idr; |
| 388 | + // Whether exists NonIDR NALU. | ||
| 389 | + bool has_non_idr; | ||
| 390 | + // Whether exists SEI NALU. | ||
| 391 | + bool has_sei; | ||
| 392 | + // Whether exists AUD NALU. | ||
| 393 | + bool has_aud; | ||
| 394 | + // The first nalu type. | ||
| 388 | SrsAvcNaluType first_nalu_type; | 395 | SrsAvcNaluType first_nalu_type; |
| 389 | public: | 396 | public: |
| 390 | // audio specified | 397 | // audio specified |
| @@ -3021,6 +3021,32 @@ int SrsTsCache::do_cache_avc(SrsAvcAacCodec* codec, SrsCodecSample* sample) | @@ -3021,6 +3021,32 @@ int SrsTsCache::do_cache_avc(SrsAvcAacCodec* codec, SrsCodecSample* sample) | ||
| 3021 | // H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 105. | 3021 | // H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 105. |
| 3022 | static u_int8_t aud_nalu_7[] = { 0x09, 0xf0}; | 3022 | static u_int8_t aud_nalu_7[] = { 0x09, 0xf0}; |
| 3023 | 3023 | ||
| 3024 | + // For NonIDR(open gop), we directly appends all frames. | ||
| 3025 | + if (sample->has_non_idr || (sample->has_aud && sample->has_sei)) { | ||
| 3026 | + for (int i = 0; i < sample->nb_sample_units; i++) { | ||
| 3027 | + SrsCodecSampleUnit* sample_unit = &sample->sample_units[i]; | ||
| 3028 | + int32_t size = sample_unit->size; | ||
| 3029 | + | ||
| 3030 | + if (!sample_unit->bytes || size <= 0) { | ||
| 3031 | + ret = ERROR_HLS_AVC_SAMPLE_SIZE; | ||
| 3032 | + srs_error("invalid avc sample length=%d, ret=%d", size, ret); | ||
| 3033 | + return ret; | ||
| 3034 | + } | ||
| 3035 | + | ||
| 3036 | + // insert nalu header before rbsp. | ||
| 3037 | + if (i == 0) { | ||
| 3038 | + video->payload->append((const char*)fresh_nalu_header, 4); | ||
| 3039 | + } else { | ||
| 3040 | + video->payload->append((const char*)cont_nalu_header, 3); | ||
| 3041 | + } | ||
| 3042 | + | ||
| 3043 | + // sample data | ||
| 3044 | + video->payload->append(sample_unit->bytes, sample_unit->size); | ||
| 3045 | + } | ||
| 3046 | + | ||
| 3047 | + return ret; | ||
| 3048 | + } | ||
| 3049 | + | ||
| 3024 | // always append a aud nalu for each frame. | 3050 | // always append a aud nalu for each frame. |
| 3025 | video->payload->append((const char*)fresh_nalu_header, 4); | 3051 | video->payload->append((const char*)fresh_nalu_header, 4); |
| 3026 | video->payload->append((const char*)aud_nalu_7, 2); | 3052 | video->payload->append((const char*)aud_nalu_7, 2); |
-
请 注册 或 登录 后发表评论