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);