winlin

fix the aac jump bug on iphone, correct the audio pts, use audio buffer and flush audio

@@ -34,7 +34,7 @@ For example, use ffmpeg to publish: @@ -34,7 +34,7 @@ For example, use ffmpeg to publish:
34 step 5: play live stream <br/> 34 step 5: play live stream <br/>
35 <pre> 35 <pre>
36 rtmp url: rtmp://127.0.0.1:1935/live/livestream 36 rtmp url: rtmp://127.0.0.1:1935/live/livestream
37 -m3u8 url: http://127.0.0.1:1935/live/livestream.m3u8 37 +m3u8 url: http://127.0.0.1:80/live/livestream.m3u8
38 </pre> 38 </pre>
39 39
40 ### Summary 40 ### Summary
@@ -13,8 +13,8 @@ vhost __defaultVhost__ { @@ -13,8 +13,8 @@ vhost __defaultVhost__ {
13 gop_cache on; 13 gop_cache on;
14 hls on; 14 hls on;
15 hls_path ./objs/nginx/html; 15 hls_path ./objs/nginx/html;
16 - hls_fragment 10;  
17 - hls_window 60; 16 + hls_fragment 5;
  17 + hls_window 30;
18 } 18 }
19 # the vhost disabled. 19 # the vhost disabled.
20 vhost removed.vhost.com { 20 vhost removed.vhost.com {
@@ -159,7 +159,7 @@ int SrsCodec::audio_aac_demux(int8_t* data, int size, SrsCodecSample* sample) @@ -159,7 +159,7 @@ int SrsCodec::audio_aac_demux(int8_t* data, int size, SrsCodecSample* sample)
159 159
160 int8_t sound_type = sound_format & 0x01; 160 int8_t sound_type = sound_format & 0x01;
161 int8_t sound_size = (sound_format >> 1) & 0x01; 161 int8_t sound_size = (sound_format >> 1) & 0x01;
162 - int8_t sound_rate = (sound_format >> 2) & 0x01; 162 + int8_t sound_rate = (sound_format >> 2) & 0x03;
163 sound_format = (sound_format >> 4) & 0x0f; 163 sound_format = (sound_format >> 4) & 0x0f;
164 164
165 audio_codec_id = sound_format; 165 audio_codec_id = sound_format;
@@ -167,6 +167,25 @@ int SrsCodec::audio_aac_demux(int8_t* data, int size, SrsCodecSample* sample) @@ -167,6 +167,25 @@ int SrsCodec::audio_aac_demux(int8_t* data, int size, SrsCodecSample* sample)
167 sample->sound_rate = (SrsCodecAudioSampleRate)sound_rate; 167 sample->sound_rate = (SrsCodecAudioSampleRate)sound_rate;
168 sample->sound_size = (SrsCodecAudioSampleSize)sound_size; 168 sample->sound_size = (SrsCodecAudioSampleSize)sound_size;
169 169
  170 + // reset the sample rate by sequence header
  171 + static int aac_sample_rates[] = {
  172 + 96000, 88200, 64000, 48000,
  173 + 44100, 32000, 24000, 22050,
  174 + 16000, 12000, 11025, 8000,
  175 + 7350, 0, 0, 0
  176 + };
  177 + switch (aac_sample_rates[aac_sample_rate]) {
  178 + case 11025:
  179 + sample->sound_rate = SrsCodecAudioSampleRate11025;
  180 + break;
  181 + case 22050:
  182 + sample->sound_rate = SrsCodecAudioSampleRate22050;
  183 + break;
  184 + case 44100:
  185 + sample->sound_rate = SrsCodecAudioSampleRate44100;
  186 + break;
  187 + };
  188 +
170 // only support aac 189 // only support aac
171 if (audio_codec_id != SrsCodecAudioAAC) { 190 if (audio_codec_id != SrsCodecAudioAAC) {
172 ret = ERROR_HLS_DECODE_ERROR; 191 ret = ERROR_HLS_DECODE_ERROR;
@@ -40,6 +40,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -40,6 +40,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
40 #define SRS_CONF_DEFAULT_HLS_PATH "./objs/nginx/html" 40 #define SRS_CONF_DEFAULT_HLS_PATH "./objs/nginx/html"
41 #define SRS_CONF_DEFAULT_HLS_FRAGMENT 10 41 #define SRS_CONF_DEFAULT_HLS_FRAGMENT 10
42 #define SRS_CONF_DEFAULT_HLS_WINDOW 60 42 #define SRS_CONF_DEFAULT_HLS_WINDOW 60
  43 +// in ms, for HLS aac sync time.
  44 +#define SRS_CONF_DEFAULT_AAC_SYNC 100
  45 +// in ms, for HLS aac flush the audio
  46 +#define SRS_CONF_DEFAULT_AAC_DELAY 300
43 47
44 class SrsFileBuffer 48 class SrsFileBuffer
45 { 49 {
@@ -269,9 +269,6 @@ public: @@ -269,9 +269,6 @@ public:
269 } 269 }
270 } 270 }
271 271
272 - // write success, clear and free the buffer  
273 - buffer->free();  
274 -  
275 return ret; 272 return ret;
276 } 273 }
277 private: 274 private:
@@ -360,16 +357,79 @@ SrsM3u8Segment::~SrsM3u8Segment() @@ -360,16 +357,79 @@ SrsM3u8Segment::~SrsM3u8Segment()
360 srs_freep(muxer); 357 srs_freep(muxer);
361 } 358 }
362 359
363 -SrsHLS::SrsHLS() 360 +SrsHlsAacJitter::SrsHlsAacJitter()
  361 +{
  362 + base_pts = 0;
  363 + nb_samples = 0;
  364 +
  365 + // TODO: config it, 0 means no adjust
  366 + sync_ms = SRS_CONF_DEFAULT_AAC_SYNC;
  367 +}
  368 +
  369 +SrsHlsAacJitter::~SrsHlsAacJitter()
  370 +{
  371 +}
  372 +
  373 +int64_t SrsHlsAacJitter::on_buffer_start(int64_t flv_pts, int sample_rate)
  374 +{
  375 + // 0 = 5.5 kHz = 5512 Hz
  376 + // 1 = 11 kHz = 11025 Hz
  377 + // 2 = 22 kHz = 22050 Hz
  378 + // 3 = 44 kHz = 44100 Hz
  379 + static int flv_sample_rates[] = {5512, 11025, 22050, 44100};
  380 + int flv_sample_rate = flv_sample_rates[sample_rate & 0x03];
  381 +
  382 + // sync time set to 0, donot adjust the aac timestamp.
  383 + if (!sync_ms) {
  384 + return flv_pts;
  385 + }
  386 +
  387 + // @see: ngx_rtmp_hls_audio
  388 + /* TODO: We assume here AAC frame size is 1024
  389 + * Need to handle AAC frames with frame size of 960 */
  390 + int64_t est_pts = base_pts + nb_samples * 90000LL * 1024LL / flv_sample_rate;
  391 + int64_t dpts = (int64_t) (est_pts - flv_pts);
  392 +
  393 + if (dpts <= (int64_t) sync_ms * 90 && dpts >= (int64_t) sync_ms * -90) {
  394 + srs_info("HLS correct aac pts "
  395 + "from %"PRId64" to %"PRId64", base=%"PRId64", nb_samples=%d, sample_rate=%d",
  396 + flv_pts, est_pts, nb_samples, flv_sample_rate, base_pts);
  397 +
  398 + nb_samples++;
  399 +
  400 + return est_pts;
  401 + }
  402 +
  403 + // resync
  404 + srs_trace("HLS aac resync, dpts=%"PRId64", pts=%"PRId64
  405 + ", base=%"PRId64", nb_samples=%"PRId64", sample_rate=%d",
  406 + dpts, flv_pts, base_pts, nb_samples, flv_sample_rate);
  407 +
  408 + base_pts = flv_pts;
  409 + nb_samples = 1;
  410 +
  411 + return flv_pts;
  412 +}
  413 +
  414 +void SrsHlsAacJitter::on_buffer_continue()
  415 +{
  416 + nb_samples++;
  417 +}
  418 +
  419 +SrsHls::SrsHls()
