正在显示
4 个修改的文件
包含
175 行增加
和
155 行删除
@@ -349,28 +349,6 @@ private: | @@ -349,28 +349,6 @@ private: | ||
349 | } | 349 | } |
350 | }; | 350 | }; |
351 | 351 | ||
352 | -SrsM3u8Segment::SrsM3u8Segment() | ||
353 | -{ | ||
354 | - duration = 0; | ||
355 | - sequence_no = 0; | ||
356 | - muxer = new SrsTSMuxer(); | ||
357 | - segment_start_dts = 0; | ||
358 | -} | ||
359 | - | ||
360 | -SrsM3u8Segment::~SrsM3u8Segment() | ||
361 | -{ | ||
362 | - srs_freep(muxer); | ||
363 | -} | ||
364 | - | ||
365 | -SrsHlsAacJitter::SrsHlsAacJitter() | ||
366 | -{ | ||
367 | - base_pts = 0; | ||
368 | - nb_samples = 0; | ||
369 | - | ||
370 | - // TODO: config it, 0 means no adjust | ||
371 | - sync_ms = SRS_CONF_DEFAULT_AAC_SYNC; | ||
372 | -} | ||
373 | - | ||
374 | SrsHlsAacJitter::~SrsHlsAacJitter() | 352 | SrsHlsAacJitter::~SrsHlsAacJitter() |
375 | { | 353 | { |
376 | } | 354 | } |
@@ -421,6 +399,111 @@ void SrsHlsAacJitter::on_buffer_continue() | @@ -421,6 +399,111 @@ void SrsHlsAacJitter::on_buffer_continue() | ||
421 | nb_samples++; | 399 | nb_samples++; |
422 | } | 400 | } |
423 | 401 | ||
402 | +SrsM3u8Segment::SrsM3u8Segment() | ||
403 | +{ | ||
404 | + duration = 0; | ||
405 | + sequence_no = 0; | ||
406 | + muxer = new SrsTSMuxer(); | ||
407 | + segment_start_dts = 0; | ||
408 | +} | ||
409 | + | ||
410 | +SrsM3u8Segment::~SrsM3u8Segment() | ||
411 | +{ | ||
412 | + srs_freep(muxer); | ||
413 | +} | ||
414 | + | ||
415 | +double SrsM3u8Segment::update_duration(int64_t video_stream_dts) | ||
416 | +{ | ||
417 | + duration = (video_stream_dts - segment_start_dts) / 90000.0; | ||
418 | + srs_assert(duration > 0); | ||
419 | + | ||
420 | + return duration; | ||
421 | +} | ||
422 | + | ||
423 | +SrsHlsAacJitter::SrsHlsAacJitter() | ||
424 | +{ | ||
425 | + base_pts = 0; | ||
426 | + nb_samples = 0; | ||
427 | + | ||
428 | + // TODO: config it, 0 means no adjust | ||
429 | + sync_ms = SRS_CONF_DEFAULT_AAC_SYNC; | ||
430 | +} | ||
431 | + | ||
432 | +SrsTSMuxer::SrsTSMuxer() | ||
433 | +{ | ||
434 | + fd = -1; | ||
435 | + _fresh = false; | ||
436 | +} | ||
437 | + | ||
438 | +SrsTSMuxer::~SrsTSMuxer() | ||
439 | +{ | ||
440 | + close(); | ||
441 | +} | ||
442 | + | ||
443 | +int SrsTSMuxer::open(std::string _path) | ||
444 | +{ | ||
445 | + int ret = ERROR_SUCCESS; | ||
446 | + | ||
447 | + path = _path; | ||
448 | + | ||
449 | + close(); | ||
450 | + | ||
451 | + int flags = O_CREAT|O_WRONLY|O_TRUNC; | ||
452 | + mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH; | ||
453 | + if ((fd = ::open(path.c_str(), flags, mode)) < 0) { | ||
454 | + ret = ERROR_HLS_OPEN_FAILED; | ||
455 | + srs_error("open ts file %s failed. ret=%d", path.c_str(), ret); | ||
456 | + return ret; | ||
457 | + } | ||
458 | + | ||
459 | + // write mpegts header | ||
460 | + if ((ret = SrsMpegtsWriter::write_header(fd)) != ERROR_SUCCESS) { | ||
461 | + return ret; | ||
462 | + } | ||
463 | + | ||
464 | + _fresh = true; | ||
465 | + | ||
466 | + return ret; | ||
467 | +} | ||
468 | + | ||
469 | +int SrsTSMuxer::write_audio(SrsMpegtsFrame* audio_frame, SrsCodecBuffer* audio_buffer) | ||
470 | +{ | ||
471 | + int ret = ERROR_SUCCESS; | ||
472 | + | ||
473 | + if ((ret = SrsMpegtsWriter::write_frame(fd, audio_frame, audio_buffer)) != ERROR_SUCCESS) { | ||
474 | + return ret; | ||
475 | + } | ||
476 | + | ||
477 | + _fresh = false; | ||
478 | + | ||
479 | + return ret; | ||
480 | +} | ||
481 | + | ||
482 | +int SrsTSMuxer::write_video(SrsMpegtsFrame* video_frame, SrsCodecBuffer* video_buffer) | ||
483 | +{ | ||
484 | + int ret = ERROR_SUCCESS; | ||
485 | + | ||
486 | + if ((ret = SrsMpegtsWriter::write_frame(fd, video_frame, video_buffer)) != ERROR_SUCCESS) { | ||
487 | + return ret; | ||
488 | + } | ||
489 | + | ||
490 | + return ret; | ||
491 | +} | ||
492 | + | ||
493 | +void SrsTSMuxer::close() | ||
494 | +{ | ||
495 | + if (fd > 0) { | ||
496 | + ::close(fd); | ||
497 | + fd = -1; | ||
498 | + _fresh = false; | ||
499 | + } | ||
500 | +} | ||
501 | + | ||
502 | +bool SrsTSMuxer::fresh() | ||
503 | +{ | ||
504 | + return _fresh; | ||
505 | +} | ||
506 | + | ||
424 | SrsHls::SrsHls() | 507 | SrsHls::SrsHls() |
425 | { | 508 | { |
426 | hls_enabled = false; | 509 | hls_enabled = false; |
@@ -430,7 +513,7 @@ SrsHls::SrsHls() | @@ -430,7 +513,7 @@ SrsHls::SrsHls() | ||
430 | jitter = new SrsRtmpJitter(); | 513 | jitter = new SrsRtmpJitter(); |
431 | aac_jitter = new SrsHlsAacJitter(); | 514 | aac_jitter = new SrsHlsAacJitter(); |
432 | file_index = 0; | 515 | file_index = 0; |
433 | - audio_buffer_start_pts = m3u8_dts = stream_dts = 0; | 516 | + audio_buffer_start_pts = video_stream_dts = 0; |
434 | hls_fragment = hls_window = 0; | 517 | hls_fragment = hls_window = 0; |
435 | 518 | ||
436 | // TODO: config it. | 519 | // TODO: config it. |
@@ -583,14 +666,15 @@ int SrsHls::on_audio(SrsSharedPtrMessage* audio) | @@ -583,14 +666,15 @@ int SrsHls::on_audio(SrsSharedPtrMessage* audio) | ||
583 | return ret; | 666 | return ret; |
584 | } | 667 | } |
585 | 668 | ||
586 | - if ((ret = jitter->correct(audio, 0, 0)) != ERROR_SUCCESS) { | 669 | + int64_t corrected_time = 0; |
670 | + if ((ret = jitter->correct(audio, 0, 0, &corrected_time)) != ERROR_SUCCESS) { | ||
587 | return ret; | 671 | return ret; |
588 | } | 672 | } |
589 | 673 | ||
590 | srs_assert(current); | 674 | srs_assert(current); |
591 | 675 | ||
592 | // the pts calc from rtmp/flv header. | 676 | // the pts calc from rtmp/flv header. |
593 | - int64_t pts = audio->header.timestamp * 90; | 677 | + int64_t pts = corrected_time * 90; |
594 | 678 | ||
595 | // flush if audio delay exceed | 679 | // flush if audio delay exceed |
596 | if (pts - audio_buffer_start_pts > audio_delay * 90) { | 680 | if (pts - audio_buffer_start_pts > audio_delay * 90) { |
@@ -650,7 +734,8 @@ int SrsHls::on_video(SrsSharedPtrMessage* video) | @@ -650,7 +734,8 @@ int SrsHls::on_video(SrsSharedPtrMessage* video) | ||
650 | return ret; | 734 | return ret; |
651 | } | 735 | } |
652 | 736 | ||
653 | - if ((ret = jitter->correct(video, 0, 0)) != ERROR_SUCCESS) { | 737 | + int64_t corrected_time = 0; |
738 | + if ((ret = jitter->correct(video, 0, 0, &corrected_time)) != ERROR_SUCCESS) { | ||
654 | return ret; | 739 | return ret; |
655 | } | 740 | } |
656 | 741 | ||
@@ -659,16 +744,16 @@ int SrsHls::on_video(SrsSharedPtrMessage* video) | @@ -659,16 +744,16 @@ int SrsHls::on_video(SrsSharedPtrMessage* video) | ||
659 | return ret; | 744 | return ret; |
660 | } | 745 | } |
661 | 746 | ||
662 | - stream_dts = video_frame->dts = video->header.timestamp * 90; | 747 | + video_stream_dts = video_frame->dts = corrected_time * 90; |
663 | video_frame->pts = video_frame->dts + sample->cts * 90; | 748 | video_frame->pts = video_frame->dts + sample->cts * 90; |
664 | video_frame->pid = TS_VIDEO_PID; | 749 | video_frame->pid = TS_VIDEO_PID; |
665 | video_frame->sid = TS_VIDEO_AVC; | 750 | video_frame->sid = TS_VIDEO_AVC; |
666 | video_frame->key = sample->frame_type == SrsCodecVideoAVCFrameKeyFrame; | 751 | video_frame->key = sample->frame_type == SrsCodecVideoAVCFrameKeyFrame; |
667 | 752 | ||
668 | // reopen the muxer for a gop | 753 | // reopen the muxer for a gop |
754 | + srs_assert(current); | ||
669 | if (sample->frame_type == SrsCodecVideoAVCFrameKeyFrame) { | 755 | if (sample->frame_type == SrsCodecVideoAVCFrameKeyFrame) { |
670 | - int64_t diff = stream_dts - m3u8_dts; | ||
671 | - if (diff / 90000 >= hls_fragment) { | 756 | + if (current->duration >= hls_fragment) { |
672 | if ((ret = reopen()) != ERROR_SUCCESS) { | 757 | if ((ret = reopen()) != ERROR_SUCCESS) { |
673 | return ret; | 758 | return ret; |
674 | } | 759 | } |
@@ -676,6 +761,9 @@ int SrsHls::on_video(SrsSharedPtrMessage* video) | @@ -676,6 +761,9 @@ int SrsHls::on_video(SrsSharedPtrMessage* video) | ||
676 | } | 761 | } |
677 | 762 | ||
678 | srs_assert(current); | 763 | srs_assert(current); |
764 | + // update the duration of segment. | ||
765 | + current->update_duration(video_stream_dts); | ||
766 | + | ||
679 | if ((ret = current->muxer->write_video(video_frame, video_buffer)) != ERROR_SUCCESS) { | 767 | if ((ret = current->muxer->write_video(video_frame, video_buffer)) != ERROR_SUCCESS) { |
680 | return ret; | 768 | return ret; |
681 | } | 769 | } |
@@ -712,11 +800,8 @@ int SrsHls::reopen() | @@ -712,11 +800,8 @@ int SrsHls::reopen() | ||
712 | return ret; | 800 | return ret; |
713 | } | 801 | } |
714 | 802 | ||
715 | - // start new segment. | 803 | + // close current segment and update the m3u8 file. |
716 | if (current) { | 804 | if (current) { |
717 | - current->duration = (stream_dts - current->segment_start_dts) / 90000.0; | ||
718 | - srs_assert(current->duration > 0); | ||
719 | - | ||
720 | // assert segment duplicate. | 805 | // assert segment duplicate. |
721 | std::vector<SrsM3u8Segment*>::iterator it; | 806 | std::vector<SrsM3u8Segment*>::iterator it; |
722 | it = std::find(segments.begin(), segments.end(), current); | 807 | it = std::find(segments.begin(), segments.end(), current); |
@@ -774,7 +859,7 @@ int SrsHls::reopen() | @@ -774,7 +859,7 @@ int SrsHls::reopen() | ||
774 | // new segment. | 859 | // new segment. |
775 | current = new SrsM3u8Segment(); | 860 | current = new SrsM3u8Segment(); |
776 | current->sequence_no = file_index++; | 861 | current->sequence_no = file_index++; |
777 | - m3u8_dts = current->segment_start_dts = stream_dts; | 862 | + current->segment_start_dts = video_stream_dts; |
778 | 863 | ||
779 | // generate filename. | 864 | // generate filename. |
780 | char filename[128]; | 865 | char filename[128]; |
@@ -1106,80 +1191,5 @@ int SrsHls::flush_audio() | @@ -1106,80 +1191,5 @@ int SrsHls::flush_audio() | ||
1106 | return ret; | 1191 | return ret; |
1107 | } | 1192 | } |
1108 | 1193 | ||
1109 | -SrsTSMuxer::SrsTSMuxer() | ||
1110 | -{ | ||
1111 | - fd = -1; | ||
1112 | - _fresh = false; | ||
1113 | -} | ||
1114 | - | ||
1115 | -SrsTSMuxer::~SrsTSMuxer() | ||
1116 | -{ | ||
1117 | - close(); | ||
1118 | -} | ||
1119 | - | ||
1120 | -int SrsTSMuxer::open(std::string _path) | ||
1121 | -{ | ||
1122 | - int ret = ERROR_SUCCESS; | ||
1123 | - | ||
1124 | - path = _path; | ||
1125 | - | ||
1126 | - close(); | ||
1127 | - | ||
1128 | - int flags = O_CREAT|O_WRONLY|O_TRUNC; | ||
1129 | - mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH; | ||
1130 | - if ((fd = ::open(path.c_str(), flags, mode)) < 0) { | ||
1131 | - ret = ERROR_HLS_OPEN_FAILED; | ||
1132 | - srs_error("open ts file %s failed. ret=%d", path.c_str(), ret); | ||
1133 | - return ret; | ||
1134 | - } | ||
1135 | - | ||
1136 | - // write mpegts header | ||
1137 | - if ((ret = SrsMpegtsWriter::write_header(fd)) != ERROR_SUCCESS) { | ||
1138 | - return ret; | ||
1139 | - } | ||
1140 | - | ||
1141 | - _fresh = true; | ||
1142 | - | ||
1143 | - return ret; | ||
1144 | -} | ||
1145 | - | ||
1146 | -int SrsTSMuxer::write_audio(SrsMpegtsFrame* audio_frame, SrsCodecBuffer* audio_buffer) | ||
1147 | -{ | ||
1148 | - int ret = ERROR_SUCCESS; | ||
1149 | - | ||
1150 | - if ((ret = SrsMpegtsWriter::write_frame(fd, audio_frame, audio_buffer)) != ERROR_SUCCESS) { | ||
1151 | - return ret; | ||
1152 | - } | ||
1153 | - | ||
1154 | - _fresh = false; | ||
1155 | - | ||
1156 | - return ret; | ||
1157 | -} | ||
1158 | - | ||
1159 | -int SrsTSMuxer::write_video(SrsMpegtsFrame* video_frame, SrsCodecBuffer* video_buffer) | ||
1160 | -{ | ||
1161 | - int ret = ERROR_SUCCESS; | ||
1162 | - | ||
1163 | - if ((ret = SrsMpegtsWriter::write_frame(fd, video_frame, video_buffer)) != ERROR_SUCCESS) { | ||
1164 | - return ret; | ||
1165 | - } | ||
1166 | - | ||
1167 | - return ret; | ||
1168 | -} | ||
1169 | - | ||
1170 | -void SrsTSMuxer::close() | ||
1171 | -{ | ||
1172 | - if (fd > 0) { | ||
1173 | - ::close(fd); | ||
1174 | - fd = -1; | ||
1175 | - _fresh = false; | ||
1176 | - } | ||
1177 | -} | ||
1178 | - | ||
1179 | -bool SrsTSMuxer::fresh() | ||
1180 | -{ | ||
1181 | - return _fresh; | ||
1182 | -} | ||
1183 | - | ||
1184 | #endif | 1194 | #endif |
1185 | 1195 |
@@ -45,29 +45,6 @@ class SrsCodec; | @@ -45,29 +45,6 @@ class SrsCodec; | ||
45 | class SrsRequest; | 45 | class SrsRequest; |
46 | 46 | ||
47 | /** | 47 | /** |
48 | -* 3.3.2. EXTINF | ||
49 | -* The EXTINF tag specifies the duration of a media segment. | ||
50 | -*/ | ||
51 | -struct SrsM3u8Segment | ||
52 | -{ | ||
53 | - // duration in seconds in m3u8. | ||
54 | - double duration; | ||
55 | - // sequence number in m3u8. | ||
56 | - int sequence_no; | ||
57 | - // ts uri in m3u8. | ||
58 | - std::string uri; | ||
59 | - // ts full file to write. | ||
60 | - std::string full_path; | ||
61 | - // the muxer to write ts. | ||
62 | - SrsTSMuxer* muxer; | ||
63 | - // current segment start dts for m3u8 | ||
64 | - int64_t segment_start_dts; | ||
65 | - | ||
66 | - SrsM3u8Segment(); | ||
67 | - virtual ~SrsM3u8Segment(); | ||
68 | -}; | ||
69 | - | ||
70 | -/** | ||
71 | * jitter correct for audio, | 48 | * jitter correct for audio, |
72 | * the sample rate 44100/32000 will lost precise, | 49 | * the sample rate 44100/32000 will lost precise, |
73 | * when mp4/ts(tbn=90000) covert to flv/rtmp(1000), | 50 | * when mp4/ts(tbn=90000) covert to flv/rtmp(1000), |
@@ -98,6 +75,52 @@ public: | @@ -98,6 +75,52 @@ public: | ||
98 | }; | 75 | }; |
99 | 76 | ||
100 | /** | 77 | /** |
78 | +* 3.3.2. EXTINF | ||
79 | +* The EXTINF tag specifies the duration of a media segment. | ||
80 | +*/ | ||
81 | +struct SrsM3u8Segment | ||
82 | +{ | ||
83 | + // duration in seconds in m3u8. | ||
84 | + double duration; | ||
85 | + // sequence number in m3u8. | ||
86 | + int sequence_no; | ||
87 | + // ts uri in m3u8. | ||
88 | + std::string uri; | ||
89 | + // ts full file to write. | ||
90 | + std::string full_path; | ||
91 | + // the muxer to write ts. | ||
92 | + SrsTSMuxer* muxer; | ||
93 | + // current segment start dts for m3u8 | ||
94 | + int64_t segment_start_dts; | ||
95 | + | ||
96 | + SrsM3u8Segment(); | ||
97 | + virtual ~SrsM3u8Segment(); | ||
98 | + | ||
99 | + /** | ||
100 | + * update the segment duration. | ||
101 | + */ | ||
102 | + virtual double update_duration(int64_t video_stream_dts); | ||
103 | +}; | ||
104 | + | ||
105 | +//TODO: refine the ts muxer, do more jobs. | ||
106 | +class SrsTSMuxer | ||
107 | +{ | ||
108 | +private: | ||
109 | + int fd; | ||
110 | + std::string path; | ||
111 | + bool _fresh; | ||
112 | +public: | ||
113 | + SrsTSMuxer(); | ||
114 | + virtual ~SrsTSMuxer(); | ||
115 | +public: | ||
116 | + virtual int open(std::string _path); | ||
117 | + virtual int write_audio(SrsMpegtsFrame* audio_frame, SrsCodecBuffer* audio_buffer); | ||
118 | + virtual int write_video(SrsMpegtsFrame* video_frame, SrsCodecBuffer* video_buffer); | ||
119 | + virtual void close(); | ||
120 | + virtual bool fresh(); | ||
121 | +}; | ||
122 | + | ||
123 | +/** | ||
101 | * write m3u8 hls. | 124 | * write m3u8 hls. |
102 | */ | 125 | */ |
103 | class SrsHls | 126 | class SrsHls |
@@ -127,10 +150,8 @@ private: | @@ -127,10 +150,8 @@ private: | ||
127 | SrsMpegtsFrame* video_frame; | 150 | SrsMpegtsFrame* video_frame; |
128 | SrsCodecBuffer* video_buffer; | 151 | SrsCodecBuffer* video_buffer; |
129 | // last known dts | 152 | // last known dts |
130 | - int64_t stream_dts; | 153 | + int64_t video_stream_dts; |
131 | int64_t audio_buffer_start_pts; | 154 | int64_t audio_buffer_start_pts; |
132 | - // last segment dts in m3u8 | ||
133 | - int64_t m3u8_dts; | ||
134 | // in ms, audio delay to flush the audios. | 155 | // in ms, audio delay to flush the audios. |
135 | int64_t audio_delay; | 156 | int64_t audio_delay; |
136 | private: | 157 | private: |
@@ -159,24 +180,6 @@ private: | @@ -159,24 +180,6 @@ private: | ||
159 | virtual int flush_audio(); | 180 | virtual int flush_audio(); |
160 | }; | 181 | }; |
161 | 182 | ||
162 | -//TODO: refine the ts muxer, do more jobs. | ||
163 | -class SrsTSMuxer | ||
164 | -{ | ||
165 | -private: | ||
166 | - int fd; | ||
167 | - std::string path; | ||
168 | - bool _fresh; | ||
169 | -public: | ||
170 | - SrsTSMuxer(); | ||
171 | - virtual ~SrsTSMuxer(); | ||
172 | -public: | ||
173 | - virtual int open(std::string _path); | ||
174 | - virtual int write_audio(SrsMpegtsFrame* audio_frame, SrsCodecBuffer* audio_buffer); | ||
175 | - virtual int write_video(SrsMpegtsFrame* video_frame, SrsCodecBuffer* video_buffer); | ||
176 | - virtual void close(); | ||
177 | - virtual bool fresh(); | ||
178 | -}; | ||
179 | - | ||
180 | #endif | 183 | #endif |
181 | 184 | ||
182 | #endif | 185 | #endif |
@@ -49,7 +49,7 @@ SrsRtmpJitter::~SrsRtmpJitter() | @@ -49,7 +49,7 @@ SrsRtmpJitter::~SrsRtmpJitter() | ||
49 | { | 49 | { |
50 | } | 50 | } |
51 | 51 | ||
52 | -int SrsRtmpJitter::correct(SrsSharedPtrMessage* msg, int tba, int tbv) | 52 | +int SrsRtmpJitter::correct(SrsSharedPtrMessage* msg, int tba, int tbv, int64_t* corrected_time) |
53 | { | 53 | { |
54 | int ret = ERROR_SUCCESS; | 54 | int ret = ERROR_SUCCESS; |
55 | 55 | ||
@@ -93,7 +93,12 @@ int SrsRtmpJitter::correct(SrsSharedPtrMessage* msg, int tba, int tbv) | @@ -93,7 +93,12 @@ int SrsRtmpJitter::correct(SrsSharedPtrMessage* msg, int tba, int tbv) | ||
93 | } | 93 | } |
94 | 94 | ||
95 | last_pkt_correct_time = srs_max(0, last_pkt_correct_time + delta); | 95 | last_pkt_correct_time = srs_max(0, last_pkt_correct_time + delta); |
96 | + | ||
97 | + if (corrected_time) { | ||
98 | + *corrected_time = last_pkt_correct_time; | ||
99 | + } | ||
96 | msg->header.timestamp = last_pkt_correct_time; | 100 | msg->header.timestamp = last_pkt_correct_time; |
101 | + | ||
97 | last_pkt_time = time; | 102 | last_pkt_time = time; |
98 | 103 | ||
99 | return ret; | 104 | return ret; |
@@ -62,8 +62,10 @@ public: | @@ -62,8 +62,10 @@ public: | ||
62 | public: | 62 | public: |
63 | /** | 63 | /** |
64 | * detect the time jitter and correct it. | 64 | * detect the time jitter and correct it. |
65 | + * @param corrected_time output the 64bits time. | ||
66 | + * ignore if NULL. | ||
65 | */ | 67 | */ |
66 | - virtual int correct(SrsSharedPtrMessage* msg, int tba, int tbv); | 68 | + virtual int correct(SrsSharedPtrMessage* msg, int tba, int tbv, int64_t* corrected_time = NULL); |
67 | /** | 69 | /** |
68 | * get current client time, the last packet time. | 70 | * get current client time, the last packet time. |
69 | */ | 71 | */ |
-
请 注册 或 登录 后发表评论