winlin

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

@@ -244,6 +244,7 @@ Supported operating systems and hardware: @@ -244,6 +244,7 @@ Supported operating systems and hardware:
244 * 2013-10-17, Created.<br/> 244 * 2013-10-17, Created.<br/>
245 245
246 ## History 246 ## History
  247 +* 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.
247 * 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. 248 * 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.
248 * 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. 249 * 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.
249 * 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. 250 * 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) @@ -170,6 +170,10 @@ int main(int argc, char** argv)
170 if (error != 0) { 170 if (error != 0) {
171 if (srs_h264_is_dvbsp_error(error)) { 171 if (srs_h264_is_dvbsp_error(error)) {
172 srs_lib_trace("ignore drop video error, code=%d", error); 172 srs_lib_trace("ignore drop video error, code=%d", error);
  173 + } else if (srs_h264_is_duplicated_sps_error(error)) {
  174 + srs_lib_trace("ignore duplicated sps, code=%d", error);
  175 + } else if (srs_h264_is_duplicated_pps_error(error)) {
  176 + srs_lib_trace("ignore duplicated pps, code=%d", error);
173 } else { 177 } else {
174 srs_lib_trace("send h264 raw data failed."); 178 srs_lib_trace("send h264 raw data failed.");
175 goto rtmp_destroy; 179 goto rtmp_destroy;
@@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 // current release version 31 // current release version
32 #define VERSION_MAJOR 2 32 #define VERSION_MAJOR 2
33 #define VERSION_MINOR 0 33 #define VERSION_MINOR 0
34 -#define VERSION_REVISION 21 34 +#define VERSION_REVISION 22
35 // server info. 35 // server info.
36 #define RTMP_SIG_SRS_KEY "SRS" 36 #define RTMP_SIG_SRS_KEY "SRS"
37 #define RTMP_SIG_SRS_ROLE "origin/edge server" 37 #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. @@ -187,6 +187,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
187 #define ERROR_H264_API_NO_PREFIXED 3041 187 #define ERROR_H264_API_NO_PREFIXED 3041
188 #define ERROR_FLV_INVALID_VIDEO_TAG 3042 188 #define ERROR_FLV_INVALID_VIDEO_TAG 3042
189 #define ERROR_H264_DROP_BEFORE_SPS_PPS 3043 189 #define ERROR_H264_DROP_BEFORE_SPS_PPS 3043
  190 +#define ERROR_H264_DUPLICATED_SPS 3044
  191 +#define ERROR_H264_DUPLICATED_PPS 3045
190 192
191 /** 193 /**
192 * whether the error code is an system control error. 194 * whether the error code is an system control error.
@@ -79,12 +79,18 @@ struct Context @@ -79,12 +79,18 @@ struct Context
79 // whether the sps and pps sent, 79 // whether the sps and pps sent,
80 // @see https://github.com/winlinvip/simple-rtmp-server/issues/203 80 // @see https://github.com/winlinvip/simple-rtmp-server/issues/203
81 bool h264_sps_pps_sent; 81 bool h264_sps_pps_sent;
  82 + // only send the ssp and pps when both changed.
  83 + // @see https://github.com/winlinvip/simple-rtmp-server/issues/204
  84 + bool h264_sps_changed;
  85 + bool h264_pps_changed;
82 86
83 Context() { 87 Context() {
84 rtmp = NULL; 88 rtmp = NULL;
85 skt = NULL; 89 skt = NULL;
86 stream_id = 0; 90 stream_id = 0;
87 h264_sps_pps_sent = false; 91 h264_sps_pps_sent = false;
  92 + h264_sps_changed = false;
  93 + h264_pps_changed = false;
88 } 94 }
89 virtual ~Context() { 95 virtual ~Context() {
90 srs_freep(rtmp); 96 srs_freep(rtmp);
@@ -1127,8 +1133,8 @@ int __srs_write_h264_sps_pps(Context* context, u_int32_t dts, u_int32_t pts) @@ -1127,8 +1133,8 @@ int __srs_write_h264_sps_pps(Context* context, u_int32_t dts, u_int32_t pts)
1127 { 1133 {
1128 int ret = ERROR_SUCCESS; 1134 int ret = ERROR_SUCCESS;
1129 1135
1130 - // when pps or sps not ready, ignore.  
1131 - if (context->h264_pps.empty() || context->h264_sps.empty()) { 1136 + // only send when both sps and pps changed.
  1137 + if (!context->h264_sps_changed || !context->h264_pps_changed) {
1132 return ret; 1138 return ret;
1133 } 1139 }
1134 1140
@@ -1207,8 +1213,8 @@ int __srs_write_h264_sps_pps(Context* context, u_int32_t dts, u_int32_t pts) @@ -1207,8 +1213,8 @@ int __srs_write_h264_sps_pps(Context* context, u_int32_t dts, u_int32_t pts)
1207 } 1213 }
1208 1214
1209 // reset sps and pps. 1215 // reset sps and pps.
1210 - context->h264_pps = "";  
1211 - context->h264_sps = ""; 1216 + context->h264_sps_changed = false;
  1217 + context->h264_pps_changed = false;
1212 context->h264_sps_pps_sent = true; 1218 context->h264_sps_pps_sent = true;
1213 1219
1214 // TODO: FIXME: for more profile. 1220 // TODO: FIXME: for more profile.
@@ -1307,13 +1313,26 @@ int __srs_write_h264_raw_frame(Context* context, @@ -1307,13 +1313,26 @@ int __srs_write_h264_raw_frame(Context* context,
1307 return ret; 1313 return ret;
1308 } 1314 }
1309 1315
1310 - context->h264_sps = "";  
1311 - context->h264_sps.append(frame, frame_size); 1316 + std::string sps;
  1317 + sps.append(frame, frame_size);
  1318 +
  1319 + if (context->h264_sps == sps) {
  1320 + return ERROR_H264_DUPLICATED_SPS;
  1321 + }
  1322 + context->h264_sps_changed = true;
  1323 + context->h264_sps = sps;
1312 1324
1313 return __srs_write_h264_sps_pps(context, dts, pts); 1325 return __srs_write_h264_sps_pps(context, dts, pts);
1314 } else if (nal_unit_type == 8) { 1326 } else if (nal_unit_type == 8) {
1315 - context->h264_pps = "";  
1316 - context->h264_pps.append(frame, frame_size); 1327 +
  1328 + std::string pps;
  1329 + pps.append(frame, frame_size);
  1330 +
  1331 + if (context->h264_pps == pps) {
  1332 + return ERROR_H264_DUPLICATED_PPS;
  1333 + }
  1334 + context->h264_pps_changed = true;
  1335 + context->h264_pps = pps;
1317 1336
1318 return __srs_write_h264_sps_pps(context, dts, pts); 1337 return __srs_write_h264_sps_pps(context, dts, pts);
1319 } else { 1338 } else {
@@ -1341,6 +1360,11 @@ int srs_h264_write_raw_frames(srs_rtmp_t rtmp, @@ -1341,6 +1360,11 @@ int srs_h264_write_raw_frames(srs_rtmp_t rtmp,
1341 return ret; 1360 return ret;
1342 } 1361 }
1343 1362
  1363 + // use the last error
  1364 + // @see https://github.com/winlinvip/simple-rtmp-server/issues/203
  1365 + // @see https://github.com/winlinvip/simple-rtmp-server/issues/204
  1366 + int error_code_return = ret;
  1367 +
1344 // send each frame. 1368 // send each frame.
1345 while (!context->h264_raw_stream.empty()) { 1369 while (!context->h264_raw_stream.empty()) {
1346 // each frame must prefixed by annexb format. 1370 // each frame must prefixed by annexb format.
@@ -1363,12 +1387,24 @@ int srs_h264_write_raw_frames(srs_rtmp_t rtmp, @@ -1363,12 +1387,24 @@ int srs_h264_write_raw_frames(srs_rtmp_t rtmp,
1363 1387
1364 // send out the frame. 1388 // send out the frame.
1365 char* frame = context->h264_raw_stream.data() + start; 1389 char* frame = context->h264_raw_stream.data() + start;
  1390 +
  1391 + // it may be return error, but we must process all packets.
1366 if ((ret = __srs_write_h264_raw_frame(context, frame, size, dts, pts)) != ERROR_SUCCESS) { 1392 if ((ret = __srs_write_h264_raw_frame(context, frame, size, dts, pts)) != ERROR_SUCCESS) {
  1393 + error_code_return = ret;
  1394 +
  1395 + // ignore known error, process all packets.
  1396 + if (srs_h264_is_dvbsp_error(ret)
  1397 + || srs_h264_is_duplicated_sps_error(ret)
  1398 + || srs_h264_is_duplicated_pps_error(ret)
  1399 + ) {
  1400 + continue;
  1401 + }
  1402 +
1367 return ret; 1403 return ret;
1368 } 1404 }
1369 } 1405 }
1370 1406
1371 - return ret; 1407 + return error_code_return;
1372 } 1408 }
1373 1409
1374 srs_h264_bool srs_h264_is_dvbsp_error(int error_code) 1410 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) @@ -1376,6 +1412,16 @@ srs_h264_bool srs_h264_is_dvbsp_error(int error_code)
1376 return error_code == ERROR_H264_DROP_BEFORE_SPS_PPS; 1412 return error_code == ERROR_H264_DROP_BEFORE_SPS_PPS;
1377 } 1413 }
1378 1414
  1415 +srs_h264_bool srs_h264_is_duplicated_sps_error(int error_code)
  1416 +{
  1417 + return error_code == ERROR_H264_DUPLICATED_SPS;
  1418 +}
  1419 +
  1420 +srs_h264_bool srs_h264_is_duplicated_pps_error(int error_code)
  1421 +{
  1422 + return error_code == ERROR_H264_DUPLICATED_PPS;
  1423 +}
  1424 +
1379 int srs_h264_startswith_annexb(char* h264_raw_data, int h264_raw_size, int* pnb_start_code) 1425 int srs_h264_startswith_annexb(char* h264_raw_data, int h264_raw_size, int* pnb_start_code)
1380 { 1426 {
1381 SrsStream stream; 1427 SrsStream stream;
@@ -445,7 +445,9 @@ typedef int srs_h264_bool; @@ -445,7 +445,9 @@ typedef int srs_h264_bool;
445 * @see https://github.com/winlinvip/simple-rtmp-server/issues/66 445 * @see https://github.com/winlinvip/simple-rtmp-server/issues/66
446 * 446 *
447 * @return 0, success; otherswise, failed. 447 * @return 0, success; otherswise, failed.
448 -* for dvbsp error, check by srs_h264_is_dvbsp_error(error_code). 448 +* for dvbsp error, @see srs_h264_is_dvbsp_error().
  449 +* for duplictated sps error, @see srs_h264_is_duplicated_sps_error().
  450 +* for duplictated pps error, @see srs_h264_is_duplicated_pps_error().
449 */ 451 */
450 /** 452 /**
451 For the example file: 453 For the example file:
@@ -491,6 +493,20 @@ extern int srs_h264_write_raw_frames(srs_rtmp_t rtmp, @@ -491,6 +493,20 @@ extern int srs_h264_write_raw_frames(srs_rtmp_t rtmp,
491 */ 493 */
492 extern srs_h264_bool srs_h264_is_dvbsp_error(int error_code); 494 extern srs_h264_bool srs_h264_is_dvbsp_error(int error_code);
493 /** 495 /**
  496 +* whether error_code is duplicated sps error.
  497 +*
  498 +* @see https://github.com/winlinvip/simple-rtmp-server/issues/204
  499 +* @example /trunk/research/librtmp/srs_h264_raw_publish.c
  500 +*/
  501 +extern srs_h264_bool srs_h264_is_duplicated_sps_error(int error_code);
  502 +/**
  503 +* whether error_code is duplicated pps error.
  504 +*
  505 +* @see https://github.com/winlinvip/simple-rtmp-server/issues/204
  506 +* @example /trunk/research/librtmp/srs_h264_raw_publish.c
  507 +*/
  508 +extern srs_h264_bool srs_h264_is_duplicated_pps_error(int error_code);
  509 +/**
494 * whether h264 raw data starts with the annexb, 510 * whether h264 raw data starts with the annexb,
495 * which bytes sequence matches N[00] 00 00 01, where N>=0. 511 * which bytes sequence matches N[00] 00 00 01, where N>=0.
496 * @param h264_raw_data the input h264 raw data, a encoded h.264 I/P/B frame data. 512 * @param h264_raw_data the input h264 raw data, a encoded h.264 I/P/B frame data.