正在显示
6 个修改的文件
包含
91 行增加
和
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. |
@@ -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. |
-
请 注册 或 登录 后发表评论