From 57e83562210430ef94fabdc4ea71cd05499924d5 Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 19 Oct 2014 19:42:27 +0800 Subject: [PATCH] fix #184, support AnnexB in RTMP body for HLS. 2.0.2 --- README.md | 5 +- trunk/src/app/srs_app_avc_aac.cpp | 343 +++++++++++++++++--------- trunk/src/app/srs_app_avc_aac.hpp | 16 ++ trunk/src/app/srs_app_utility.cpp | 34 ++- trunk/src/app/srs_app_utility.hpp | 10 + trunk/src/core/srs_core.hpp | 2 +- trunk/src/kernel/srs_kernel_error.hpp | 1 + 7 files changed, 291 insertions(+), 120 deletions(-) diff --git a/README.md b/README.md index 9db3cc4b0..eefee9a43 100755 --- a/README.md +++ b/README.md @@ -201,8 +201,9 @@ Supported operating systems and hardware: * 2013-10-17, Created.
## History -* v1.0, 2014-10-18, remove supports for OSX(darwin). 2.0.1. -* v1.0, 2014-10-16, revert github srs README to English. 2.0.0. +* v2.0, 2014-10-19, fix [#184](https://github.com/winlinvip/simple-rtmp-server/issues/184), support AnnexB in RTMP body for HLS. 2.0.2 +* v2.0, 2014-10-18, remove supports for OSX(darwin). 2.0.1. +* v2.0, 2014-10-16, revert github srs README to English. 2.0.0. * v1.0, 2014-10-09, [1.0 beta(1.0.0)](https://github.com/winlinvip/simple-rtmp-server/releases/tag/1.0.beta) released. 59316 lines. * v1.0, 2014-10-08, fix [#151](https://github.com/winlinvip/simple-rtmp-server/issues/151), always reap ts whatever audio or video packet. 0.9.223. * v1.0, 2014-10-08, fix [#162](https://github.com/winlinvip/simple-rtmp-server/issues/162), failed if no epoll. 0.9.222. diff --git a/trunk/src/app/srs_app_avc_aac.cpp b/trunk/src/app/srs_app_avc_aac.cpp index 752a5d9a5..4c0f2843e 100644 --- a/trunk/src/app/srs_app_avc_aac.cpp +++ b/trunk/src/app/srs_app_avc_aac.cpp @@ -27,6 +27,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include #include +#include SrsCodecSampleUnit::SrsCodecSampleUnit() { @@ -358,94 +359,9 @@ int SrsAvcAacCodec::video_avc_demux(char* data, int size, SrsCodecSample* sample sample->avc_packet_type = (SrsCodecVideoAVCType)avc_packet_type; if (avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader) { - // AVCDecoderConfigurationRecord - // 5.2.4.1.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 16 - avc_extra_size = stream->size() - stream->pos(); - if (avc_extra_size > 0) { - srs_freep(avc_extra_data); - avc_extra_data = new char[avc_extra_size]; - memcpy(avc_extra_data, stream->data() + stream->pos(), avc_extra_size); - } - - if (!stream->require(6)) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode video avc sequenc header failed. ret=%d", ret); + if ((ret = avc_demux_sps_pps(stream)) != ERROR_SUCCESS) { return ret; } - //int8_t configurationVersion = stream->read_1bytes(); - stream->read_1bytes(); - //int8_t AVCProfileIndication = stream->read_1bytes(); - avc_profile = stream->read_1bytes(); - //int8_t profile_compatibility = stream->read_1bytes(); - stream->read_1bytes(); - //int8_t AVCLevelIndication = stream->read_1bytes(); - avc_level = stream->read_1bytes(); - - // parse the NALU size. - int8_t lengthSizeMinusOne = stream->read_1bytes(); - lengthSizeMinusOne &= 0x03; - NAL_unit_length = lengthSizeMinusOne; - - // 1 sps - if (!stream->require(1)) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode video avc sequenc header sps failed. ret=%d", ret); - return ret; - } - int8_t numOfSequenceParameterSets = stream->read_1bytes(); - numOfSequenceParameterSets &= 0x1f; - if (numOfSequenceParameterSets != 1) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode video avc sequenc header sps failed. ret=%d", ret); - return ret; - } - if (!stream->require(2)) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode video avc sequenc header sps size failed. ret=%d", ret); - return ret; - } - sequenceParameterSetLength = stream->read_2bytes(); - if (!stream->require(sequenceParameterSetLength)) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode video avc sequenc header sps data failed. ret=%d", ret); - return ret; - } - if (sequenceParameterSetLength > 0) { - srs_freep(sequenceParameterSetNALUnit); - sequenceParameterSetNALUnit = new char[sequenceParameterSetLength]; - memcpy(sequenceParameterSetNALUnit, stream->data() + stream->pos(), sequenceParameterSetLength); - stream->skip(sequenceParameterSetLength); - } - // 1 pps - if (!stream->require(1)) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode video avc sequenc header pps failed. ret=%d", ret); - return ret; - } - int8_t numOfPictureParameterSets = stream->read_1bytes(); - numOfPictureParameterSets &= 0x1f; - if (numOfPictureParameterSets != 1) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode video avc sequenc header pps failed. ret=%d", ret); - return ret; - } - if (!stream->require(2)) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode video avc sequenc header pps size failed. ret=%d", ret); - return ret; - } - pictureParameterSetLength = stream->read_2bytes(); - if (!stream->require(pictureParameterSetLength)) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode video avc sequenc header pps data failed. ret=%d", ret); - return ret; - } - if (pictureParameterSetLength > 0) { - srs_freep(pictureParameterSetNALUnit); - pictureParameterSetNALUnit = new char[pictureParameterSetLength]; - memcpy(pictureParameterSetNALUnit, stream->data() + stream->pos(), pictureParameterSetLength); - stream->skip(pictureParameterSetLength); - } } else if (avc_packet_type == SrsCodecVideoAVCTypeNALU){ // ensure the sequence header demuxed if (avc_extra_size <= 0 || !avc_extra_data) { @@ -455,38 +371,18 @@ int SrsAvcAacCodec::video_avc_demux(char* data, int size, SrsCodecSample* sample } // One or more NALUs (Full frames are required) - // 5.3.4.2.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 20 - int PictureLength = stream->size() - stream->pos(); - for (int i = 0; i < PictureLength;) { - if (!stream->require(NAL_unit_length + 1)) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode video avc NALU size failed. ret=%d", ret); + // 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; } - int32_t NALUnitLength = 0; - if (NAL_unit_length == 3) { - NALUnitLength = stream->read_4bytes(); - } else if (NAL_unit_length == 2) { - NALUnitLength = stream->read_3bytes(); - } else if (NAL_unit_length == 1) { - NALUnitLength = stream->read_2bytes(); - } else { - NALUnitLength = stream->read_1bytes(); - } - // NALUnit - if (!stream->require(NALUnitLength)) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode video avc NALU data failed. ret=%d", ret); - return ret; - } - // 7.3.1 NAL unit syntax, H.264-AVC-ISO_IEC_14496-10.pdf, page 44. - if ((ret = sample->add_sample_unit(stream->data() + stream->pos(), NALUnitLength)) != ERROR_SUCCESS) { - srs_error("hls add video sample failed. ret=%d", ret); - return ret; - } - stream->skip(NALUnitLength); - i += NAL_unit_length + 1 + NALUnitLength; + // 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 { // ignored. @@ -498,3 +394,220 @@ int SrsAvcAacCodec::video_avc_demux(char* data, int size, SrsCodecSample* sample return ret; } +int SrsAvcAacCodec::avc_demux_sps_pps(SrsStream* stream) +{ + int ret = ERROR_SUCCESS; + + // AVCDecoderConfigurationRecord + // 5.2.4.1.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 16 + avc_extra_size = stream->size() - stream->pos(); + if (avc_extra_size > 0) { + srs_freep(avc_extra_data); + avc_extra_data = new char[avc_extra_size]; + memcpy(avc_extra_data, stream->data() + stream->pos(), avc_extra_size); + } + + if (!stream->require(6)) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode video avc sequenc header failed. ret=%d", ret); + return ret; + } + //int8_t configurationVersion = stream->read_1bytes(); + stream->read_1bytes(); + //int8_t AVCProfileIndication = stream->read_1bytes(); + avc_profile = stream->read_1bytes(); + //int8_t profile_compatibility = stream->read_1bytes(); + stream->read_1bytes(); + //int8_t AVCLevelIndication = stream->read_1bytes(); + avc_level = stream->read_1bytes(); + + // parse the NALU size. + int8_t lengthSizeMinusOne = stream->read_1bytes(); + lengthSizeMinusOne &= 0x03; + NAL_unit_length = lengthSizeMinusOne; + + // 5.3.4.2.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 16 + // 5.2.4.1 AVC decoder configuration record + // 5.2.4.1.2 Semantics + // The value of this field shall be one of 0, 1, or 3 corresponding to a + // length encoded with 1, 2, or 4 bytes, respectively. + if (NAL_unit_length == 2) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("sps lengthSizeMinusOne should never be 2. ret=%d", ret); + return ret; + } + + // 1 sps + if (!stream->require(1)) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode video avc sequenc header sps failed. ret=%d", ret); + return ret; + } + int8_t numOfSequenceParameterSets = stream->read_1bytes(); + numOfSequenceParameterSets &= 0x1f; + if (numOfSequenceParameterSets != 1) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode video avc sequenc header sps failed. ret=%d", ret); + return ret; + } + if (!stream->require(2)) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode video avc sequenc header sps size failed. ret=%d", ret); + return ret; + } + sequenceParameterSetLength = stream->read_2bytes(); + if (!stream->require(sequenceParameterSetLength)) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode video avc sequenc header sps data failed. ret=%d", ret); + return ret; + } + if (sequenceParameterSetLength > 0) { + srs_freep(sequenceParameterSetNALUnit); + sequenceParameterSetNALUnit = new char[sequenceParameterSetLength]; + memcpy(sequenceParameterSetNALUnit, stream->data() + stream->pos(), sequenceParameterSetLength); + stream->skip(sequenceParameterSetLength); + } + // 1 pps + if (!stream->require(1)) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode video avc sequenc header pps failed. ret=%d", ret); + return ret; + } + int8_t numOfPictureParameterSets = stream->read_1bytes(); + numOfPictureParameterSets &= 0x1f; + if (numOfPictureParameterSets != 1) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode video avc sequenc header pps failed. ret=%d", ret); + return ret; + } + if (!stream->require(2)) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode video avc sequenc header pps size failed. ret=%d", ret); + return ret; + } + pictureParameterSetLength = stream->read_2bytes(); + if (!stream->require(pictureParameterSetLength)) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode video avc sequenc header pps data failed. ret=%d", ret); + return ret; + } + if (pictureParameterSetLength > 0) { + srs_freep(pictureParameterSetNALUnit); + pictureParameterSetNALUnit = new char[pictureParameterSetLength]; + memcpy(pictureParameterSetNALUnit, stream->data() + stream->pos(), pictureParameterSetLength); + stream->skip(pictureParameterSetLength); + } + + return ret; +} + +int SrsAvcAacCodec::avc_demux_annexb_format(SrsStream* stream, SrsCodecSample* sample) +{ + int ret = ERROR_SUCCESS; + + // not annexb, try others + if (!srs_avc_startswith_annexb(stream, NULL)) { + return ERROR_HLS_AVC_TRY_OTHERS; + } + + // AnnexB + // B.1.1 Byte stream NAL unit syntax, + // H.264-AVC-ISO_IEC_14496-10.pdf, page 211. + while (!stream->empty()) { + // find start code + int nb_start_code = 0; + if (!srs_avc_startswith_annexb(stream, &nb_start_code)) { + return ret; + } + + // skip the start code. + if (nb_start_code > 0) { + stream->skip(nb_start_code); + } + + // the NALU start bytes. + char* p = stream->data() + stream->pos(); + + // get the last matched NALU + while (!stream->empty()) { + if (srs_avc_startswith_annexb(stream, &nb_start_code)) { + break; + } + + stream->skip(1); + } + + char* pp = stream->data() + stream->pos(); + + // skip the empty. + if (pp - p <= 0) { + continue; + } + + // got the NALU. + if ((ret = sample->add_sample_unit(p, pp - p)) != ERROR_SUCCESS) { + srs_error("annexb add video sample failed. ret=%d", ret); + return ret; + } + } + + return ret; +} + +int SrsAvcAacCodec::avc_demux_ibmf_format(SrsStream* stream, SrsCodecSample* sample) +{ + int ret = ERROR_SUCCESS; + + int PictureLength = stream->size() - stream->pos(); + + // 5.3.4.2.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 16 + // 5.2.4.1 AVC decoder configuration record + // 5.2.4.1.2 Semantics + // The value of this field shall be one of 0, 1, or 3 corresponding to a + // length encoded with 1, 2, or 4 bytes, respectively. + srs_assert(NAL_unit_length != 2); + + // 5.3.4.2.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 20 + for (int i = 0; i < PictureLength;) { + // unsigned int((NAL_unit_length+1)*8) NALUnitLength; + if (!stream->require(NAL_unit_length + 1)) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode video avc NALU size failed. ret=%d", ret); + return ret; + } + int32_t NALUnitLength = 0; + if (NAL_unit_length == 3) { + NALUnitLength = stream->read_4bytes(); + } else if (NAL_unit_length == 1) { + NALUnitLength = stream->read_2bytes(); + } else { + NALUnitLength = stream->read_1bytes(); + } + + // maybe stream is invalid format. + // see: https://github.com/winlinvip/simple-rtmp-server/issues/183 + if (NALUnitLength < 0) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("maybe stream is AnnexB format. ret=%d", ret); + return ret; + } + + // NALUnit + if (!stream->require(NALUnitLength)) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode video avc NALU data failed. ret=%d", ret); + return ret; + } + // 7.3.1 NAL unit syntax, H.264-AVC-ISO_IEC_14496-10.pdf, page 44. + if ((ret = sample->add_sample_unit(stream->data() + stream->pos(), NALUnitLength)) != ERROR_SUCCESS) { + srs_error("hls add video sample failed. ret=%d", ret); + return ret; + } + stream->skip(NALUnitLength); + + i += NAL_unit_length + 1 + NALUnitLength; + } + + return ret; +} + diff --git a/trunk/src/app/srs_app_avc_aac.hpp b/trunk/src/app/srs_app_avc_aac.hpp index 1e0e42fe1..96b13e6f4 100644 --- a/trunk/src/app/srs_app_avc_aac.hpp +++ b/trunk/src/app/srs_app_avc_aac.hpp @@ -278,6 +278,22 @@ public: * demux the h.264 NALUs to sampe units. */ virtual int video_avc_demux(char* data, int size, SrsCodecSample* sample); +private: + /** + * when avc packet type is SrsCodecVideoAVCTypeSequenceHeader, + * decode the sps and pps. + */ + virtual int avc_demux_sps_pps(SrsStream* stream); + /** + * demux the avc NALU in "AnnexB" + * from H.264-AVC-ISO_IEC_14496-10.pdf, page 211. + */ + virtual int avc_demux_annexb_format(SrsStream* stream, SrsCodecSample* sample); + /** + * demux the avc NALU in "ISO Base Media File Format" + * from H.264-AVC-ISO_IEC_14496-15.pdf, page 20 + */ + virtual int avc_demux_ibmf_format(SrsStream* stream, SrsCodecSample* sample); }; #endif diff --git a/trunk/src/app/srs_app_utility.cpp b/trunk/src/app/srs_app_utility.cpp index b4d910f9e..c11716e75 100644 --- a/trunk/src/app/srs_app_utility.cpp +++ b/trunk/src/app/srs_app_utility.cpp @@ -36,8 +36,9 @@ using namespace std; #include #include #include +#include -int srs_socket_connect(std::string server, int port, int64_t timeout, st_netfd_t* pstfd) +int srs_socket_connect(string server, int port, int64_t timeout, st_netfd_t* pstfd) { int ret = ERROR_SUCCESS; @@ -89,7 +90,7 @@ failed: return ret; } -int srs_get_log_level(std::string level) +int srs_get_log_level(string level) { if ("verbose" == level) { return SrsLogLevel::Verbose; @@ -106,6 +107,35 @@ int srs_get_log_level(std::string level) } } +bool srs_avc_startswith_annexb(SrsStream* stream, int* pnb_start_code) +{ + char* bytes = stream->data() + stream->pos(); + char* p = bytes; + + for (;;) { + if (!stream->require(p - bytes + 3)) { + return false; + } + + // not match + if (p[0] != 0x00 || p[1] != 0x00) { + return false; + } + + // match N[00] 00 00 01, where N>=0 + if (p[2] == 0x01) { + if (pnb_start_code) { + *pnb_start_code = (int)(p - bytes) + 3; + } + return true; + } + + p++; + } + + return false; +} + static SrsRusage _srs_system_rusage; SrsRusage::SrsRusage() diff --git a/trunk/src/app/srs_app_utility.hpp b/trunk/src/app/srs_app_utility.hpp index cd05b5959..a310483b6 100644 --- a/trunk/src/app/srs_app_utility.hpp +++ b/trunk/src/app/srs_app_utility.hpp @@ -39,6 +39,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include class SrsKbps; +class SrsStream; // client open socket and connect to server. extern int srs_socket_connect(std::string server, int port, int64_t timeout, st_netfd_t* pstfd); @@ -49,6 +50,15 @@ extern int srs_socket_connect(std::string server, int port, int64_t timeout, st_ */ extern int srs_get_log_level(std::string level); +/** +* whether stream starts with the avc NALU in "AnnexB" +* from H.264-AVC-ISO_IEC_14496-10.pdf, page 211. +* start code must be "N[00] 00 00 01" where N>=0 +* @param pnb_start_code output the size of start code, must >=3. +* NULL to ignore. +*/ +extern bool srs_avc_startswith_annexb(SrsStream* stream, int* pnb_start_code = NULL); + // current process resouce usage. // @see: man getrusage class SrsRusage diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp index 47f56b103..0a50dc91a 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 "1" +#define VERSION_REVISION "2" #define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION // server info. #define RTMP_SIG_SRS_KEY "SRS" diff --git a/trunk/src/kernel/srs_kernel_error.hpp b/trunk/src/kernel/srs_kernel_error.hpp index 27218bcac..4eb2f3426 100644 --- a/trunk/src/kernel/srs_kernel_error.hpp +++ b/trunk/src/kernel/srs_kernel_error.hpp @@ -183,6 +183,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define ERROR_KERNEL_FLV_STREAM_CLOSED 3037 #define ERROR_KERNEL_STREAM_INIT 3038 #define ERROR_EDGE_VHOST_REMOVED 3039 +#define ERROR_HLS_AVC_TRY_OTHERS 3040 /** * whether the error code is an system control error.