From 278ff845d32a4d1063a8cf606074612219440f6b Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 15 Nov 2014 16:30:37 +0800 Subject: [PATCH] fix #203, srs-librtmp drop any video before sps/pps(sequence header). 2.0.21. --- README.md | 1 + trunk/research/librtmp/srs_h264_raw_publish.c | 11 +++++-- trunk/src/core/srs_core.hpp | 2 +- trunk/src/kernel/srs_kernel_error.hpp | 1 + trunk/src/libs/srs_librtmp.cpp | 18 ++++++++++- trunk/src/libs/srs_librtmp.hpp | 30 ++++++++++++++----- 6 files changed, 50 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 1449786ae..509f6d416 100755 --- a/README.md +++ b/README.md @@ -244,6 +244,7 @@ Supported operating systems and hardware: * 2013-10-17, Created.
## History +* v2.0, 2014-11-15, fix [#203](https://github.com/winlinvip/simple-rtmp-server/issues/203), srs-librtmp drop any video before sps/pps(sequence header). 2.0.21. * v2.0, 2014-11-15, fix [#202](https://github.com/winlinvip/simple-rtmp-server/issues/202), fix memory leak of h.264 raw packet send in srs-librtmp. 2.0.20. * v2.0, 2014-11-13, fix [#200](https://github.com/winlinvip/simple-rtmp-server/issues/200), deadloop when read/write 0 and ETIME. 2.0.16. * v2.0, 2014-11-13, fix [#194](https://github.com/winlinvip/simple-rtmp-server/issues/194), writev multiple msgs, support 6k+ 250kbps clients. 2.0.15. diff --git a/trunk/research/librtmp/srs_h264_raw_publish.c b/trunk/research/librtmp/srs_h264_raw_publish.c index db16b9025..0cbbe76d1 100644 --- a/trunk/research/librtmp/srs_h264_raw_publish.c +++ b/trunk/research/librtmp/srs_h264_raw_publish.c @@ -166,9 +166,14 @@ int main(int argc, char** argv) } // send out the h264 packet over RTMP - if (srs_write_h264_raw_frames(rtmp, data, size, dts, pts) != 0) { - srs_lib_trace("send h264 raw data failed."); - goto rtmp_destroy; + int error = srs_h264_write_raw_frames(rtmp, data, size, dts, pts); + if (error != 0) { + if (srs_h264_is_dvbsp_error(error)) { + srs_lib_trace("ignore drop video error, code=%d", error); + } else { + srs_lib_trace("send h264 raw data failed."); + goto rtmp_destroy; + } } // 5bits, 7.3.1 NAL unit syntax, diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp index f610cfd92..32e907eb0 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 20 +#define VERSION_REVISION 21 // server info. #define RTMP_SIG_SRS_KEY "SRS" #define RTMP_SIG_SRS_ROLE "origin/edge server" diff --git a/trunk/src/kernel/srs_kernel_error.hpp b/trunk/src/kernel/srs_kernel_error.hpp index d9997c16c..ac51890b6 100644 --- a/trunk/src/kernel/srs_kernel_error.hpp +++ b/trunk/src/kernel/srs_kernel_error.hpp @@ -186,6 +186,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define ERROR_HLS_AVC_TRY_OTHERS 3040 #define ERROR_H264_API_NO_PREFIXED 3041 #define ERROR_FLV_INVALID_VIDEO_TAG 3042 +#define ERROR_H264_DROP_BEFORE_SPS_PPS 3043 /** * whether the error code is an system control error. diff --git a/trunk/src/libs/srs_librtmp.cpp b/trunk/src/libs/srs_librtmp.cpp index 64ba3aa8b..7e5c631da 100644 --- a/trunk/src/libs/srs_librtmp.cpp +++ b/trunk/src/libs/srs_librtmp.cpp @@ -76,11 +76,15 @@ struct Context // about SPS, @see: 7.3.2.1.1, H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 62 std::string h264_sps; std::string h264_pps; + // whether the sps and pps sent, + // @see https://github.com/winlinvip/simple-rtmp-server/issues/203 + bool h264_sps_pps_sent; Context() { rtmp = NULL; skt = NULL; stream_id = 0; + h264_sps_pps_sent = false; } virtual ~Context() { srs_freep(rtmp); @@ -1205,6 +1209,7 @@ int __srs_write_h264_sps_pps(Context* context, u_int32_t dts, u_int32_t pts) // reset sps and pps. context->h264_pps = ""; context->h264_sps = ""; + context->h264_sps_pps_sent = true; // TODO: FIXME: for more profile. // 5.3.4.2.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 16 @@ -1227,6 +1232,12 @@ int __srs_write_h264_ipb_frame(Context* context, ) { int ret = ERROR_SUCCESS; + // when sps or pps not sent, ignore the packet. + // @see https://github.com/winlinvip/simple-rtmp-server/issues/203 + if (!context->h264_sps_pps_sent) { + return ERROR_H264_DROP_BEFORE_SPS_PPS; + } + // 5bits, 7.3.1 NAL unit syntax, // H.264-AVC-ISO_IEC_14496-10.pdf, page 44. // 7: SPS, 8: PPS, 5: I Frame, 1: P Frame @@ -1315,7 +1326,7 @@ int __srs_write_h264_raw_frame(Context* context, /** * write h264 multiple frames, in annexb format. */ -int srs_write_h264_raw_frames(srs_rtmp_t rtmp, +int srs_h264_write_raw_frames(srs_rtmp_t rtmp, char* frames, int frames_size, u_int32_t dts, u_int32_t pts ) { int ret = ERROR_SUCCESS; @@ -1360,6 +1371,11 @@ int srs_write_h264_raw_frames(srs_rtmp_t rtmp, return ret; } +srs_h264_bool srs_h264_is_dvbsp_error(int error_code) +{ + return error_code == ERROR_H264_DROP_BEFORE_SPS_PPS; +} + int srs_h264_startswith_annexb(char* h264_raw_data, int h264_raw_size, int* pnb_start_code) { SrsStream stream; diff --git a/trunk/src/libs/srs_librtmp.hpp b/trunk/src/libs/srs_librtmp.hpp index e0d6fb9df..fdc903fa2 100644 --- a/trunk/src/libs/srs_librtmp.hpp +++ b/trunk/src/libs/srs_librtmp.hpp @@ -424,6 +424,7 @@ extern char* srs_amf0_human_print(srs_amf0_t amf0, char** pdata, int* psize); * h264 raw codec ************************************************************** *************************************************************/ +typedef int srs_h264_bool; /** * write h.264 raw frame over RTMP to rtmp server. * @param frames the input h264 raw data, encoded h.264 I/P/B frames data. @@ -441,8 +442,10 @@ extern char* srs_amf0_human_print(srs_amf0_t amf0, char** pdata, int* psize); * @remark, cts = pts - dts * @remark, use srs_h264_startswith_annexb to check whether frame is annexb format. * @example /trunk/research/librtmp/srs_h264_raw_publish.c +* @see https://github.com/winlinvip/simple-rtmp-server/issues/66 * * @return 0, success; otherswise, failed. +* for dvbsp error, check by srs_h264_is_dvbsp_error(error_code). */ /** For the example file: @@ -458,25 +461,36 @@ The data sequence is: 0000000141E02041F8CDDC562BBDEFAD2F..... User can send the SPS+PPS, then each frame: // SPS+PPS - srs_write_h264_raw_frame('000000016742802995A014016E400000000168CE3880', size, dts, pts) + srs_h264_write_raw_frames('000000016742802995A014016E400000000168CE3880', size, dts, pts) // IFrame - srs_write_h264_raw_frame('0000000165B8041014C038008B0D0D3A071......', size, dts, pts) + srs_h264_write_raw_frames('0000000165B8041014C038008B0D0D3A071......', size, dts, pts) // PFrame - srs_write_h264_raw_frame('0000000141E02041F8CDDC562BBDEFAD2F......', size, dts, pts) + srs_h264_write_raw_frames('0000000141E02041F8CDDC562BBDEFAD2F......', size, dts, pts) User also can send one by one: // SPS - srs_write_h264_raw_frame('000000016742802995A014016E4', size, dts, pts) + srs_h264_write_raw_frames('000000016742802995A014016E4', size, dts, pts) // PPS - srs_write_h264_raw_frame('00000000168CE3880', size, dts, pts) + srs_h264_write_raw_frames('00000000168CE3880', size, dts, pts) // IFrame - srs_write_h264_raw_frame('0000000165B8041014C038008B0D0D3A071......', size, dts, pts) + srs_h264_write_raw_frames('0000000165B8041014C038008B0D0D3A071......', size, dts, pts) // PFrame - srs_write_h264_raw_frame('0000000141E02041F8CDDC562BBDEFAD2F......', size, dts, pts) + srs_h264_write_raw_frames('0000000141E02041F8CDDC562BBDEFAD2F......', size, dts, pts) */ -extern int srs_write_h264_raw_frames(srs_rtmp_t rtmp, +extern int srs_h264_write_raw_frames(srs_rtmp_t rtmp, char* frames, int frames_size, u_int32_t dts, u_int32_t pts ); /** +* whether error_code is dvbsp(drop video before sps/pps/sequence-header) error. +* +* @see https://github.com/winlinvip/simple-rtmp-server/issues/203 +* @example /trunk/research/librtmp/srs_h264_raw_publish.c +* @remark why drop video? +* some encoder, for example, ipcamera, will send sps/pps before each IFrame, +* so, when error and reconnect the rtmp, the first video is not sps/pps(sequence header), +* this will cause SRS server to disable HLS. +*/ +extern srs_h264_bool srs_h264_is_dvbsp_error(int error_code); +/** * whether h264 raw data starts with the annexb, * which bytes sequence matches N[00] 00 00 01, where N>=0. * @param h264_raw_data the input h264 raw data, a encoded h.264 I/P/B frame data.