fix #204, srs-librtmp drop dupliated sps/pps(sequence header). 2.0.22.
正在显示
6 个修改的文件
包含
80 行增加
和
11 行删除
| @@ -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. |
-
请 注册 或 登录 后发表评论