正在显示
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. |
-
请 注册 或 登录 后发表评论