364 { 420 {
365 hls_enabled = false; 421 hls_enabled = false;
366 codec = new SrsCodec(); 422 codec = new SrsCodec();
367 sample = new SrsCodecSample(); 423 sample = new SrsCodecSample();
368 current = NULL; 424 current = NULL;
369 jitter = new SrsRtmpJitter(); 425 jitter = new SrsRtmpJitter();
  426 + aac_jitter = new SrsHlsAacJitter();
370 file_index = 0; 427 file_index = 0;
371 - m3u8_dts = stream_dts = 0; 428 + audio_buffer_start_pts = m3u8_dts = stream_dts = 0;
372 hls_fragment = hls_window = 0; 429 hls_fragment = hls_window = 0;
  430 +
  431 + // TODO: config it.
  432 + audio_delay = SRS_CONF_DEFAULT_AAC_DELAY;
373 433
374 audio_buffer = new SrsCodecBuffer(); 434 audio_buffer = new SrsCodecBuffer();
375 video_buffer = new SrsCodecBuffer(); 435 video_buffer = new SrsCodecBuffer();
@@ -378,11 +438,12 @@ SrsHLS::SrsHLS() @@ -378,11 +438,12 @@ SrsHLS::SrsHLS()
378 video_frame = new SrsMpegtsFrame(); 438 video_frame = new SrsMpegtsFrame();
379 } 439 }
380 440
381 -SrsHLS::~SrsHLS() 441 +SrsHls::~SrsHls()
382 { 442 {
383 srs_freep(codec); 443 srs_freep(codec);
384 srs_freep(sample); 444 srs_freep(sample);
385 srs_freep(jitter); 445 srs_freep(jitter);
  446 + srs_freep(aac_jitter);
386 447
387 std::vector<SrsM3u8Segment*>::iterator it; 448 std::vector<SrsM3u8Segment*>::iterator it;
388 for (it = segments.begin(); it != segments.end(); ++it) { 449 for (it = segments.begin(); it != segments.end(); ++it) {
@@ -403,7 +464,7 @@ SrsHLS::~SrsHLS() @@ -403,7 +464,7 @@ SrsHLS::~SrsHLS()
403 srs_freep(video_frame); 464 srs_freep(video_frame);
404 } 465 }
405 466
406 -int SrsHLS::on_publish(std::string _vhost, std::string _app, std::string _stream) 467 +int SrsHls::on_publish(std::string _vhost, std::string _app, std::string _stream)
407 { 468 {
408 int ret = ERROR_SUCCESS; 469 int ret = ERROR_SUCCESS;
409 470
@@ -435,12 +496,12 @@ int SrsHLS::on_publish(std::string _vhost, std::string _app, std::string _stream @@ -435,12 +496,12 @@ int SrsHLS::on_publish(std::string _vhost, std::string _app, std::string _stream
435 return ret; 496 return ret;
436 } 497 }
437 498
438 -void SrsHLS::on_unpublish() 499 +void SrsHls::on_unpublish()
439 { 500 {
440 hls_enabled = false; 501 hls_enabled = false;
441 } 502 }
442 503
443 -int SrsHLS::on_meta_data(SrsOnMetaDataPacket* metadata) 504 +int SrsHls::on_meta_data(SrsOnMetaDataPacket* metadata)
444 { 505 {
445 int ret = ERROR_SUCCESS; 506 int ret = ERROR_SUCCESS;
446 507
@@ -492,7 +553,7 @@ int SrsHLS::on_meta_data(SrsOnMetaDataPacket* metadata) @@ -492,7 +553,7 @@ int SrsHLS::on_meta_data(SrsOnMetaDataPacket* metadata)
492 return ret; 553 return ret;
493 } 554 }
494 555
495 -int SrsHLS::on_audio(SrsSharedPtrMessage* audio) 556 +int SrsHls::on_audio(SrsSharedPtrMessage* audio)
496 { 557 {
497 int ret = ERROR_SUCCESS; 558 int ret = ERROR_SUCCESS;
498 559
@@ -523,18 +584,43 @@ int SrsHLS::on_audio(SrsSharedPtrMessage* audio) @@ -523,18 +584,43 @@ int SrsHLS::on_audio(SrsSharedPtrMessage* audio)
523 584
524 srs_assert(current); 585 srs_assert(current);
525 586
526 - stream_dts = audio_frame->dts = audio_frame->pts = audio->header.timestamp * 90;  
527 - audio_frame->pid = TS_AUDIO_PID;  
528 - audio_frame->sid = TS_AUDIO_AAC; 587 + // the pts calc from rtmp/flv header.
  588 + int64_t pts = audio->header.timestamp * 90;
  589 +
  590 + // flush if audio delay exceed
  591 + if (pts - audio_buffer_start_pts > audio_delay * 90) {
  592 + if ((ret = flush_audio()) != ERROR_SUCCESS) {
  593 + return ret;
  594 + }
  595 + }
529 596
530 - if ((ret = current->muxer->write_audio(audio_frame, audio_buffer, codec, sample)) != ERROR_SUCCESS) { 597 + // start buffer, set the audio_frame
  598 + if (audio_buffer->size == 0) {
  599 + pts = aac_jitter->on_buffer_start(pts, sample->sound_rate);
  600 +
  601 + audio_frame->dts = audio_frame->pts = audio_buffer_start_pts = pts;
  602 + audio_frame->pid = TS_AUDIO_PID;
  603 + audio_frame->sid = TS_AUDIO_AAC;
  604 + } else {
  605 + aac_jitter->on_buffer_continue();
  606 + }
  607 +
  608 + // write audio to cache.
  609 + if ((ret = write_audio()) != ERROR_SUCCESS) {
531 return ret; 610 return ret;
532 } 611 }
533 612
  613 + // write cache to file.
  614 + if (audio_buffer->size > 1024 * 1024) {
  615 + if ((ret = flush_audio()) != ERROR_SUCCESS) {
  616 + return ret;
  617 + }
  618 + }
  619 +
534 return ret; 620 return ret;
535 } 621 }
536 622
537 -int SrsHLS::on_video(SrsSharedPtrMessage* video) 623 +int SrsHls::on_video(SrsSharedPtrMessage* video)
538 { 624 {
539 int ret = ERROR_SUCCESS; 625 int ret = ERROR_SUCCESS;
540 626
@@ -563,6 +649,11 @@ int SrsHLS::on_video(SrsSharedPtrMessage* video) @@ -563,6 +649,11 @@ int SrsHLS::on_video(SrsSharedPtrMessage* video)
563 return ret; 649 return ret;
564 } 650 }
565 651
  652 + // write video to cache.
  653 + if ((ret = write_video()) != ERROR_SUCCESS) {
  654 + return ret;
  655 + }
  656 +
566 stream_dts = video_frame->dts = video->header.timestamp * 90; 657 stream_dts = video_frame->dts = video->header.timestamp * 90;
567 video_frame->pts = video_frame->dts + sample->cts * 90; 658 video_frame->pts = video_frame->dts + sample->cts * 90;
568 video_frame->pid = TS_VIDEO_PID; 659 video_frame->pid = TS_VIDEO_PID;
@@ -580,14 +671,17 @@ int SrsHLS::on_video(SrsSharedPtrMessage* video) @@ -580,14 +671,17 @@ int SrsHLS::on_video(SrsSharedPtrMessage* video)
580 } 671 }
581 672
582 srs_assert(current); 673 srs_assert(current);
583 - if ((ret = current->muxer->write_video(video_frame, video_buffer, codec, sample)) != ERROR_SUCCESS) { 674 + if ((ret = current->muxer->write_video(video_frame, video_buffer)) != ERROR_SUCCESS) {
584 return ret; 675 return ret;
585 } 676 }
  677 +
  678 + // write success, clear and free the buffer
  679 + video_buffer->free();
586 680
587 return ret; 681 return ret;
588 } 682 }
589 683
590 -int SrsHLS::reopen() 684 +int SrsHls::reopen()
591 { 685 {
592 int ret = ERROR_SUCCESS; 686 int ret = ERROR_SUCCESS;
593 687
@@ -675,10 +769,19 @@ int SrsHLS::reopen() @@ -675,10 +769,19 @@ int SrsHLS::reopen()
675 } 769 }
676 srs_info("open HLS muxer success. vhost=%s, path=%s", vhost.c_str(), current->full_path.c_str()); 770 srs_info("open HLS muxer success. vhost=%s, path=%s", vhost.c_str(), current->full_path.c_str());
677 771
  772 + // segment open, flush the audio.
  773 + // @see: ngx_rtmp_hls_open_fragment
  774 + /* start fragment with audio to make iPhone happy */
  775 + if (current->muxer->fresh()) {
  776 + if ((ret = flush_audio()) != ERROR_SUCCESS) {
  777 + return ret;
  778 + }
  779 + }
  780 +
