winlin

fix #204, srs-librtmp drop dupliated sps/pps(sequence header). 2.0.22.

... ... @@ -244,6 +244,7 @@ Supported operating systems and hardware:
* 2013-10-17, Created.<br/>
## 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.
... ...
... ... @@ -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;
... ...
... ... @@ -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"
... ...
... ... @@ -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.
... ...
... ... @@ -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;
... ...
... ... @@ -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.
... ...