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.