正在显示
6 个修改的文件
包含
55 行增加
和
18 行删除
@@ -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,10 +166,15 @@ int main(int argc, char** argv) | @@ -166,10 +166,15 @@ 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) { | 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 { | ||
170 | srs_lib_trace("send h264 raw data failed."); | 174 | srs_lib_trace("send h264 raw data failed."); |
171 | goto rtmp_destroy; | 175 | goto rtmp_destroy; |
172 | } | 176 | } |
177 | + } | ||
173 | 178 | ||
174 | // 5bits, 7.3.1 NAL unit syntax, | 179 | // 5bits, 7.3.1 NAL unit syntax, |
175 | // H.264-AVC-ISO_IEC_14496-10.pdf, page 44. | 180 | // H.264-AVC-ISO_IEC_14496-10.pdf, page 44. |
@@ -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); |
@@ -767,17 +771,17 @@ void srs_flv_lseek(srs_flv_t flv, int64_t offset) | @@ -767,17 +771,17 @@ void srs_flv_lseek(srs_flv_t flv, int64_t offset) | ||
767 | context->reader.lseek(offset); | 771 | context->reader.lseek(offset); |
768 | } | 772 | } |
769 | 773 | ||
770 | -flv_bool srs_flv_is_eof(int error_code) | 774 | +srs_flv_bool srs_flv_is_eof(int error_code) |
771 | { | 775 | { |
772 | return error_code == ERROR_SYSTEM_FILE_EOF; | 776 | return error_code == ERROR_SYSTEM_FILE_EOF; |
773 | } | 777 | } |
774 | 778 | ||
775 | -flv_bool srs_flv_is_sequence_header(char* data, int32_t size) | 779 | +srs_flv_bool srs_flv_is_sequence_header(char* data, int32_t size) |
776 | { | 780 | { |
777 | return SrsFlvCodec::video_is_sequence_header(data, (int)size); | 781 | return SrsFlvCodec::video_is_sequence_header(data, (int)size); |
778 | } | 782 | } |
779 | 783 | ||
780 | -flv_bool srs_flv_is_keyframe(char* data, int32_t size) | 784 | +srs_flv_bool srs_flv_is_keyframe(char* data, int32_t size) |
781 | { | 785 | { |
782 | return SrsFlvCodec::video_is_keyframe(data, (int)size); | 786 | return SrsFlvCodec::video_is_keyframe(data, (int)size); |
783 | } | 787 | } |
@@ -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; |
@@ -269,7 +269,7 @@ extern const char* srs_format_time(); | @@ -269,7 +269,7 @@ extern const char* srs_format_time(); | ||
269 | ************************************************************** | 269 | ************************************************************** |
270 | *************************************************************/ | 270 | *************************************************************/ |
271 | typedef void* srs_flv_t; | 271 | typedef void* srs_flv_t; |
272 | -typedef int flv_bool; | 272 | +typedef int srs_flv_bool; |
273 | /* open flv file for both read/write. */ | 273 | /* open flv file for both read/write. */ |
274 | extern srs_flv_t srs_flv_open_read(const char* file); | 274 | extern srs_flv_t srs_flv_open_read(const char* file); |
275 | extern srs_flv_t srs_flv_open_write(const char* file); | 275 | extern srs_flv_t srs_flv_open_write(const char* file); |
@@ -344,20 +344,20 @@ extern int64_t srs_flv_tellg(srs_flv_t flv); | @@ -344,20 +344,20 @@ extern int64_t srs_flv_tellg(srs_flv_t flv); | ||
344 | extern void srs_flv_lseek(srs_flv_t flv, int64_t offset); | 344 | extern void srs_flv_lseek(srs_flv_t flv, int64_t offset); |
345 | /* error code */ | 345 | /* error code */ |
346 | /* whether the error code indicates EOF */ | 346 | /* whether the error code indicates EOF */ |
347 | -extern flv_bool srs_flv_is_eof(int error_code); | 347 | +extern srs_flv_bool srs_flv_is_eof(int error_code); |
348 | /* media codec */ | 348 | /* media codec */ |
349 | /** | 349 | /** |
350 | * whether the video body is sequence header | 350 | * whether the video body is sequence header |
351 | * @param data, the data of tag, read by srs_flv_read_tag_data(). | 351 | * @param data, the data of tag, read by srs_flv_read_tag_data(). |
352 | * @param size, the size of tag, read by srs_flv_read_tag_data(). | 352 | * @param size, the size of tag, read by srs_flv_read_tag_data(). |
353 | */ | 353 | */ |
354 | -extern flv_bool srs_flv_is_sequence_header(char* data, int32_t size); | 354 | +extern srs_flv_bool srs_flv_is_sequence_header(char* data, int32_t size); |
355 | /** | 355 | /** |
356 | * whether the video body is keyframe | 356 | * whether the video body is keyframe |
357 | * @param data, the data of tag, read by srs_flv_read_tag_data(). | 357 | * @param data, the data of tag, read by srs_flv_read_tag_data(). |
358 | * @param size, the size of tag, read by srs_flv_read_tag_data(). | 358 | * @param size, the size of tag, read by srs_flv_read_tag_data(). |
359 | */ | 359 | */ |
360 | -extern flv_bool srs_flv_is_keyframe(char* data, int32_t size); | 360 | +extern srs_flv_bool srs_flv_is_keyframe(char* data, int32_t size); |
361 | 361 | ||
362 | /************************************************************* | 362 | /************************************************************* |
363 | ************************************************************** | 363 | ************************************************************** |
@@ -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. |
-
请 注册 或 登录 后发表评论