fix #203, srs-librtmp drop any video before sps/pps(sequence header). 2.0.21.
正在显示
6 个修改的文件
包含
50 行增加
和
13 行删除
| @@ -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 [#203](https://github.com/winlinvip/simple-rtmp-server/issues/203), srs-librtmp drop any video before sps/pps(sequence header). 2.0.21. | ||
| 247 | * 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. | 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. |
| 248 | * 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. | 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. |
| 249 | * v2.0, 2014-11-13, fix [#194](https://github.com/winlinvip/simple-rtmp-server/issues/194), writev multiple msgs, support 6k+ 250kbps clients. 2.0.15. | 250 | * v2.0, 2014-11-13, fix [#194](https://github.com/winlinvip/simple-rtmp-server/issues/194), writev multiple msgs, support 6k+ 250kbps clients. 2.0.15. |
| @@ -166,9 +166,14 @@ int main(int argc, char** argv) | @@ -166,9 +166,14 @@ int main(int argc, char** argv) | ||
| 166 | } | 166 | } |
| 167 | 167 | ||
| 168 | // send out the h264 packet over RTMP | 168 | // send out the h264 packet over RTMP |
| 169 | - if (srs_write_h264_raw_frames(rtmp, data, size, dts, pts) != 0) { | ||
| 170 | - srs_lib_trace("send h264 raw data failed."); | ||
| 171 | - goto rtmp_destroy; | 169 | + int error = srs_h264_write_raw_frames(rtmp, data, size, dts, pts); |
| 170 | + if (error != 0) { | ||
| 171 | + if (srs_h264_is_dvbsp_error(error)) { | ||
| 172 | + srs_lib_trace("ignore drop video error, code=%d", error); | ||
| 173 | + } else { | ||
| 174 | + srs_lib_trace("send h264 raw data failed."); | ||
| 175 | + goto rtmp_destroy; | ||
| 176 | + } | ||
| 172 | } | 177 | } |
| 173 | 178 | ||
| 174 | // 5bits, 7.3.1 NAL unit syntax, | 179 | // 5bits, 7.3.1 NAL unit syntax, |
| @@ -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 20 | 34 | +#define VERSION_REVISION 21 |
| 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" |
| @@ -186,6 +186,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -186,6 +186,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 186 | #define ERROR_HLS_AVC_TRY_OTHERS 3040 | 186 | #define ERROR_HLS_AVC_TRY_OTHERS 3040 |
| 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 | 190 | ||
| 190 | /** | 191 | /** |
| 191 | * whether the error code is an system control error. | 192 | * whether the error code is an system control error. |
| @@ -76,11 +76,15 @@ struct Context | @@ -76,11 +76,15 @@ struct Context | ||
| 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, | ||
| 80 | + // @see https://github.com/winlinvip/simple-rtmp-server/issues/203 | ||
| 81 | + bool h264_sps_pps_sent; | ||
| 79 | 82 | ||
| 80 | Context() { | 83 | Context() { |
| 81 | rtmp = NULL; | 84 | rtmp = NULL; |
| 82 | skt = NULL; | 85 | skt = NULL; |
| 83 | stream_id = 0; | 86 | stream_id = 0; |
| 87 | + h264_sps_pps_sent = false; | ||
| 84 | } | 88 | } |
| 85 | virtual ~Context() { | 89 | virtual ~Context() { |
| 86 | srs_freep(rtmp); | 90 | srs_freep(rtmp); |
| @@ -1205,6 +1209,7 @@ int __srs_write_h264_sps_pps(Context* context, u_int32_t dts, u_int32_t pts) | @@ -1205,6 +1209,7 @@ int __srs_write_h264_sps_pps(Context* context, u_int32_t dts, u_int32_t pts) | ||
| 1205 | // reset sps and pps. | 1209 | // reset sps and pps. |
| 1206 | context->h264_pps = ""; | 1210 | context->h264_pps = ""; |
| 1207 | context->h264_sps = ""; | 1211 | context->h264_sps = ""; |
| 1212 | + context->h264_sps_pps_sent = true; | ||
| 1208 | 1213 | ||
| 1209 | // TODO: FIXME: for more profile. | 1214 | // TODO: FIXME: for more profile. |
| 1210 | // 5.3.4.2.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 16 | 1215 | // 5.3.4.2.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 16 |
| @@ -1227,6 +1232,12 @@ int __srs_write_h264_ipb_frame(Context* context, | @@ -1227,6 +1232,12 @@ int __srs_write_h264_ipb_frame(Context* context, | ||
| 1227 | ) { | 1232 | ) { |
| 1228 | int ret = ERROR_SUCCESS; | 1233 | int ret = ERROR_SUCCESS; |
| 1229 | 1234 | ||
| 1235 | + // when sps or pps not sent, ignore the packet. | ||
| 1236 | + // @see https://github.com/winlinvip/simple-rtmp-server/issues/203 | ||
| 1237 | + if (!context->h264_sps_pps_sent) { | ||
| 1238 | + return ERROR_H264_DROP_BEFORE_SPS_PPS; | ||
| 1239 | + } | ||
| 1240 | + | ||
| 1230 | // 5bits, 7.3.1 NAL unit syntax, | 1241 | // 5bits, 7.3.1 NAL unit syntax, |
| 1231 | // H.264-AVC-ISO_IEC_14496-10.pdf, page 44. | 1242 | // H.264-AVC-ISO_IEC_14496-10.pdf, page 44. |
| 1232 | // 7: SPS, 8: PPS, 5: I Frame, 1: P Frame | 1243 | // 7: SPS, 8: PPS, 5: I Frame, 1: P Frame |
| @@ -1315,7 +1326,7 @@ int __srs_write_h264_raw_frame(Context* context, | @@ -1315,7 +1326,7 @@ int __srs_write_h264_raw_frame(Context* context, | ||
| 1315 | /** | 1326 | /** |
| 1316 | * write h264 multiple frames, in annexb format. | 1327 | * write h264 multiple frames, in annexb format. |
| 1317 | */ | 1328 | */ |
| 1318 | -int srs_write_h264_raw_frames(srs_rtmp_t rtmp, | 1329 | +int srs_h264_write_raw_frames(srs_rtmp_t rtmp, |
| 1319 | char* frames, int frames_size, u_int32_t dts, u_int32_t pts | 1330 | char* frames, int frames_size, u_int32_t dts, u_int32_t pts |
| 1320 | ) { | 1331 | ) { |
| 1321 | int ret = ERROR_SUCCESS; | 1332 | int ret = ERROR_SUCCESS; |
| @@ -1360,6 +1371,11 @@ int srs_write_h264_raw_frames(srs_rtmp_t rtmp, | @@ -1360,6 +1371,11 @@ int srs_write_h264_raw_frames(srs_rtmp_t rtmp, | ||
| 1360 | return ret; | 1371 | return ret; |
| 1361 | } | 1372 | } |
| 1362 | 1373 | ||
| 1374 | +srs_h264_bool srs_h264_is_dvbsp_error(int error_code) | ||
| 1375 | +{ | ||
| 1376 | + return error_code == ERROR_H264_DROP_BEFORE_SPS_PPS; | ||
| 1377 | +} | ||
| 1378 | + | ||
| 1363 | int srs_h264_startswith_annexb(char* h264_raw_data, int h264_raw_size, int* pnb_start_code) | 1379 | int srs_h264_startswith_annexb(char* h264_raw_data, int h264_raw_size, int* pnb_start_code) |
| 1364 | { | 1380 | { |
| 1365 | SrsStream stream; | 1381 | SrsStream stream; |
| @@ -424,6 +424,7 @@ extern char* srs_amf0_human_print(srs_amf0_t amf0, char** pdata, int* psize); | @@ -424,6 +424,7 @@ extern char* srs_amf0_human_print(srs_amf0_t amf0, char** pdata, int* psize); | ||
| 424 | * h264 raw codec | 424 | * h264 raw codec |
| 425 | ************************************************************** | 425 | ************************************************************** |
| 426 | *************************************************************/ | 426 | *************************************************************/ |
| 427 | +typedef int srs_h264_bool; | ||
| 427 | /** | 428 | /** |
| 428 | * write h.264 raw frame over RTMP to rtmp server. | 429 | * write h.264 raw frame over RTMP to rtmp server. |
| 429 | * @param frames the input h264 raw data, encoded h.264 I/P/B frames data. | 430 | * @param frames the input h264 raw data, encoded h.264 I/P/B frames data. |
| @@ -441,8 +442,10 @@ extern char* srs_amf0_human_print(srs_amf0_t amf0, char** pdata, int* psize); | @@ -441,8 +442,10 @@ extern char* srs_amf0_human_print(srs_amf0_t amf0, char** pdata, int* psize); | ||
| 441 | * @remark, cts = pts - dts | 442 | * @remark, cts = pts - dts |
| 442 | * @remark, use srs_h264_startswith_annexb to check whether frame is annexb format. | 443 | * @remark, use srs_h264_startswith_annexb to check whether frame is annexb format. |
| 443 | * @example /trunk/research/librtmp/srs_h264_raw_publish.c | 444 | * @example /trunk/research/librtmp/srs_h264_raw_publish.c |
| 445 | +* @see https://github.com/winlinvip/simple-rtmp-server/issues/66 | ||
| 444 | * | 446 | * |
| 445 | * @return 0, success; otherswise, failed. | 447 | * @return 0, success; otherswise, failed. |
| 448 | +* for dvbsp error, check by srs_h264_is_dvbsp_error(error_code). | ||
| 446 | */ | 449 | */ |
| 447 | /** | 450 | /** |
| 448 | For the example file: | 451 | For the example file: |
| @@ -458,25 +461,36 @@ The data sequence is: | @@ -458,25 +461,36 @@ The data sequence is: | ||
| 458 | 0000000141E02041F8CDDC562BBDEFAD2F..... | 461 | 0000000141E02041F8CDDC562BBDEFAD2F..... |
| 459 | User can send the SPS+PPS, then each frame: | 462 | User can send the SPS+PPS, then each frame: |
| 460 | // SPS+PPS | 463 | // SPS+PPS |
| 461 | - srs_write_h264_raw_frame('000000016742802995A014016E400000000168CE3880', size, dts, pts) | 464 | + srs_h264_write_raw_frames('000000016742802995A014016E400000000168CE3880', size, dts, pts) |
| 462 | // IFrame | 465 | // IFrame |
| 463 | - srs_write_h264_raw_frame('0000000165B8041014C038008B0D0D3A071......', size, dts, pts) | 466 | + srs_h264_write_raw_frames('0000000165B8041014C038008B0D0D3A071......', size, dts, pts) |
| 464 | // PFrame | 467 | // PFrame |
| 465 | - srs_write_h264_raw_frame('0000000141E02041F8CDDC562BBDEFAD2F......', size, dts, pts) | 468 | + srs_h264_write_raw_frames('0000000141E02041F8CDDC562BBDEFAD2F......', size, dts, pts) |
| 466 | User also can send one by one: | 469 | User also can send one by one: |
| 467 | // SPS | 470 | // SPS |
| 468 | - srs_write_h264_raw_frame('000000016742802995A014016E4', size, dts, pts) | 471 | + srs_h264_write_raw_frames('000000016742802995A014016E4', size, dts, pts) |
| 469 | // PPS | 472 | // PPS |
| 470 | - srs_write_h264_raw_frame('00000000168CE3880', size, dts, pts) | 473 | + srs_h264_write_raw_frames('00000000168CE3880', size, dts, pts) |
| 471 | // IFrame | 474 | // IFrame |
| 472 | - srs_write_h264_raw_frame('0000000165B8041014C038008B0D0D3A071......', size, dts, pts) | 475 | + srs_h264_write_raw_frames('0000000165B8041014C038008B0D0D3A071......', size, dts, pts) |
| 473 | // PFrame | 476 | // PFrame |
| 474 | - srs_write_h264_raw_frame('0000000141E02041F8CDDC562BBDEFAD2F......', size, dts, pts) | 477 | + srs_h264_write_raw_frames('0000000141E02041F8CDDC562BBDEFAD2F......', size, dts, pts) |
| 475 | */ | 478 | */ |
| 476 | -extern int srs_write_h264_raw_frames(srs_rtmp_t rtmp, | 479 | +extern int srs_h264_write_raw_frames(srs_rtmp_t rtmp, |
| 477 | char* frames, int frames_size, u_int32_t dts, u_int32_t pts | 480 | char* frames, int frames_size, u_int32_t dts, u_int32_t pts |
| 478 | ); | 481 | ); |
| 479 | /** | 482 | /** |
| 483 | +* whether error_code is dvbsp(drop video before sps/pps/sequence-header) error. | ||
| 484 | +* | ||
| 485 | +* @see https://github.com/winlinvip/simple-rtmp-server/issues/203 | ||
| 486 | +* @example /trunk/research/librtmp/srs_h264_raw_publish.c | ||
| 487 | +* @remark why drop video? | ||
| 488 | +* some encoder, for example, ipcamera, will send sps/pps before each IFrame, | ||
| 489 | +* so, when error and reconnect the rtmp, the first video is not sps/pps(sequence header), | ||
| 490 | +* this will cause SRS server to disable HLS. | ||
| 491 | +*/ | ||
| 492 | +extern srs_h264_bool srs_h264_is_dvbsp_error(int error_code); | ||
| 493 | +/** | ||
| 480 | * whether h264 raw data starts with the annexb, | 494 | * whether h264 raw data starts with the annexb, |
| 481 | * which bytes sequence matches N[00] 00 00 01, where N>=0. | 495 | * which bytes sequence matches N[00] 00 00 01, where N>=0. |
| 482 | * @param h264_raw_data the input h264 raw data, a encoded h.264 I/P/B frame data. | 496 | * @param h264_raw_data the input h264 raw data, a encoded h.264 I/P/B frame data. |
-
请 注册 或 登录 后发表评论