winlin

Merge branch 'srs.master'

@@ -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.
@@ -72,19 +72,25 @@ struct Context @@ -72,19 +72,25 @@ struct Context
72 72
73 // for h264 raw stream, 73 // for h264 raw stream,
74 // see: https://github.com/winlinvip/simple-rtmp-server/issues/66#issuecomment-62240521 74 // see: https://github.com/winlinvip/simple-rtmp-server/issues/66#issuecomment-62240521
75 - SrsStream raw_stream; 75 + SrsStream h264_raw_stream;
76 // about SPS, @see: 7.3.2.1.1, H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 62 76 // about SPS, @see: 7.3.2.1.1, H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 62
77 std::string h264_sps; 77 std::string h264_sps;
78 std::string h264_pps; 78 std::string h264_pps;
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 {
@@ -1337,38 +1356,55 @@ int srs_h264_write_raw_frames(srs_rtmp_t rtmp, @@ -1337,38 +1356,55 @@ int srs_h264_write_raw_frames(srs_rtmp_t rtmp,
1337 srs_assert(rtmp != NULL); 1356 srs_assert(rtmp != NULL);
1338 Context* context = (Context*)rtmp; 1357 Context* context = (Context*)rtmp;
1339 1358
1340 - if ((ret = context->raw_stream.initialize(frames, frames_size)) != ERROR_SUCCESS) { 1359 + if ((ret = context->h264_raw_stream.initialize(frames, frames_size)) != ERROR_SUCCESS) {
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->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.
1347 // about annexb, @see H.264-AVC-ISO_IEC_14496-10.pdf, page 211. 1371 // about annexb, @see H.264-AVC-ISO_IEC_14496-10.pdf, page 211.
1348 int pnb_start_code = 0; 1372 int pnb_start_code = 0;
1349 - if (!srs_avc_startswith_annexb(&context->raw_stream, &pnb_start_code)) { 1373 + if (!srs_avc_startswith_annexb(&context->h264_raw_stream, &pnb_start_code)) {
1350 return ERROR_H264_API_NO_PREFIXED; 1374 return ERROR_H264_API_NO_PREFIXED;
1351 } 1375 }
1352 - int start = context->raw_stream.pos() + pnb_start_code; 1376 + int start = context->h264_raw_stream.pos() + pnb_start_code;
1353 1377
1354 // find the last frame prefixed by annexb format. 1378 // find the last frame prefixed by annexb format.
1355 - context->raw_stream.skip(pnb_start_code);  
1356 - while (!context->raw_stream.empty()) {  
1357 - if (srs_avc_startswith_annexb(&context->raw_stream, NULL)) { 1379 + context->h264_raw_stream.skip(pnb_start_code);
  1380 + while (!context->h264_raw_stream.empty()) {
  1381 + if (srs_avc_startswith_annexb(&context->h264_raw_stream, NULL)) {
1358 break; 1382 break;
1359 } 1383 }
1360 - context->raw_stream.skip(1); 1384 + context->h264_raw_stream.skip(1);
1361 } 1385 }
1362 - int size = context->raw_stream.pos() - start; 1386 + int size = context->h264_raw_stream.pos() - start;
1363 1387
1364 // send out the frame. 1388 // send out the frame.
1365 - char* frame = context->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.