678 return ret; 781 return ret;
679 } 782 }
680 783
681 -int SrsHLS::refresh_m3u8() 784 +int SrsHls::refresh_m3u8()
682 { 785 {
683 int ret = ERROR_SUCCESS; 786 int ret = ERROR_SUCCESS;
684 787
@@ -708,7 +811,7 @@ int SrsHLS::refresh_m3u8() @@ -708,7 +811,7 @@ int SrsHLS::refresh_m3u8()
708 return ret; 811 return ret;
709 } 812 }
710 813
711 -int SrsHLS::_refresh_m3u8(int& fd, std::string m3u8_file) 814 +int SrsHls::_refresh_m3u8(int& fd, std::string m3u8_file)
712 { 815 {
713 int ret = ERROR_SUCCESS; 816 int ret = ERROR_SUCCESS;
714 817
@@ -799,7 +902,7 @@ int SrsHLS::_refresh_m3u8(int& fd, std::string m3u8_file) @@ -799,7 +902,7 @@ int SrsHLS::_refresh_m3u8(int& fd, std::string m3u8_file)
799 return ret; 902 return ret;
800 } 903 }
801 904
802 -int SrsHLS::create_dir() 905 +int SrsHls::create_dir()
803 { 906 {
804 int ret = ERROR_SUCCESS; 907 int ret = ERROR_SUCCESS;
805 908
@@ -822,41 +925,7 @@ int SrsHLS::create_dir() @@ -822,41 +925,7 @@ int SrsHLS::create_dir()
822 return ret; 925 return ret;
823 } 926 }
824 927
825 -SrsTSMuxer::SrsTSMuxer()  
826 -{  
827 - fd = -1;  
828 -}  
829 -  
830 -SrsTSMuxer::~SrsTSMuxer()  
831 -{  
832 - close();  
833 -}  
834 -  
835 -int SrsTSMuxer::open(std::string _path)  
836 -{  
837 - int ret = ERROR_SUCCESS;  
838 -  
839 - path = _path;  
840 -  
841 - close();  
842 -  
843 - int flags = O_CREAT|O_WRONLY|O_TRUNC;  
844 - mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH;  
845 - if ((fd = ::open(path.c_str(), flags, mode)) < 0) {  
846 - ret = ERROR_HLS_OPEN_FAILED;  
847 - srs_error("open ts file %s failed. ret=%d", path.c_str(), ret);  
848 - return ret;  
849 - }  
850 -  
851 - // write mpegts header  
852 - if ((ret = SrsMpegtsWriter::write_header(fd)) != ERROR_SUCCESS) {  
853 - return ret;  
854 - }  
855 -  
856 - return ret;  
857 -}  
858 -  
859 -int SrsTSMuxer::write_audio(SrsMpegtsFrame* audio_frame, SrsCodecBuffer* audio_buffer, SrsCodec* codec, SrsCodecSample* sample) 928 +int SrsHls::write_audio()
860 { 929 {
861 int ret = ERROR_SUCCESS; 930 int ret = ERROR_SUCCESS;
862 931
@@ -920,14 +989,10 @@ int SrsTSMuxer::write_audio(SrsMpegtsFrame* audio_frame, SrsCodecBuffer* audio_b @@ -920,14 +989,10 @@ int SrsTSMuxer::write_audio(SrsMpegtsFrame* audio_frame, SrsCodecBuffer* audio_b
920 audio_buffer->append(buf->bytes, buf->size); 989 audio_buffer->append(buf->bytes, buf->size);
921 } 990 }
922 991
923 - if ((ret = SrsMpegtsWriter::write_frame(fd, audio_frame, audio_buffer)) != ERROR_SUCCESS) {  
924 - return ret;  
925 - }  
926 -  
927 return ret; 992 return ret;
928 } 993 }
929 994
930 -int SrsTSMuxer::write_video(SrsMpegtsFrame* video_frame, SrsCodecBuffer* video_buffer, SrsCodec* codec, SrsCodecSample* sample) 995 +int SrsHls::write_video()
931 { 996 {
932 int ret = ERROR_SUCCESS; 997 int ret = ERROR_SUCCESS;
933 998
@@ -991,6 +1056,81 @@ int SrsTSMuxer::write_video(SrsMpegtsFrame* video_frame, SrsCodecBuffer* video_b @@ -991,6 +1056,81 @@ int SrsTSMuxer::write_video(SrsMpegtsFrame* video_frame, SrsCodecBuffer* video_b
991 video_buffer->append(buf->bytes, buf->size); 1056 video_buffer->append(buf->bytes, buf->size);
992 } 1057 }
993 1058
  1059 + return ret;
  1060 +}
  1061 +
  1062 +int SrsHls::flush_audio()
  1063 +{
  1064 + int ret = ERROR_SUCCESS;
  1065 +
  1066 + if (audio_buffer->size <= 0) {
  1067 + return ret;
  1068 + }
  1069 +
  1070 + if ((ret = current->muxer->write_audio(audio_frame, audio_buffer)) != ERROR_SUCCESS) {
  1071 + return ret;
  1072 + }
  1073 +
  1074 + // write success, clear and free the buffer
  1075 + audio_buffer->free();
  1076 +
  1077 + return ret;
  1078 +}
  1079 +
  1080 +SrsTSMuxer::SrsTSMuxer()
  1081 +{
  1082 + fd = -1;
  1083 + _fresh = false;
  1084 +}
  1085 +
  1086 +SrsTSMuxer::~SrsTSMuxer()
  1087 +{
  1088 + close();
  1089 +}
  1090 +
  1091 +int SrsTSMuxer::open(std::string _path)
  1092 +{
  1093 + int ret = ERROR_SUCCESS;
  1094 +
  1095 + path = _path;
  1096 +
  1097 + close();
  1098 +
  1099 + int flags = O_CREAT|O_WRONLY|O_TRUNC;
  1100 + mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH;
  1101 + if ((fd = ::open(path.c_str(), flags, mode)) < 0) {
  1102 + ret = ERROR_HLS_OPEN_FAILED;
  1103 + srs_error("open ts file %s failed. ret=%d", path.c_str(), ret);
  1104 + return ret;
  1105 + }
  1106 +
  1107 + // write mpegts header
  1108 + if ((ret = SrsMpegtsWriter::write_header(fd)) != ERROR_SUCCESS) {
  1109 + return ret;
  1110 + }
  1111 +
  1112 + _fresh = true;
  1113 +
  1114 + return ret;
  1115 +}
  1116 +
  1117 +int SrsTSMuxer::write_audio(SrsMpegtsFrame* audio_frame, SrsCodecBuffer* audio_buffer)
  1118 +{
  1119 + int ret = ERROR_SUCCESS;
  1120 +
  1121 + if ((ret = SrsMpegtsWriter::write_frame(fd, audio_frame, audio_buffer)) != ERROR_SUCCESS) {
  1122 + return ret;
  1123 + }
  1124 +
  1125 + _fresh = false;
  1126 +
  1127 + return ret;
  1128 +}
  1129 +
  1130 +int SrsTSMuxer::write_video(SrsMpegtsFrame* video_frame, SrsCodecBuffer* video_buffer)
  1131 +{
  1132 + int ret = ERROR_SUCCESS;
  1133 +
994 if ((ret = SrsMpegtsWriter::write_frame(fd, video_frame, video_buffer)) != ERROR_SUCCESS) { 1134 if ((ret = SrsMpegtsWriter::write_frame(fd, video_frame, video_buffer)) != ERROR_SUCCESS) {
995 return ret; 1135 return ret;
996 } 1136 }
@@ -1003,6 +1143,12 @@ void SrsTSMuxer::close() @@ -1003,6 +1143,12 @@ void SrsTSMuxer::close()
1003 if (fd > 0) { 1143 if (fd > 0) {
1004 ::close(fd); 1144 ::close(fd);
1005 fd = -1; 1145 fd = -1;
  1146 + _fresh = false;
1006 } 1147 }
1007 } 1148 }
1008 1149
  1150 +bool SrsTSMuxer::fresh()
  1151 +{
  1152 + return _fresh;
  1153 +}
  1154 +
