diff --git a/README.md b/README.md index 509f6d416..5edaaf6d5 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 [#204](https://github.com/winlinvip/simple-rtmp-server/issues/204), srs-librtmp drop dupliated sps/pps(sequence header). 2.0.22. * 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. diff --git a/trunk/research/librtmp/srs_h264_raw_publish.c b/trunk/research/librtmp/srs_h264_raw_publish.c index 0cbbe76d1..da8b9a483 100644 --- a/trunk/research/librtmp/srs_h264_raw_publish.c +++ b/trunk/research/librtmp/srs_h264_raw_publish.c @@ -170,6 +170,10 @@ int main(int argc, char** argv) if (error != 0) { if (srs_h264_is_dvbsp_error(error)) { srs_lib_trace("ignore drop video error, code=%d", error); + } else if (srs_h264_is_duplicated_sps_error(error)) { + srs_lib_trace("ignore duplicated sps, code=%d", error); + } else if (srs_h264_is_duplicated_pps_error(error)) { + srs_lib_trace("ignore duplicated pps, code=%d", error); } else { srs_lib_trace("send h264 raw data failed."); goto rtmp_destroy; diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp index 32e907eb0..e9c377957 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 21 +#define VERSION_REVISION 22 // 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 ac51890b6..f76f8129a 100644 --- a/trunk/src/kernel/srs_kernel_error.hpp +++ b/trunk/src/kernel/srs_kernel_error.hpp @@ -187,6 +187,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define ERROR_H264_API_NO_PREFIXED 3041 #define ERROR_FLV_INVALID_VIDEO_TAG 3042 #define ERROR_H264_DROP_BEFORE_SPS_PPS 3043 +#define ERROR_H264_DUPLICATED_SPS 3044 +#define ERROR_H264_DUPLICATED_PPS 3045 /** * 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 0fb7afc2e..e2d3f80da 100644 --- a/trunk/src/libs/srs_librtmp.cpp +++ b/trunk/src/libs/srs_librtmp.cpp @@ -79,12 +79,18 @@ struct Context // whether the sps and pps sent, // @see https://github.com/winlinvip/simple-rtmp-server/issues/203 bool h264_sps_pps_sent; + // only send the ssp and pps when both changed. + // @see https://github.com/winlinvip/simple-rtmp-server/issues/204 + bool h264_sps_changed; + bool h264_pps_changed; Context() { rtmp = NULL; skt = NULL; stream_id = 0; h264_sps_pps_sent = false; + h264_sps_changed = false; + h264_pps_changed = false; } virtual ~Context() { srs_freep(rtmp); @@ -1127,8 +1133,8 @@ int __srs_write_h264_sps_pps(Context* context, u_int32_t dts, u_int32_t pts) { int ret = ERROR_SUCCESS; - // when pps or sps not ready, ignore. - if (context->h264_pps.empty() || context->h264_sps.empty()) { + // only send when both sps and pps changed. + if (!context->h264_sps_changed || !context->h264_pps_changed) { return ret; } @@ -1207,8 +1213,8 @@ 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_changed = false; + context->h264_pps_changed = false; context->h264_sps_pps_sent = true; // TODO: FIXME: for more profile. @@ -1307,13 +1313,26 @@ int __srs_write_h264_raw_frame(Context* context, return ret; } - context->h264_sps = ""; - context->h264_sps.append(frame, frame_size); + std::string sps; + sps.append(frame, frame_size); + + if (context->h264_sps == sps) { + return ERROR_H264_DUPLICATED_SPS; + } + context->h264_sps_changed = true; + context->h264_sps = sps; return __srs_write_h264_sps_pps(context, dts, pts); } else if (nal_unit_type == 8) { - context->h264_pps = ""; - context->h264_pps.append(frame, frame_size); + + std::string pps; + pps.append(frame, frame_size); + + if (context->h264_pps == pps) { + return ERROR_H264_DUPLICATED_PPS; + } + context->h264_pps_changed = true; + context->h264_pps = pps; return __srs_write_h264_sps_pps(context, dts, pts); } else { @@ -1341,6 +1360,11 @@ int srs_h264_write_raw_frames(srs_rtmp_t rtmp, return ret; } + // use the last error + // @see https://github.com/winlinvip/simple-rtmp-server/issues/203 + // @see https://github.com/winlinvip/simple-rtmp-server/issues/204 + int error_code_return = ret; + // send each frame. while (!context->h264_raw_stream.empty()) { // each frame must prefixed by annexb format. @@ -1363,12 +1387,24 @@ int srs_h264_write_raw_frames(srs_rtmp_t rtmp, // send out the frame. char* frame = context->h264_raw_stream.data() + start; + + // it may be return error, but we must process all packets. if ((ret = __srs_write_h264_raw_frame(context, frame, size, dts, pts)) != ERROR_SUCCESS) { + error_code_return = ret; + + // ignore known error, process all packets. + if (srs_h264_is_dvbsp_error(ret) + || srs_h264_is_duplicated_sps_error(ret) + || srs_h264_is_duplicated_pps_error(ret) + ) { + continue; + } + return ret; } } - return ret; + return error_code_return; } srs_h264_bool srs_h264_is_dvbsp_error(int error_code) @@ -1376,6 +1412,16 @@ srs_h264_bool srs_h264_is_dvbsp_error(int error_code) return error_code == ERROR_H264_DROP_BEFORE_SPS_PPS; } +srs_h264_bool srs_h264_is_duplicated_sps_error(int error_code) +{ + return error_code == ERROR_H264_DUPLICATED_SPS; +} + +srs_h264_bool srs_h264_is_duplicated_pps_error(int error_code) +{ + return error_code == ERROR_H264_DUPLICATED_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 fdc903fa2..a72c270c1 100644 --- a/trunk/src/libs/srs_librtmp.hpp +++ b/trunk/src/libs/srs_librtmp.hpp @@ -445,7 +445,9 @@ typedef int srs_h264_bool; * @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 dvbsp error, @see srs_h264_is_dvbsp_error(). +* for duplictated sps error, @see srs_h264_is_duplicated_sps_error(). +* for duplictated pps error, @see srs_h264_is_duplicated_pps_error(). */ /** For the example file: @@ -491,6 +493,20 @@ extern int srs_h264_write_raw_frames(srs_rtmp_t rtmp, */ extern srs_h264_bool srs_h264_is_dvbsp_error(int error_code); /** +* whether error_code is duplicated sps error. +* +* @see https://github.com/winlinvip/simple-rtmp-server/issues/204 +* @example /trunk/research/librtmp/srs_h264_raw_publish.c +*/ +extern srs_h264_bool srs_h264_is_duplicated_sps_error(int error_code); +/** +* whether error_code is duplicated pps error. +* +* @see https://github.com/winlinvip/simple-rtmp-server/issues/204 +* @example /trunk/research/librtmp/srs_h264_raw_publish.c +*/ +extern srs_h264_bool srs_h264_is_duplicated_pps_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.