@@ -65,9 +65,39 @@ struct SrsM3u8Segment @@ -65,9 +65,39 @@ struct SrsM3u8Segment
65 }; 65 };
66 66
67 /** 67 /**
  68 +* jitter correct for audio,
  69 +* the sample rate 44100/32000 will lost precise,
  70 +* when mp4/ts(tbn=90000) covert to flv/rtmp(1000),
  71 +* so the Hls on ipad or iphone will corrupt,
  72 +* @see nginx-rtmp: est_pts
  73 +*/
  74 +class SrsHlsAacJitter
  75 +{
  76 +private:
  77 + int64_t base_pts;
  78 + int64_t nb_samples;
  79 + int sync_ms;
  80 +public:
  81 + SrsHlsAacJitter();
  82 + virtual ~SrsHlsAacJitter();
  83 + /**
  84 + * when buffer start, calc the "correct" pts for ts,
  85 + * @param flv_pts, the flv pts calc from flv header timestamp,
  86 + * @return the calc correct pts.
  87 + */
  88 + virtual int64_t on_buffer_start(int64_t flv_pts, int sample_rate);
  89 + /**
  90 + * when buffer continue, muxer donot write to file,
  91 + * the audio buffer continue grow and donot need a pts,
  92 + * for the ts audio PES packet only has one pts at the first time.
  93 + */
  94 + virtual void on_buffer_continue();
  95 +};
  96 +
  97 +/**
68 * write m3u8 hls. 98 * write m3u8 hls.
69 */ 99 */
70 -class SrsHLS 100 +class SrsHls
71 { 101 {
72 private: 102 private:
73 std::string vhost; 103 std::string vhost;
@@ -95,16 +125,20 @@ private: @@ -95,16 +125,20 @@ private:
95 SrsCodecBuffer* video_buffer; 125 SrsCodecBuffer* video_buffer;
96 // last known dts 126 // last known dts
97 int64_t stream_dts; 127 int64_t stream_dts;
  128 + int64_t audio_buffer_start_pts;
98 // last segment dts in m3u8 129 // last segment dts in m3u8
99 int64_t m3u8_dts; 130 int64_t m3u8_dts;
  131 + // in ms, audio delay to flush the audios.
  132 + int64_t audio_delay;
100 private: 133 private:
101 bool hls_enabled; 134 bool hls_enabled;
102 SrsCodec* codec; 135 SrsCodec* codec;
103 SrsCodecSample* sample; 136 SrsCodecSample* sample;
104 SrsRtmpJitter* jitter; 137 SrsRtmpJitter* jitter;
  138 + SrsHlsAacJitter* aac_jitter;
105 public: 139 public:
106 - SrsHLS();  
107 - virtual ~SrsHLS(); 140 + SrsHls();
  141 + virtual ~SrsHls();
108 public: 142 public:
109 virtual int on_publish(std::string _vhost, std::string _app, std::string _stream); 143 virtual int on_publish(std::string _vhost, std::string _app, std::string _stream);
110 virtual void on_unpublish(); 144 virtual void on_unpublish();
@@ -116,6 +150,10 @@ private: @@ -116,6 +150,10 @@ private:
116 virtual int refresh_m3u8(); 150 virtual int refresh_m3u8();
117 virtual int _refresh_m3u8(int& fd, std::string m3u8_file); 151 virtual int _refresh_m3u8(int& fd, std::string m3u8_file);
118 virtual int create_dir(); 152 virtual int create_dir();
  153 +private:
  154 + virtual int write_audio();
  155 + virtual int write_video();
  156 + virtual int flush_audio();
119 }; 157 };
120 158
121 class SrsTSMuxer 159 class SrsTSMuxer
@@ -123,14 +161,16 @@ class SrsTSMuxer @@ -123,14 +161,16 @@ class SrsTSMuxer
123 private: 161 private:
124 int fd; 162 int fd;
125 std::string path; 163 std::string path;
  164 + bool _fresh;
126 public: 165 public:
127 SrsTSMuxer(); 166 SrsTSMuxer();
128 virtual ~SrsTSMuxer(); 167 virtual ~SrsTSMuxer();
129 public: 168 public:
130 virtual int open(std::string _path); 169 virtual int open(std::string _path);
131 - virtual int write_audio(SrsMpegtsFrame* audio_frame, SrsCodecBuffer* audio_buffer, SrsCodec* codec, SrsCodecSample* sample);  
132 - virtual int write_video(SrsMpegtsFrame* video_frame, SrsCodecBuffer* video_buffer, SrsCodec* codec, SrsCodecSample* sample); 170 + virtual int write_audio(SrsMpegtsFrame* audio_frame, SrsCodecBuffer* audio_buffer);
  171 + virtual int write_video(SrsMpegtsFrame* video_frame, SrsCodecBuffer* video_buffer);
133 virtual void close(); 172 virtual void close();
  173 + virtual bool fresh();
134 }; 174 };
135 175
136 #endif 176 #endif
@@ -257,7 +257,7 @@ SrsSource* SrsSource::find(std::string stream_url) @@ -257,7 +257,7 @@ SrsSource* SrsSource::find(std::string stream_url)
257 SrsSource::SrsSource(std::string _stream_url) 257 SrsSource::SrsSource(std::string _stream_url)
258 { 258 {
259 stream_url = _stream_url; 259 stream_url = _stream_url;
260 - hls = new SrsHLS(); 260 + hls = new SrsHls();
261 261
262 cache_metadata = cache_sh_video = cache_sh_audio = NULL; 262 cache_metadata = cache_sh_video = cache_sh_audio = NULL;
263 263
@@ -38,7 +38,7 @@ class SrsSource; @@ -38,7 +38,7 @@ class SrsSource;
38 class SrsCommonMessage; 38 class SrsCommonMessage;
39 class SrsOnMetaDataPacket; 39 class SrsOnMetaDataPacket;
40 class SrsSharedPtrMessage; 40 class SrsSharedPtrMessage;
41 -class SrsHLS; 41 +class SrsHls;
42 42
43 /** 43 /**
44 * time jitter detect and correct, 44 * time jitter detect and correct,
@@ -125,7 +125,7 @@ public: @@ -125,7 +125,7 @@ public:
125 */ 125 */
126 static SrsSource* find(std::string stream_url); 126 static SrsSource* find(std::string stream_url);
127 private: 127 private:
128 - SrsHLS* hls; 128 + SrsHls* hls;
129 std::string stream_url; 129 std::string stream_url;
130 std::vector<SrsConsumer*> consumers; 130 std::vector<SrsConsumer*> consumers;
131 // gop cache for client fast startup. 131 // gop cache for client fast startup.