正在显示
10 个修改的文件
包含
303 行增加
和
73 行删除
| @@ -521,6 +521,7 @@ Supported operating systems and hardware: | @@ -521,6 +521,7 @@ Supported operating systems and hardware: | ||
| 521 | 521 | ||
| 522 | ### SRS 2.0 history | 522 | ### SRS 2.0 history |
| 523 | 523 | ||
| 524 | +* v2.0, 2015-01-25, for [#301](https://github.com/winlinvip/simple-rtmp-server/issues/301), http ts stream support h.264+mp3. 2.0.106 | ||
| 524 | * v2.0, 2015-01-25, hotfix [#268](https://github.com/winlinvip/simple-rtmp-server/issues/268), refine the pcr start at 0, dts/pts plus delay. 2.0.105 | 525 | * v2.0, 2015-01-25, hotfix [#268](https://github.com/winlinvip/simple-rtmp-server/issues/268), refine the pcr start at 0, dts/pts plus delay. 2.0.105 |
| 525 | * v2.0, 2015-01-25, hotfix [#151](https://github.com/winlinvip/simple-rtmp-server/issues/151), refine pcr=dts-800ms and use dts/pts directly. 2.0.104 | 526 | * v2.0, 2015-01-25, hotfix [#151](https://github.com/winlinvip/simple-rtmp-server/issues/151), refine pcr=dts-800ms and use dts/pts directly. 2.0.104 |
| 526 | * v2.0, 2015-01-23, hotfix [#151](https://github.com/winlinvip/simple-rtmp-server/issues/151), use absolutely overflow to make jwplayer happy. 2.0.103 | 527 | * v2.0, 2015-01-23, hotfix [#151](https://github.com/winlinvip/simple-rtmp-server/issues/151), use absolutely overflow to make jwplayer happy. 2.0.103 |
| @@ -199,6 +199,13 @@ bool SrsHlsMuxer::is_segment_absolutely_overflow() | @@ -199,6 +199,13 @@ bool SrsHlsMuxer::is_segment_absolutely_overflow() | ||
| 199 | return current->duration >= 2 * hls_fragment; | 199 | return current->duration >= 2 * hls_fragment; |
| 200 | } | 200 | } |
| 201 | 201 | ||
| 202 | +int SrsHlsMuxer::update_acodec(SrsCodecAudio acodec) | ||
| 203 | +{ | ||
| 204 | + srs_assert(current); | ||
| 205 | + srs_assert(current->muxer); | ||
| 206 | + return current->muxer->update_acodec(acodec); | ||
| 207 | +} | ||
| 208 | + | ||
| 202 | int SrsHlsMuxer::flush_audio(SrsMpegtsFrame* af, SrsSimpleBuffer* ab) | 209 | int SrsHlsMuxer::flush_audio(SrsMpegtsFrame* af, SrsSimpleBuffer* ab) |
| 203 | { | 210 | { |
| 204 | int ret = ERROR_SUCCESS; | 211 | int ret = ERROR_SUCCESS; |
| @@ -572,8 +579,6 @@ int SrsHlsCache::on_sequence_header(SrsHlsMuxer* muxer) | @@ -572,8 +579,6 @@ int SrsHlsCache::on_sequence_header(SrsHlsMuxer* muxer) | ||
| 572 | int SrsHlsCache::write_audio(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t pts, SrsCodecSample* sample) | 579 | int SrsHlsCache::write_audio(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t pts, SrsCodecSample* sample) |
| 573 | { | 580 | { |
| 574 | int ret = ERROR_SUCCESS; | 581 | int ret = ERROR_SUCCESS; |
| 575 | - | ||
| 576 | - audio_buffer_start_pts = pts; | ||
| 577 | 582 | ||
| 578 | // write audio to cache. | 583 | // write audio to cache. |
| 579 | if ((ret = cache->cache_audio(codec, pts, sample)) != ERROR_SUCCESS) { | 584 | if ((ret = cache->cache_audio(codec, pts, sample)) != ERROR_SUCCESS) { |
| @@ -591,7 +596,7 @@ int SrsHlsCache::write_audio(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t | @@ -591,7 +596,7 @@ int SrsHlsCache::write_audio(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t | ||
| 591 | // in ms, audio delay to flush the audios. | 596 | // in ms, audio delay to flush the audios. |
| 592 | int64_t audio_delay = SRS_CONF_DEFAULT_AAC_DELAY; | 597 | int64_t audio_delay = SRS_CONF_DEFAULT_AAC_DELAY; |
| 593 | // flush if audio delay exceed | 598 | // flush if audio delay exceed |
| 594 | - if (pts - audio_buffer_start_pts > audio_delay * 90) { | 599 | + if (pts - cache->audio_buffer_start_pts > audio_delay * 90) { |
| 595 | if ((ret = muxer->flush_audio(cache->af, cache->ab)) != ERROR_SUCCESS) { | 600 | if ((ret = muxer->flush_audio(cache->af, cache->ab)) != ERROR_SUCCESS) { |
| 596 | return ret; | 601 | return ret; |
| 597 | } | 602 | } |
| @@ -773,11 +778,25 @@ int SrsHls::on_audio(SrsSharedPtrMessage* __audio) | @@ -773,11 +778,25 @@ int SrsHls::on_audio(SrsSharedPtrMessage* __audio) | ||
| 773 | 778 | ||
| 774 | sample->clear(); | 779 | sample->clear(); |
| 775 | if ((ret = codec->audio_aac_demux(audio->payload, audio->size, sample)) != ERROR_SUCCESS) { | 780 | if ((ret = codec->audio_aac_demux(audio->payload, audio->size, sample)) != ERROR_SUCCESS) { |
| 776 | - srs_error("hls codec demux audio failed. ret=%d", ret); | ||
| 777 | - return ret; | 781 | + if (ret != ERROR_HLS_TRY_MP3) { |
| 782 | + srs_error("hls aac demux audio failed. ret=%d", ret); | ||
| 783 | + return ret; | ||
| 784 | + } | ||
| 785 | + if ((ret = codec->audio_mp3_demux(audio->payload, audio->size, sample)) != ERROR_SUCCESS) { | ||
| 786 | + srs_error("hls mp3 demux audio failed. ret=%d", ret); | ||
| 787 | + return ret; | ||
| 788 | + } | ||
| 778 | } | 789 | } |
| 790 | + SrsCodecAudio acodec = (SrsCodecAudio)codec->audio_codec_id; | ||
| 779 | 791 | ||
| 780 | - if (codec->audio_codec_id != SrsCodecAudioAAC) { | 792 | + // ts support audio codec: aac/mp3 |
| 793 | + if (acodec != SrsCodecAudioAAC && acodec != SrsCodecAudioMP3) { | ||
| 794 | + return ret; | ||
| 795 | + } | ||
| 796 | + | ||
| 797 | + // when codec changed, write new header. | ||
| 798 | + if ((ret = muxer->update_acodec(acodec)) != ERROR_SUCCESS) { | ||
| 799 | + srs_error("http: ts audio write header failed. ret=%d", ret); | ||
| 781 | return ret; | 800 | return ret; |
| 782 | } | 801 | } |
| 783 | 802 |
| @@ -37,6 +37,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -37,6 +37,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 37 | #include <string> | 37 | #include <string> |
| 38 | #include <vector> | 38 | #include <vector> |
| 39 | 39 | ||
| 40 | +#include <srs_kernel_codec.hpp> | ||
| 41 | + | ||
| 40 | class SrsSharedPtrMessage; | 42 | class SrsSharedPtrMessage; |
| 41 | class SrsCodecSample; | 43 | class SrsCodecSample; |
| 42 | class SrsMpegtsFrame; | 44 | class SrsMpegtsFrame; |
| @@ -141,6 +143,8 @@ public: | @@ -141,6 +143,8 @@ public: | ||
| 141 | * @see https://github.com/winlinvip/simple-rtmp-server/issues/151#issuecomment-71155184 | 143 | * @see https://github.com/winlinvip/simple-rtmp-server/issues/151#issuecomment-71155184 |
| 142 | */ | 144 | */ |
| 143 | virtual bool is_segment_absolutely_overflow(); | 145 | virtual bool is_segment_absolutely_overflow(); |
| 146 | +public: | ||
| 147 | + virtual int update_acodec(SrsCodecAudio acodec); | ||
| 144 | virtual int flush_audio(SrsMpegtsFrame* af, SrsSimpleBuffer* ab); | 148 | virtual int flush_audio(SrsMpegtsFrame* af, SrsSimpleBuffer* ab); |
| 145 | virtual int flush_video(SrsMpegtsFrame* af, SrsSimpleBuffer* ab, SrsMpegtsFrame* vf, SrsSimpleBuffer* vb); | 149 | virtual int flush_video(SrsMpegtsFrame* af, SrsSimpleBuffer* ab, SrsMpegtsFrame* vf, SrsSimpleBuffer* vb); |
| 146 | /** | 150 | /** |
| @@ -174,8 +178,6 @@ private: | @@ -174,8 +178,6 @@ private: | ||
| 174 | class SrsHlsCache | 178 | class SrsHlsCache |
| 175 | { | 179 | { |
| 176 | private: | 180 | private: |
| 177 | - // the audio cache buffer start pts, to flush audio if full. | ||
| 178 | - int64_t audio_buffer_start_pts; | ||
| 179 | SrsTsCache* cache; | 181 | SrsTsCache* cache; |
| 180 | public: | 182 | public: |
| 181 | SrsHlsCache(); | 183 | SrsHlsCache(); |
| @@ -1349,12 +1349,17 @@ int SrsSource::on_audio(SrsCommonMessage* __audio) | @@ -1349,12 +1349,17 @@ int SrsSource::on_audio(SrsCommonMessage* __audio) | ||
| 1349 | } | 1349 | } |
| 1350 | } | 1350 | } |
| 1351 | 1351 | ||
| 1352 | - // cache the sequence header if h264 | ||
| 1353 | - // donot cache the sequence header to gop_cache, return here. | ||
| 1354 | - if (SrsFlvCodec::audio_is_sequence_header(msg.payload, msg.size)) { | 1352 | + // cache the sequence header of aac, or first packet of mp3. |
| 1353 | + // for example, the mp3 is used for hls to write the "right" audio codec. | ||
| 1354 | + bool is_aac_sequence_header = SrsFlvCodec::audio_is_sequence_header(msg.payload, msg.size); | ||
| 1355 | + if (is_aac_sequence_header || !cache_sh_audio) { | ||
| 1355 | srs_freep(cache_sh_audio); | 1356 | srs_freep(cache_sh_audio); |
| 1356 | cache_sh_audio = msg.copy(); | 1357 | cache_sh_audio = msg.copy(); |
| 1357 | - | 1358 | + } |
| 1359 | + | ||
| 1360 | + // cache the sequence header if aac | ||
| 1361 | + // donot cache the sequence header to gop_cache, return here. | ||
| 1362 | + if (is_aac_sequence_header) { | ||
| 1358 | // parse detail audio codec | 1363 | // parse detail audio codec |
| 1359 | SrsAvcAacCodec codec; | 1364 | SrsAvcAacCodec codec; |
| 1360 | SrsCodecSample sample; | 1365 | SrsCodecSample sample; |
| @@ -1768,18 +1773,20 @@ int SrsSource::create_consumer(SrsConsumer*& consumer, bool ds, bool dm, bool dg | @@ -1768,18 +1773,20 @@ int SrsSource::create_consumer(SrsConsumer*& consumer, bool ds, bool dm, bool dg | ||
| 1768 | srs_info("dispatch metadata success"); | 1773 | srs_info("dispatch metadata success"); |
| 1769 | 1774 | ||
| 1770 | // copy sequence header | 1775 | // copy sequence header |
| 1776 | + // copy audio sequence first, for hls to fast parse the "right" audio codec. | ||
| 1777 | + // @see https://github.com/winlinvip/simple-rtmp-server/issues/301 | ||
| 1778 | + if (ds && cache_sh_audio && (ret = consumer->enqueue(cache_sh_audio, atc, tba, tbv, ag)) != ERROR_SUCCESS) { | ||
| 1779 | + srs_error("dispatch audio sequence header failed. ret=%d", ret); | ||
| 1780 | + return ret; | ||
| 1781 | + } | ||
| 1782 | + srs_info("dispatch audio sequence header success"); | ||
| 1783 | + | ||
| 1771 | if (ds && cache_sh_video && (ret = consumer->enqueue(cache_sh_video, atc, tba, tbv, ag)) != ERROR_SUCCESS) { | 1784 | if (ds && cache_sh_video && (ret = consumer->enqueue(cache_sh_video, atc, tba, tbv, ag)) != ERROR_SUCCESS) { |
| 1772 | srs_error("dispatch video sequence header failed. ret=%d", ret); | 1785 | srs_error("dispatch video sequence header failed. ret=%d", ret); |
| 1773 | return ret; | 1786 | return ret; |
| 1774 | } | 1787 | } |
| 1775 | srs_info("dispatch video sequence header success"); | 1788 | srs_info("dispatch video sequence header success"); |
| 1776 | 1789 | ||
| 1777 | - if (cache_sh_audio && (ret = consumer->enqueue(cache_sh_audio, atc, tba, tbv, ag)) != ERROR_SUCCESS) { | ||
| 1778 | - srs_error("dispatch audio sequence header failed. ret=%d", ret); | ||
| 1779 | - return ret; | ||
| 1780 | - } | ||
| 1781 | - srs_info("dispatch audio sequence header success"); | ||
| 1782 | - | ||
| 1783 | // copy gop cache to client. | 1790 | // copy gop cache to client. |
| 1784 | if (dg && (ret = gop_cache->dump(consumer, atc, tba, tbv, ag)) != ERROR_SUCCESS) { | 1791 | if (dg && (ret = gop_cache->dump(consumer, atc, tba, tbv, ag)) != ERROR_SUCCESS) { |
| 1785 | return ret; | 1792 | return ret; |
| @@ -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 105 | 34 | +#define VERSION_REVISION 106 |
| 35 | 35 | ||
| 36 | // server info. | 36 | // server info. |
| 37 | #define RTMP_SIG_SRS_KEY "SRS" | 37 | #define RTMP_SIG_SRS_KEY "SRS" |
| @@ -60,6 +60,7 @@ void SrsCodecSample::clear() | @@ -60,6 +60,7 @@ void SrsCodecSample::clear() | ||
| 60 | frame_type = SrsCodecVideoAVCFrameReserved; | 60 | frame_type = SrsCodecVideoAVCFrameReserved; |
| 61 | avc_packet_type = SrsCodecVideoAVCTypeReserved; | 61 | avc_packet_type = SrsCodecVideoAVCTypeReserved; |
| 62 | 62 | ||
| 63 | + acodec = SrsCodecAudioReserved1; | ||
| 63 | sound_rate = SrsCodecAudioSampleRateReserved; | 64 | sound_rate = SrsCodecAudioSampleRateReserved; |
| 64 | sound_size = SrsCodecAudioSampleSizeReserved; | 65 | sound_size = SrsCodecAudioSampleSizeReserved; |
| 65 | sound_type = SrsCodecAudioSoundTypeReserved; | 66 | sound_type = SrsCodecAudioSoundTypeReserved; |
| @@ -91,10 +92,13 @@ SrsAvcAacCodec::SrsAvcAacCodec() | @@ -91,10 +92,13 @@ SrsAvcAacCodec::SrsAvcAacCodec() | ||
| 91 | duration = 0; | 92 | duration = 0; |
| 92 | NAL_unit_length = 0; | 93 | NAL_unit_length = 0; |
| 93 | frame_rate = 0; | 94 | frame_rate = 0; |
| 95 | + | ||
| 94 | video_data_rate = 0; | 96 | video_data_rate = 0; |
| 95 | video_codec_id = 0; | 97 | video_codec_id = 0; |
| 98 | + | ||
| 96 | audio_data_rate = 0; | 99 | audio_data_rate = 0; |
| 97 | audio_codec_id = 0; | 100 | audio_codec_id = 0; |
| 101 | + | ||
| 98 | avc_profile = 0; | 102 | avc_profile = 0; |
| 99 | avc_level = 0; | 103 | avc_level = 0; |
| 100 | aac_profile = 0; | 104 | aac_profile = 0; |
| @@ -104,6 +108,7 @@ SrsAvcAacCodec::SrsAvcAacCodec() | @@ -104,6 +108,7 @@ SrsAvcAacCodec::SrsAvcAacCodec() | ||
| 104 | avc_extra_data = NULL; | 108 | avc_extra_data = NULL; |
| 105 | aac_extra_size = 0; | 109 | aac_extra_size = 0; |
| 106 | aac_extra_data = NULL; | 110 | aac_extra_data = NULL; |
| 111 | + | ||
| 107 | sequenceParameterSetLength = 0; | 112 | sequenceParameterSetLength = 0; |
| 108 | sequenceParameterSetNALUnit = NULL; | 113 | sequenceParameterSetNALUnit = NULL; |
| 109 | pictureParameterSetLength = 0; | 114 | pictureParameterSetLength = 0; |
| @@ -129,7 +134,7 @@ int SrsAvcAacCodec::audio_aac_demux(char* data, int size, SrsCodecSample* sample | @@ -129,7 +134,7 @@ int SrsAvcAacCodec::audio_aac_demux(char* data, int size, SrsCodecSample* sample | ||
| 129 | sample->is_video = false; | 134 | sample->is_video = false; |
| 130 | 135 | ||
| 131 | if (!data || size <= 0) { | 136 | if (!data || size <= 0) { |
| 132 | - srs_trace("no audio present, hls ignore it."); | 137 | + srs_trace("no audio present, ignore it."); |
| 133 | return ret; | 138 | return ret; |
| 134 | } | 139 | } |
| 135 | 140 | ||
| @@ -140,7 +145,7 @@ int SrsAvcAacCodec::audio_aac_demux(char* data, int size, SrsCodecSample* sample | @@ -140,7 +145,7 @@ int SrsAvcAacCodec::audio_aac_demux(char* data, int size, SrsCodecSample* sample | ||
| 140 | // audio decode | 145 | // audio decode |
| 141 | if (!stream->require(1)) { | 146 | if (!stream->require(1)) { |
| 142 | ret = ERROR_HLS_DECODE_ERROR; | 147 | ret = ERROR_HLS_DECODE_ERROR; |
| 143 | - srs_error("hls decode audio sound_format failed. ret=%d", ret); | 148 | + srs_error("audio codec decode sound_format failed. ret=%d", ret); |
| 144 | return ret; | 149 | return ret; |
| 145 | } | 150 | } |
| 146 | 151 | ||
| @@ -153,20 +158,27 @@ int SrsAvcAacCodec::audio_aac_demux(char* data, int size, SrsCodecSample* sample | @@ -153,20 +158,27 @@ int SrsAvcAacCodec::audio_aac_demux(char* data, int size, SrsCodecSample* sample | ||
| 153 | sound_format = (sound_format >> 4) & 0x0f; | 158 | sound_format = (sound_format >> 4) & 0x0f; |
| 154 | 159 | ||
| 155 | audio_codec_id = sound_format; | 160 | audio_codec_id = sound_format; |
| 161 | + sample->acodec = (SrsCodecAudio)audio_codec_id; | ||
| 162 | + | ||
| 156 | sample->sound_type = (SrsCodecAudioSoundType)sound_type; | 163 | sample->sound_type = (SrsCodecAudioSoundType)sound_type; |
| 157 | sample->sound_rate = (SrsCodecAudioSampleRate)sound_rate; | 164 | sample->sound_rate = (SrsCodecAudioSampleRate)sound_rate; |
| 158 | sample->sound_size = (SrsCodecAudioSampleSize)sound_size; | 165 | sample->sound_size = (SrsCodecAudioSampleSize)sound_size; |
| 166 | + | ||
| 167 | + // we support h.264+mp3 for hls. | ||
| 168 | + if (audio_codec_id == SrsCodecAudioMP3) { | ||
| 169 | + return ERROR_HLS_TRY_MP3; | ||
| 170 | + } | ||
| 159 | 171 | ||
| 160 | // only support aac | 172 | // only support aac |
| 161 | if (audio_codec_id != SrsCodecAudioAAC) { | 173 | if (audio_codec_id != SrsCodecAudioAAC) { |
| 162 | ret = ERROR_HLS_DECODE_ERROR; | 174 | ret = ERROR_HLS_DECODE_ERROR; |
| 163 | - srs_error("hls only support audio aac codec. actual=%d, ret=%d", audio_codec_id, ret); | 175 | + srs_error("audio codec only support mp3/aac codec. actual=%d, ret=%d", audio_codec_id, ret); |
| 164 | return ret; | 176 | return ret; |
| 165 | } | 177 | } |
| 166 | 178 | ||
| 167 | if (!stream->require(1)) { | 179 | if (!stream->require(1)) { |
| 168 | ret = ERROR_HLS_DECODE_ERROR; | 180 | ret = ERROR_HLS_DECODE_ERROR; |
| 169 | - srs_error("hls decode audio aac_packet_type failed. ret=%d", ret); | 181 | + srs_error("audio codec decode aac_packet_type failed. ret=%d", ret); |
| 170 | return ret; | 182 | return ret; |
| 171 | } | 183 | } |
| 172 | 184 | ||
| @@ -189,7 +201,7 @@ int SrsAvcAacCodec::audio_aac_demux(char* data, int size, SrsCodecSample* sample | @@ -189,7 +201,7 @@ int SrsAvcAacCodec::audio_aac_demux(char* data, int size, SrsCodecSample* sample | ||
| 189 | // channelConfiguration, aac_channels, 4bits | 201 | // channelConfiguration, aac_channels, 4bits |
| 190 | if (!stream->require(2)) { | 202 | if (!stream->require(2)) { |
| 191 | ret = ERROR_HLS_DECODE_ERROR; | 203 | ret = ERROR_HLS_DECODE_ERROR; |
| 192 | - srs_error("hls decode audio aac sequence header failed. ret=%d", ret); | 204 | + srs_error("audio codec decode aac sequence header failed. ret=%d", ret); |
| 193 | return ret; | 205 | return ret; |
| 194 | } | 206 | } |
| 195 | aac_profile = stream->read_1bytes(); | 207 | aac_profile = stream->read_1bytes(); |
| @@ -201,7 +213,7 @@ int SrsAvcAacCodec::audio_aac_demux(char* data, int size, SrsCodecSample* sample | @@ -201,7 +213,7 @@ int SrsAvcAacCodec::audio_aac_demux(char* data, int size, SrsCodecSample* sample | ||
| 201 | 213 | ||
| 202 | if (aac_profile == 0 || aac_profile == 0x1f) { | 214 | if (aac_profile == 0 || aac_profile == 0x1f) { |
| 203 | ret = ERROR_HLS_DECODE_ERROR; | 215 | ret = ERROR_HLS_DECODE_ERROR; |
| 204 | - srs_error("hls decode audio aac sequence header failed, " | 216 | + srs_error("audio codec decode aac sequence header failed, " |
| 205 | "adts object=%d invalid. ret=%d", aac_profile, ret); | 217 | "adts object=%d invalid. ret=%d", aac_profile, ret); |
| 206 | return ret; | 218 | return ret; |
| 207 | } | 219 | } |
| @@ -221,14 +233,14 @@ int SrsAvcAacCodec::audio_aac_demux(char* data, int size, SrsCodecSample* sample | @@ -221,14 +233,14 @@ int SrsAvcAacCodec::audio_aac_demux(char* data, int size, SrsCodecSample* sample | ||
| 221 | // ensure the sequence header demuxed | 233 | // ensure the sequence header demuxed |
| 222 | if (aac_extra_size <= 0 || !aac_extra_data) { | 234 | if (aac_extra_size <= 0 || !aac_extra_data) { |
| 223 | ret = ERROR_HLS_DECODE_ERROR; | 235 | ret = ERROR_HLS_DECODE_ERROR; |
| 224 | - srs_error("hls decode audio aac failed, sequence header not found. ret=%d", ret); | 236 | + srs_error("audio codec decode aac failed, sequence header not found. ret=%d", ret); |
| 225 | return ret; | 237 | return ret; |
| 226 | } | 238 | } |
| 227 | 239 | ||
| 228 | // Raw AAC frame data in UI8 [] | 240 | // Raw AAC frame data in UI8 [] |
| 229 | // 6.3 Raw Data, aac-iso-13818-7.pdf, page 28 | 241 | // 6.3 Raw Data, aac-iso-13818-7.pdf, page 28 |
| 230 | if ((ret = sample->add_sample_unit(stream->data() + stream->pos(), stream->size() - stream->pos())) != ERROR_SUCCESS) { | 242 | if ((ret = sample->add_sample_unit(stream->data() + stream->pos(), stream->size() - stream->pos())) != ERROR_SUCCESS) { |
| 231 | - srs_error("hls add audio sample failed. ret=%d", ret); | 243 | + srs_error("audio codec add sample failed. ret=%d", ret); |
| 232 | return ret; | 244 | return ret; |
| 233 | } | 245 | } |
| 234 | } else { | 246 | } else { |
| @@ -264,6 +276,31 @@ int SrsAvcAacCodec::audio_aac_demux(char* data, int size, SrsCodecSample* sample | @@ -264,6 +276,31 @@ int SrsAvcAacCodec::audio_aac_demux(char* data, int size, SrsCodecSample* sample | ||
| 264 | return ret; | 276 | return ret; |
| 265 | } | 277 | } |
| 266 | 278 | ||
| 279 | +int SrsAvcAacCodec::audio_mp3_demux(char* data, int size, SrsCodecSample* sample) | ||
| 280 | +{ | ||
| 281 | + int ret = ERROR_SUCCESS; | ||
| 282 | + | ||
| 283 | + // we always decode aac then mp3. | ||
| 284 | + srs_assert(sample->acodec == SrsCodecAudioMP3); | ||
| 285 | + | ||
| 286 | + // @see: E.4.2 Audio Tags, video_file_format_spec_v10_1.pdf, page 76 | ||
| 287 | + if (!data || size <= 1) { | ||
| 288 | + srs_trace("no mp3 audio present, ignore it."); | ||
| 289 | + return ret; | ||
| 290 | + } | ||
| 291 | + | ||
| 292 | + // mp3 payload. | ||
| 293 | + if ((ret = sample->add_sample_unit(data + 1, size - 1)) != ERROR_SUCCESS) { | ||
| 294 | + srs_error("audio codec add mp3 sample failed. ret=%d", ret); | ||
| 295 | + return ret; | ||
| 296 | + } | ||
| 297 | + | ||
| 298 | + srs_info("audio decoded, type=%d, codec=%d, asize=%d, rate=%d, format=%d, size=%d", | ||
| 299 | + sample->sound_type, audio_codec_id, sample->sound_size, sample->sound_rate, sample->acodec, size); | ||
| 300 | + | ||
| 301 | + return ret; | ||
| 302 | +} | ||
| 303 | + | ||
| 267 | int SrsAvcAacCodec::video_avc_demux(char* data, int size, SrsCodecSample* sample) | 304 | int SrsAvcAacCodec::video_avc_demux(char* data, int size, SrsCodecSample* sample) |
| 268 | { | 305 | { |
| 269 | int ret = ERROR_SUCCESS; | 306 | int ret = ERROR_SUCCESS; |
| @@ -271,7 +308,7 @@ int SrsAvcAacCodec::video_avc_demux(char* data, int size, SrsCodecSample* sample | @@ -271,7 +308,7 @@ int SrsAvcAacCodec::video_avc_demux(char* data, int size, SrsCodecSample* sample | ||
| 271 | sample->is_video = true; | 308 | sample->is_video = true; |
| 272 | 309 | ||
| 273 | if (!data || size <= 0) { | 310 | if (!data || size <= 0) { |
| 274 | - srs_trace("no video present, hls ignore it."); | 311 | + srs_trace("no video present, ignore it."); |
| 275 | return ret; | 312 | return ret; |
| 276 | } | 313 | } |
| 277 | 314 | ||
| @@ -282,7 +319,7 @@ int SrsAvcAacCodec::video_avc_demux(char* data, int size, SrsCodecSample* sample | @@ -282,7 +319,7 @@ int SrsAvcAacCodec::video_avc_demux(char* data, int size, SrsCodecSample* sample | ||
| 282 | // video decode | 319 | // video decode |
| 283 | if (!stream->require(1)) { | 320 | if (!stream->require(1)) { |
| 284 | ret = ERROR_HLS_DECODE_ERROR; | 321 | ret = ERROR_HLS_DECODE_ERROR; |
| 285 | - srs_error("hls decode video frame_type failed. ret=%d", ret); | 322 | + srs_error("video codec decode frame_type failed. ret=%d", ret); |
| 286 | return ret; | 323 | return ret; |
| 287 | } | 324 | } |
| 288 | 325 | ||
| @@ -296,21 +333,21 @@ int SrsAvcAacCodec::video_avc_demux(char* data, int size, SrsCodecSample* sample | @@ -296,21 +333,21 @@ int SrsAvcAacCodec::video_avc_demux(char* data, int size, SrsCodecSample* sample | ||
| 296 | // ignore info frame without error, | 333 | // ignore info frame without error, |
| 297 | // @see https://github.com/winlinvip/simple-rtmp-server/issues/288#issuecomment-69863909 | 334 | // @see https://github.com/winlinvip/simple-rtmp-server/issues/288#issuecomment-69863909 |
| 298 | if (sample->frame_type == SrsCodecVideoAVCFrameVideoInfoFrame) { | 335 | if (sample->frame_type == SrsCodecVideoAVCFrameVideoInfoFrame) { |
| 299 | - srs_warn("hls igone the info frame, ret=%d", ret); | 336 | + srs_warn("video codec igone the info frame, ret=%d", ret); |
| 300 | return ret; | 337 | return ret; |
| 301 | } | 338 | } |
| 302 | 339 | ||
| 303 | // only support h.264/avc | 340 | // only support h.264/avc |
| 304 | if (codec_id != SrsCodecVideoAVC) { | 341 | if (codec_id != SrsCodecVideoAVC) { |
| 305 | ret = ERROR_HLS_DECODE_ERROR; | 342 | ret = ERROR_HLS_DECODE_ERROR; |
| 306 | - srs_error("hls only support video h.264/avc codec. actual=%d, ret=%d", codec_id, ret); | 343 | + srs_error("video codec only support video h.264/avc codec. actual=%d, ret=%d", codec_id, ret); |
| 307 | return ret; | 344 | return ret; |
| 308 | } | 345 | } |
| 309 | video_codec_id = codec_id; | 346 | video_codec_id = codec_id; |
| 310 | 347 | ||
| 311 | if (!stream->require(4)) { | 348 | if (!stream->require(4)) { |
| 312 | ret = ERROR_HLS_DECODE_ERROR; | 349 | ret = ERROR_HLS_DECODE_ERROR; |
| 313 | - srs_error("hls decode video avc_packet_type failed. ret=%d", ret); | 350 | + srs_error("video codec decode avc_packet_type failed. ret=%d", ret); |
| 314 | return ret; | 351 | return ret; |
| 315 | } | 352 | } |
| 316 | int8_t avc_packet_type = stream->read_1bytes(); | 353 | int8_t avc_packet_type = stream->read_1bytes(); |
| @@ -328,7 +365,7 @@ int SrsAvcAacCodec::video_avc_demux(char* data, int size, SrsCodecSample* sample | @@ -328,7 +365,7 @@ int SrsAvcAacCodec::video_avc_demux(char* data, int size, SrsCodecSample* sample | ||
| 328 | // ensure the sequence header demuxed | 365 | // ensure the sequence header demuxed |
| 329 | if (avc_extra_size <= 0 || !avc_extra_data) { | 366 | if (avc_extra_size <= 0 || !avc_extra_data) { |
| 330 | ret = ERROR_HLS_DECODE_ERROR; | 367 | ret = ERROR_HLS_DECODE_ERROR; |
| 331 | - srs_error("hls decode video avc failed, sequence header not found. ret=%d", ret); | 368 | + srs_error("avc decode failed, sequence header not found. ret=%d", ret); |
| 332 | return ret; | 369 | return ret; |
| 333 | } | 370 | } |
| 334 | 371 | ||
| @@ -371,7 +408,7 @@ int SrsAvcAacCodec::avc_demux_sps_pps(SrsStream* stream) | @@ -371,7 +408,7 @@ int SrsAvcAacCodec::avc_demux_sps_pps(SrsStream* stream) | ||
| 371 | 408 | ||
| 372 | if (!stream->require(6)) { | 409 | if (!stream->require(6)) { |
| 373 | ret = ERROR_HLS_DECODE_ERROR; | 410 | ret = ERROR_HLS_DECODE_ERROR; |
| 374 | - srs_error("hls decode video avc sequenc header failed. ret=%d", ret); | 411 | + srs_error("avc decode sequenc header failed. ret=%d", ret); |
| 375 | return ret; | 412 | return ret; |
| 376 | } | 413 | } |
| 377 | //int8_t configurationVersion = stream->read_1bytes(); | 414 | //int8_t configurationVersion = stream->read_1bytes(); |
| @@ -402,25 +439,25 @@ int SrsAvcAacCodec::avc_demux_sps_pps(SrsStream* stream) | @@ -402,25 +439,25 @@ int SrsAvcAacCodec::avc_demux_sps_pps(SrsStream* stream) | ||
| 402 | // 1 sps | 439 | // 1 sps |
| 403 | if (!stream->require(1)) { | 440 | if (!stream->require(1)) { |
| 404 | ret = ERROR_HLS_DECODE_ERROR; | 441 | ret = ERROR_HLS_DECODE_ERROR; |
| 405 | - srs_error("hls decode video avc sequenc header sps failed. ret=%d", ret); | 442 | + srs_error("avc decode sequenc header sps failed. ret=%d", ret); |
| 406 | return ret; | 443 | return ret; |
| 407 | } | 444 | } |
| 408 | int8_t numOfSequenceParameterSets = stream->read_1bytes(); | 445 | int8_t numOfSequenceParameterSets = stream->read_1bytes(); |
| 409 | numOfSequenceParameterSets &= 0x1f; | 446 | numOfSequenceParameterSets &= 0x1f; |
| 410 | if (numOfSequenceParameterSets != 1) { | 447 | if (numOfSequenceParameterSets != 1) { |
| 411 | ret = ERROR_HLS_DECODE_ERROR; | 448 | ret = ERROR_HLS_DECODE_ERROR; |
| 412 | - srs_error("hls decode video avc sequenc header sps failed. ret=%d", ret); | 449 | + srs_error("avc decode sequenc header sps failed. ret=%d", ret); |
| 413 | return ret; | 450 | return ret; |
| 414 | } | 451 | } |
| 415 | if (!stream->require(2)) { | 452 | if (!stream->require(2)) { |
| 416 | ret = ERROR_HLS_DECODE_ERROR; | 453 | ret = ERROR_HLS_DECODE_ERROR; |
| 417 | - srs_error("hls decode video avc sequenc header sps size failed. ret=%d", ret); | 454 | + srs_error("avc decode sequenc header sps size failed. ret=%d", ret); |
| 418 | return ret; | 455 | return ret; |
| 419 | } | 456 | } |
| 420 | sequenceParameterSetLength = stream->read_2bytes(); | 457 | sequenceParameterSetLength = stream->read_2bytes(); |
| 421 | if (!stream->require(sequenceParameterSetLength)) { | 458 | if (!stream->require(sequenceParameterSetLength)) { |
| 422 | ret = ERROR_HLS_DECODE_ERROR; | 459 | ret = ERROR_HLS_DECODE_ERROR; |
| 423 | - srs_error("hls decode video avc sequenc header sps data failed. ret=%d", ret); | 460 | + srs_error("avc decode sequenc header sps data failed. ret=%d", ret); |
| 424 | return ret; | 461 | return ret; |
| 425 | } | 462 | } |
| 426 | if (sequenceParameterSetLength > 0) { | 463 | if (sequenceParameterSetLength > 0) { |
| @@ -432,25 +469,25 @@ int SrsAvcAacCodec::avc_demux_sps_pps(SrsStream* stream) | @@ -432,25 +469,25 @@ int SrsAvcAacCodec::avc_demux_sps_pps(SrsStream* stream) | ||
| 432 | // 1 pps | 469 | // 1 pps |
| 433 | if (!stream->require(1)) { | 470 | if (!stream->require(1)) { |
| 434 | ret = ERROR_HLS_DECODE_ERROR; | 471 | ret = ERROR_HLS_DECODE_ERROR; |
| 435 | - srs_error("hls decode video avc sequenc header pps failed. ret=%d", ret); | 472 | + srs_error("avc decode sequenc header pps failed. ret=%d", ret); |
| 436 | return ret; | 473 | return ret; |
| 437 | } | 474 | } |
| 438 | int8_t numOfPictureParameterSets = stream->read_1bytes(); | 475 | int8_t numOfPictureParameterSets = stream->read_1bytes(); |
| 439 | numOfPictureParameterSets &= 0x1f; | 476 | numOfPictureParameterSets &= 0x1f; |
| 440 | if (numOfPictureParameterSets != 1) { | 477 | if (numOfPictureParameterSets != 1) { |
| 441 | ret = ERROR_HLS_DECODE_ERROR; | 478 | ret = ERROR_HLS_DECODE_ERROR; |
| 442 | - srs_error("hls decode video avc sequenc header pps failed. ret=%d", ret); | 479 | + srs_error("avc decode sequenc header pps failed. ret=%d", ret); |
| 443 | return ret; | 480 | return ret; |
| 444 | } | 481 | } |
| 445 | if (!stream->require(2)) { | 482 | if (!stream->require(2)) { |
| 446 | ret = ERROR_HLS_DECODE_ERROR; | 483 | ret = ERROR_HLS_DECODE_ERROR; |
| 447 | - srs_error("hls decode video avc sequenc header pps size failed. ret=%d", ret); | 484 | + srs_error("avc decode sequenc header pps size failed. ret=%d", ret); |
| 448 | return ret; | 485 | return ret; |
| 449 | } | 486 | } |
| 450 | pictureParameterSetLength = stream->read_2bytes(); | 487 | pictureParameterSetLength = stream->read_2bytes(); |
| 451 | if (!stream->require(pictureParameterSetLength)) { | 488 | if (!stream->require(pictureParameterSetLength)) { |
| 452 | ret = ERROR_HLS_DECODE_ERROR; | 489 | ret = ERROR_HLS_DECODE_ERROR; |
| 453 | - srs_error("hls decode video avc sequenc header pps data failed. ret=%d", ret); | 490 | + srs_error("avc decode sequenc header pps data failed. ret=%d", ret); |
| 454 | return ret; | 491 | return ret; |
| 455 | } | 492 | } |
| 456 | if (pictureParameterSetLength > 0) { | 493 | if (pictureParameterSetLength > 0) { |
| @@ -534,7 +571,7 @@ int SrsAvcAacCodec::avc_demux_ibmf_format(SrsStream* stream, SrsCodecSample* sam | @@ -534,7 +571,7 @@ int SrsAvcAacCodec::avc_demux_ibmf_format(SrsStream* stream, SrsCodecSample* sam | ||
| 534 | // unsigned int((NAL_unit_length+1)*8) NALUnitLength; | 571 | // unsigned int((NAL_unit_length+1)*8) NALUnitLength; |
| 535 | if (!stream->require(NAL_unit_length + 1)) { | 572 | if (!stream->require(NAL_unit_length + 1)) { |
| 536 | ret = ERROR_HLS_DECODE_ERROR; | 573 | ret = ERROR_HLS_DECODE_ERROR; |
| 537 | - srs_error("hls decode video avc NALU size failed. ret=%d", ret); | 574 | + srs_error("avc decode NALU size failed. ret=%d", ret); |
| 538 | return ret; | 575 | return ret; |
| 539 | } | 576 | } |
| 540 | int32_t NALUnitLength = 0; | 577 | int32_t NALUnitLength = 0; |
| @@ -557,12 +594,12 @@ int SrsAvcAacCodec::avc_demux_ibmf_format(SrsStream* stream, SrsCodecSample* sam | @@ -557,12 +594,12 @@ int SrsAvcAacCodec::avc_demux_ibmf_format(SrsStream* stream, SrsCodecSample* sam | ||
| 557 | // NALUnit | 594 | // NALUnit |
| 558 | if (!stream->require(NALUnitLength)) { | 595 | if (!stream->require(NALUnitLength)) { |
| 559 | ret = ERROR_HLS_DECODE_ERROR; | 596 | ret = ERROR_HLS_DECODE_ERROR; |
| 560 | - srs_error("hls decode video avc NALU data failed. ret=%d", ret); | 597 | + srs_error("avc decode NALU data failed. ret=%d", ret); |
| 561 | return ret; | 598 | return ret; |
| 562 | } | 599 | } |
| 563 | // 7.3.1 NAL unit syntax, H.264-AVC-ISO_IEC_14496-10.pdf, page 44. | 600 | // 7.3.1 NAL unit syntax, H.264-AVC-ISO_IEC_14496-10.pdf, page 44. |
| 564 | if ((ret = sample->add_sample_unit(stream->data() + stream->pos(), NALUnitLength)) != ERROR_SUCCESS) { | 601 | if ((ret = sample->add_sample_unit(stream->data() + stream->pos(), NALUnitLength)) != ERROR_SUCCESS) { |
| 565 | - srs_error("hls add video sample failed. ret=%d", ret); | 602 | + srs_error("avc add video sample failed. ret=%d", ret); |
| 566 | return ret; | 603 | return ret; |
| 567 | } | 604 | } |
| 568 | stream->skip(NALUnitLength); | 605 | stream->skip(NALUnitLength); |
| @@ -156,6 +156,8 @@ public: | @@ -156,6 +156,8 @@ public: | ||
| 156 | SrsCodecVideoAVCType avc_packet_type; | 156 | SrsCodecVideoAVCType avc_packet_type; |
| 157 | public: | 157 | public: |
| 158 | // audio specified | 158 | // audio specified |
| 159 | + SrsCodecAudio acodec; | ||
| 160 | + // audio aac specified. | ||
| 159 | SrsCodecAudioSampleRate sound_rate; | 161 | SrsCodecAudioSampleRate sound_rate; |
| 160 | SrsCodecAudioSampleSize sound_size; | 162 | SrsCodecAudioSampleSize sound_size; |
| 161 | SrsCodecAudioSoundType sound_type; | 163 | SrsCodecAudioSoundType sound_type; |
| @@ -271,6 +273,7 @@ public: | @@ -271,6 +273,7 @@ public: | ||
| 271 | * demux the aac raw to sample units. | 273 | * demux the aac raw to sample units. |
| 272 | */ | 274 | */ |
| 273 | virtual int audio_aac_demux(char* data, int size, SrsCodecSample* sample); | 275 | virtual int audio_aac_demux(char* data, int size, SrsCodecSample* sample); |
| 276 | + virtual int audio_mp3_demux(char* data, int size, SrsCodecSample* sample); | ||
| 274 | /** | 277 | /** |
| 275 | * demux the video packet in h.264 codec. | 278 | * demux the video packet in h.264 codec. |
| 276 | * the packet mux in FLV/RTMP format defined in flv specification. | 279 | * the packet mux in FLV/RTMP format defined in flv specification. |
| @@ -202,6 +202,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -202,6 +202,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 202 | #define ERROR_AAC_REQUIRED_ADTS 3046 | 202 | #define ERROR_AAC_REQUIRED_ADTS 3046 |
| 203 | #define ERROR_AAC_ADTS_HEADER 3047 | 203 | #define ERROR_AAC_ADTS_HEADER 3047 |
| 204 | #define ERROR_AAC_DATA_INVALID 3048 | 204 | #define ERROR_AAC_DATA_INVALID 3048 |
| 205 | +#define ERROR_HLS_TRY_MP3 3049 | ||
| 205 | 206 | ||
| 206 | /////////////////////////////////////////////////////// | 207 | /////////////////////////////////////////////////////// |
| 207 | // HTTP/StreamCaster protocol error. | 208 | // HTTP/StreamCaster protocol error. |
| @@ -53,6 +53,7 @@ using namespace std; | @@ -53,6 +53,7 @@ using namespace std; | ||
| 53 | 53 | ||
| 54 | // ts aac stream id. | 54 | // ts aac stream id. |
| 55 | #define TS_AUDIO_AAC 0xc0 | 55 | #define TS_AUDIO_AAC 0xc0 |
| 56 | +#define TS_AUDIO_MP3 0x04 | ||
| 56 | // ts avc stream id. | 57 | // ts avc stream id. |
| 57 | #define TS_VIDEO_AVC 0xe0 | 58 | #define TS_VIDEO_AVC 0xe0 |
| 58 | 59 | ||
| @@ -118,11 +119,18 @@ u_int8_t mpegts_header[] = { | @@ -118,11 +119,18 @@ u_int8_t mpegts_header[] = { | ||
| 118 | // must generate header with/without video, @see: | 119 | // must generate header with/without video, @see: |
| 119 | // https://github.com/winlinvip/simple-rtmp-server/issues/40 | 120 | // https://github.com/winlinvip/simple-rtmp-server/issues/40 |
| 120 | 0x1b, 0xe1, 0x00, 0xf0, 0x00, /* h264, pid=0x100=256 */ | 121 | 0x1b, 0xe1, 0x00, 0xf0, 0x00, /* h264, pid=0x100=256 */ |
| 122 | +}; | ||
| 123 | +u_int8_t mpegts_header_aac[] = { | ||
| 121 | 0x0f, 0xe1, 0x01, 0xf0, 0x00, /* aac, pid=0x101=257 */ | 124 | 0x0f, 0xe1, 0x01, 0xf0, 0x00, /* aac, pid=0x101=257 */ |
| 122 | - /*0x03, 0xe1, 0x01, 0xf0, 0x00,*/ /* mp3 */ | ||
| 123 | /* CRC */ | 125 | /* CRC */ |
| 124 | 0x2f, 0x44, 0xb9, 0x9b, /* crc for aac */ | 126 | 0x2f, 0x44, 0xb9, 0x9b, /* crc for aac */ |
| 125 | - /*0x4e, 0x59, 0x3d, 0x1e,*/ /* crc for mp3 */ | 127 | +}; |
| 128 | +u_int8_t mpegts_header_mp3[] = { | ||
| 129 | + 0x03, 0xe1, 0x01, 0xf0, 0x00, /* mp3 */ | ||
| 130 | + /* CRC */ | ||
| 131 | + 0x4e, 0x59, 0x3d, 0x1e, /* crc for mp3 */ | ||
| 132 | +}; | ||
| 133 | +u_int8_t mpegts_header_padding[] = { | ||
| 126 | /* stuffing 157 bytes */ | 134 | /* stuffing 157 bytes */ |
| 127 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 135 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 128 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 136 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| @@ -147,7 +155,7 @@ u_int8_t mpegts_header[] = { | @@ -147,7 +155,7 @@ u_int8_t mpegts_header[] = { | ||
| 147 | class SrsMpegtsWriter | 155 | class SrsMpegtsWriter |
| 148 | { | 156 | { |
| 149 | public: | 157 | public: |
| 150 | - static int write_header(SrsFileWriter* writer) | 158 | + static int write_header(SrsFileWriter* writer, SrsCodecAudio acodec) |
| 151 | { | 159 | { |
| 152 | int ret = ERROR_SUCCESS; | 160 | int ret = ERROR_SUCCESS; |
| 153 | 161 | ||
| @@ -157,6 +165,26 @@ public: | @@ -157,6 +165,26 @@ public: | ||
| 157 | return ret; | 165 | return ret; |
| 158 | } | 166 | } |
| 159 | 167 | ||
| 168 | + if (acodec == SrsCodecAudioAAC) { | ||
| 169 | + if ((ret = writer->write(mpegts_header_aac, sizeof(mpegts_header_aac), NULL)) != ERROR_SUCCESS) { | ||
| 170 | + ret = ERROR_HLS_WRITE_FAILED; | ||
| 171 | + srs_error("write ts file aac header failed. ret=%d", ret); | ||
| 172 | + return ret; | ||
| 173 | + } | ||
| 174 | + } else { | ||
| 175 | + if ((ret = writer->write(mpegts_header_mp3, sizeof(mpegts_header_mp3), NULL)) != ERROR_SUCCESS) { | ||
| 176 | + ret = ERROR_HLS_WRITE_FAILED; | ||
| 177 | + srs_error("write ts file mp3 header failed. ret=%d", ret); | ||
| 178 | + return ret; | ||
| 179 | + } | ||
| 180 | + } | ||
| 181 | + | ||
| 182 | + if ((ret = writer->write(mpegts_header_padding, sizeof(mpegts_header_padding), NULL)) != ERROR_SUCCESS) { | ||
| 183 | + ret = ERROR_HLS_WRITE_FAILED; | ||
| 184 | + srs_error("write ts file padding header failed. ret=%d", ret); | ||
| 185 | + return ret; | ||
| 186 | + } | ||
| 187 | + | ||
| 160 | return ret; | 188 | return ret; |
| 161 | } | 189 | } |
| 162 | static int write_frame(SrsFileWriter* writer, SrsMpegtsFrame* frame, SrsSimpleBuffer* buffer) | 190 | static int write_frame(SrsFileWriter* writer, SrsMpegtsFrame* frame, SrsSimpleBuffer* buffer) |
| @@ -375,6 +403,11 @@ SrsMpegtsFrame::SrsMpegtsFrame() | @@ -375,6 +403,11 @@ SrsMpegtsFrame::SrsMpegtsFrame() | ||
| 375 | SrsTSMuxer::SrsTSMuxer(SrsFileWriter* w) | 403 | SrsTSMuxer::SrsTSMuxer(SrsFileWriter* w) |
| 376 | { | 404 | { |
| 377 | writer = w; | 405 | writer = w; |
| 406 | + | ||
| 407 | + // reserved is not written. | ||
| 408 | + previous = SrsCodecAudioReserved1; | ||
| 409 | + // current default to aac. | ||
| 410 | + current = SrsCodecAudioAAC; | ||
| 378 | } | 411 | } |
| 379 | 412 | ||
| 380 | SrsTSMuxer::~SrsTSMuxer() | 413 | SrsTSMuxer::~SrsTSMuxer() |
| @@ -393,12 +426,19 @@ int SrsTSMuxer::open(string _path) | @@ -393,12 +426,19 @@ int SrsTSMuxer::open(string _path) | ||
| 393 | if ((ret = writer->open(path)) != ERROR_SUCCESS) { | 426 | if ((ret = writer->open(path)) != ERROR_SUCCESS) { |
| 394 | return ret; | 427 | return ret; |
| 395 | } | 428 | } |
| 429 | + | ||
| 430 | + return ret; | ||
| 431 | +} | ||
| 432 | + | ||
| 433 | +int SrsTSMuxer::update_acodec(SrsCodecAudio acodec) | ||
| 434 | +{ | ||
| 435 | + int ret = ERROR_SUCCESS; | ||
| 396 | 436 | ||
| 397 | - // write mpegts header | ||
| 398 | - if ((ret = SrsMpegtsWriter::write_header(writer)) != ERROR_SUCCESS) { | 437 | + if (current == acodec) { |
| 399 | return ret; | 438 | return ret; |
| 400 | } | 439 | } |
| 401 | - | 440 | + current = acodec; |
| 441 | + | ||
| 402 | return ret; | 442 | return ret; |
| 403 | } | 443 | } |
| 404 | 444 | ||
| @@ -406,6 +446,14 @@ int SrsTSMuxer::write_audio(SrsMpegtsFrame* af, SrsSimpleBuffer* ab) | @@ -406,6 +446,14 @@ int SrsTSMuxer::write_audio(SrsMpegtsFrame* af, SrsSimpleBuffer* ab) | ||
| 406 | { | 446 | { |
| 407 | int ret = ERROR_SUCCESS; | 447 | int ret = ERROR_SUCCESS; |
| 408 | 448 | ||
| 449 | + // when acodec changed, write header. | ||
| 450 | + if (current != previous) { | ||
| 451 | + previous = current; | ||
| 452 | + if ((ret = SrsMpegtsWriter::write_header(writer, previous)) != ERROR_SUCCESS) { | ||
| 453 | + return ret; | ||
| 454 | + } | ||
| 455 | + } | ||
| 456 | + | ||
| 409 | if ((ret = SrsMpegtsWriter::write_frame(writer, af, ab)) != ERROR_SUCCESS) { | 457 | if ((ret = SrsMpegtsWriter::write_frame(writer, af, ab)) != ERROR_SUCCESS) { |
| 410 | return ret; | 458 | return ret; |
| 411 | } | 459 | } |
| @@ -417,6 +465,14 @@ int SrsTSMuxer::write_video(SrsMpegtsFrame* vf, SrsSimpleBuffer* vb) | @@ -417,6 +465,14 @@ int SrsTSMuxer::write_video(SrsMpegtsFrame* vf, SrsSimpleBuffer* vb) | ||
| 417 | { | 465 | { |
| 418 | int ret = ERROR_SUCCESS; | 466 | int ret = ERROR_SUCCESS; |
| 419 | 467 | ||
| 468 | + // when acodec changed, write header. | ||
| 469 | + if (current != previous) { | ||
| 470 | + previous = current; | ||
| 471 | + if ((ret = SrsMpegtsWriter::write_header(writer, previous)) != ERROR_SUCCESS) { | ||
| 472 | + return ret; | ||
| 473 | + } | ||
| 474 | + } | ||
| 475 | + | ||
| 420 | if ((ret = SrsMpegtsWriter::write_frame(writer, vf, vb)) != ERROR_SUCCESS) { | 476 | if ((ret = SrsMpegtsWriter::write_frame(writer, vf, vb)) != ERROR_SUCCESS) { |
| 421 | return ret; | 477 | return ret; |
| 422 | } | 478 | } |
| @@ -501,6 +557,8 @@ SrsTsCache::SrsTsCache() | @@ -501,6 +557,8 @@ SrsTsCache::SrsTsCache() | ||
| 501 | 557 | ||
| 502 | af = new SrsMpegtsFrame(); | 558 | af = new SrsMpegtsFrame(); |
| 503 | vf = new SrsMpegtsFrame(); | 559 | vf = new SrsMpegtsFrame(); |
| 560 | + | ||
| 561 | + audio_buffer_start_pts = 0; | ||
| 504 | } | 562 | } |
| 505 | 563 | ||
| 506 | SrsTsCache::~SrsTsCache() | 564 | SrsTsCache::~SrsTsCache() |
| @@ -520,23 +578,53 @@ SrsTsCache::~SrsTsCache() | @@ -520,23 +578,53 @@ SrsTsCache::~SrsTsCache() | ||
| 520 | int SrsTsCache::cache_audio(SrsAvcAacCodec* codec, int64_t pts, SrsCodecSample* sample) | 578 | int SrsTsCache::cache_audio(SrsAvcAacCodec* codec, int64_t pts, SrsCodecSample* sample) |
| 521 | { | 579 | { |
| 522 | int ret = ERROR_SUCCESS; | 580 | int ret = ERROR_SUCCESS; |
| 523 | - | ||
| 524 | - // start buffer, set the af | 581 | + |
| 582 | + // @remark, always use the orignal pts. | ||
| 525 | if (ab->length() == 0) { | 583 | if (ab->length() == 0) { |
| 526 | - pts = aac_jitter->on_buffer_start(pts, sample->sound_rate, codec->aac_sample_rate); | ||
| 527 | - | ||
| 528 | - af->dts = af->pts = pts; | ||
| 529 | - af->pid = TS_AUDIO_PID; | ||
| 530 | - af->sid = TS_AUDIO_AAC; | ||
| 531 | - } else { | ||
| 532 | - aac_jitter->on_buffer_continue(); | 584 | + audio_buffer_start_pts = pts; |
| 533 | } | 585 | } |
| 534 | 586 | ||
| 535 | - // write audio to cache. | ||
| 536 | - if ((ret = do_cache_audio(codec, sample)) != ERROR_SUCCESS) { | 587 | + // must be aac or mp3 |
| 588 | + SrsCodecAudio acodec = (SrsCodecAudio)codec->audio_codec_id; | ||
| 589 | + srs_assert(acodec == SrsCodecAudioAAC || acodec == SrsCodecAudioMP3); | ||
| 590 | + | ||
| 591 | + // cache the aac audio. | ||
| 592 | + if (codec->audio_codec_id == SrsCodecAudioAAC) { | ||
| 593 | + // for aac audio, recalc the timestamp by aac jitter. | ||
| 594 | + if (ab->length() == 0) { | ||
| 595 | + pts = aac_jitter->on_buffer_start(pts, sample->sound_rate, codec->aac_sample_rate); | ||
| 596 | + | ||
| 597 | + af->dts = af->pts = pts; | ||
| 598 | + af->pid = TS_AUDIO_PID; | ||
| 599 | + af->sid = TS_AUDIO_AAC; | ||
| 600 | + } else { | ||
| 601 | + aac_jitter->on_buffer_continue(); | ||
| 602 | + } | ||
| 603 | + | ||
| 604 | + // write aac audio to cache. | ||
| 605 | + if ((ret = do_cache_audio(codec, sample)) != ERROR_SUCCESS) { | ||
| 606 | + return ret; | ||
| 607 | + } | ||
| 608 | + | ||
| 537 | return ret; | 609 | return ret; |
| 538 | } | 610 | } |
| 539 | 611 | ||
| 612 | + // cache the mp3 audio. | ||
| 613 | + if (codec->audio_codec_id == SrsCodecAudioMP3) { | ||
| 614 | + // for mp3 audio, recalc the timestamp by mp3 jitter. | ||
| 615 | + // TODO: FIXME: implements it. | ||
| 616 | + af->dts = af->pts = pts; | ||
| 617 | + af->pid = TS_AUDIO_PID; | ||
| 618 | + af->sid = SrsCodecAudioMP3; | ||
| 619 | + | ||
| 620 | + // for mp3, directly write to cache. | ||
| 621 | + // TODO: FIXME: implements it. | ||
| 622 | + for (int i = 0; i < sample->nb_sample_units; i++) { | ||
| 623 | + SrsCodecSampleUnit* sample_unit = &sample->sample_units[i]; | ||
| 624 | + ab->append(sample_unit->bytes, sample_unit->size); | ||
| 625 | + } | ||
| 626 | + } | ||
| 627 | + | ||
| 540 | return ret; | 628 | return ret; |
| 541 | } | 629 | } |
| 542 | 630 | ||
| @@ -784,16 +872,30 @@ int SrsTsEncoder::write_audio(int64_t timestamp, char* data, int size) | @@ -784,16 +872,30 @@ int SrsTsEncoder::write_audio(int64_t timestamp, char* data, int size) | ||
| 784 | 872 | ||
| 785 | sample->clear(); | 873 | sample->clear(); |
| 786 | if ((ret = codec->audio_aac_demux(data, size, sample)) != ERROR_SUCCESS) { | 874 | if ((ret = codec->audio_aac_demux(data, size, sample)) != ERROR_SUCCESS) { |
| 787 | - srs_error("http: ts codec demux audio failed. ret=%d", ret); | ||
| 788 | - return ret; | 875 | + if (ret != ERROR_HLS_TRY_MP3) { |
| 876 | + srs_error("http: ts aac demux audio failed. ret=%d", ret); | ||
| 877 | + return ret; | ||
| 878 | + } | ||
| 879 | + if ((ret = codec->audio_mp3_demux(data, size, sample)) != ERROR_SUCCESS) { | ||
| 880 | + srs_error("http: ts mp3 demux audio failed. ret=%d", ret); | ||
| 881 | + return ret; | ||
| 882 | + } | ||
| 789 | } | 883 | } |
| 884 | + SrsCodecAudio acodec = (SrsCodecAudio)codec->audio_codec_id; | ||
| 790 | 885 | ||
| 791 | - if (codec->audio_codec_id != SrsCodecAudioAAC) { | 886 | + // ts support audio codec: aac/mp3 |
| 887 | + if (acodec != SrsCodecAudioAAC && acodec != SrsCodecAudioMP3) { | ||
| 888 | + return ret; | ||
| 889 | + } | ||
| 890 | + | ||
| 891 | + // when codec changed, write new header. | ||
| 892 | + if ((ret = muxer->update_acodec(acodec)) != ERROR_SUCCESS) { | ||
| 893 | + srs_error("http: ts audio write header failed. ret=%d", ret); | ||
| 792 | return ret; | 894 | return ret; |
| 793 | } | 895 | } |
| 794 | 896 | ||
| 795 | - // ignore sequence header | ||
| 796 | - if (sample->aac_packet_type == SrsCodecAudioTypeSequenceHeader) { | 897 | + // for aac: ignore sequence header |
| 898 | + if (acodec == SrsCodecAudioAAC && sample->aac_packet_type == SrsCodecAudioTypeSequenceHeader) { | ||
| 797 | return ret; | 899 | return ret; |
| 798 | } | 900 | } |
| 799 | 901 | ||
| @@ -809,12 +911,15 @@ int SrsTsEncoder::write_audio(int64_t timestamp, char* data, int size) | @@ -809,12 +911,15 @@ int SrsTsEncoder::write_audio(int64_t timestamp, char* data, int size) | ||
| 809 | 911 | ||
| 810 | // flush if buffer exceed max size. | 912 | // flush if buffer exceed max size. |
| 811 | if (cache->ab->length() > SRS_AUTO_HLS_AUDIO_CACHE_SIZE) { | 913 | if (cache->ab->length() > SRS_AUTO_HLS_AUDIO_CACHE_SIZE) { |
| 812 | - if ((ret = muxer->write_audio(cache->af, cache->ab)) != ERROR_SUCCESS) { | ||
| 813 | - return ret; | ||
| 814 | - } | ||
| 815 | - | ||
| 816 | - // write success, clear and free the buffer | ||
| 817 | - cache->ab->erase(cache->ab->length()); | 914 | + return flush_video(); |
| 915 | + } | ||
| 916 | + | ||
| 917 | + // TODO: config it. | ||
| 918 | + // in ms, audio delay to flush the audios. | ||
| 919 | + int64_t audio_delay = SRS_CONF_DEFAULT_AAC_DELAY; | ||
| 920 | + // flush if audio delay exceed | ||
| 921 | + if (dts - cache->audio_buffer_start_pts > audio_delay * 90) { | ||
| 922 | + return flush_audio(); | ||
| 818 | } | 923 | } |
| 819 | 924 | ||
| 820 | return ret; | 925 | return ret; |
| @@ -852,6 +957,27 @@ int SrsTsEncoder::write_video(int64_t timestamp, char* data, int size) | @@ -852,6 +957,27 @@ int SrsTsEncoder::write_video(int64_t timestamp, char* data, int size) | ||
| 852 | if ((ret = cache->cache_video(codec, dts, sample)) != ERROR_SUCCESS) { | 957 | if ((ret = cache->cache_video(codec, dts, sample)) != ERROR_SUCCESS) { |
| 853 | return ret; | 958 | return ret; |
| 854 | } | 959 | } |
| 960 | + | ||
| 961 | + return flush_video(); | ||
| 962 | +} | ||
| 963 | + | ||
| 964 | +int SrsTsEncoder::flush_audio() | ||
| 965 | +{ | ||
| 966 | + int ret = ERROR_SUCCESS; | ||
| 967 | + | ||
| 968 | + if ((ret = muxer->write_audio(cache->af, cache->ab)) != ERROR_SUCCESS) { | ||
| 969 | + return ret; | ||
| 970 | + } | ||
| 971 | + | ||
| 972 | + // write success, clear and free the buffer | ||
| 973 | + cache->ab->erase(cache->ab->length()); | ||
| 974 | + | ||
| 975 | + return ret; | ||
| 976 | +} | ||
| 977 | + | ||
| 978 | +int SrsTsEncoder::flush_video() | ||
| 979 | +{ | ||
| 980 | + int ret = ERROR_SUCCESS; | ||
| 855 | 981 | ||
| 856 | if ((ret = muxer->write_video(cache->vf, cache->vb)) != ERROR_SUCCESS) { | 982 | if ((ret = muxer->write_video(cache->vf, cache->vb)) != ERROR_SUCCESS) { |
| 857 | return ret; | 983 | return ret; |
| @@ -31,6 +31,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -31,6 +31,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 31 | 31 | ||
| 32 | #include <string> | 32 | #include <string> |
| 33 | 33 | ||
| 34 | +#include <srs_kernel_codec.hpp> | ||
| 35 | + | ||
| 34 | class SrsTsCache; | 36 | class SrsTsCache; |
| 35 | class SrsTSMuxer; | 37 | class SrsTSMuxer; |
| 36 | class SrsFileWriter; | 38 | class SrsFileWriter; |
| @@ -63,15 +65,40 @@ public: | @@ -63,15 +65,40 @@ public: | ||
| 63 | class SrsTSMuxer | 65 | class SrsTSMuxer |
| 64 | { | 66 | { |
| 65 | private: | 67 | private: |
| 68 | + SrsCodecAudio previous; | ||
| 69 | + SrsCodecAudio current; | ||
| 70 | +private: | ||
| 66 | SrsFileWriter* writer; | 71 | SrsFileWriter* writer; |
| 67 | std::string path; | 72 | std::string path; |
| 68 | public: | 73 | public: |
| 69 | SrsTSMuxer(SrsFileWriter* w); | 74 | SrsTSMuxer(SrsFileWriter* w); |
| 70 | virtual ~SrsTSMuxer(); | 75 | virtual ~SrsTSMuxer(); |
| 71 | public: | 76 | public: |
| 77 | + /** | ||
| 78 | + * open the writer, donot write the PSI of ts. | ||
| 79 | + */ | ||
| 72 | virtual int open(std::string _path); | 80 | virtual int open(std::string _path); |
| 81 | + /** | ||
| 82 | + * when open ts, we donot write the header(PSI), | ||
| 83 | + * for user may need to update the acodec to mp3 or others, | ||
| 84 | + * so we use delay write PSI, when write audio or video. | ||
| 85 | + * @remark for audio aac codec, for example, SRS1, it's ok to write PSI when open ts. | ||
| 86 | + * @see https://github.com/winlinvip/simple-rtmp-server/issues/301 | ||
| 87 | + */ | ||
| 88 | + virtual int update_acodec(SrsCodecAudio acodec); | ||
| 89 | + /** | ||
| 90 | + * write an audio frame to ts, | ||
| 91 | + * @remark write PSI first when not write yet. | ||
| 92 | + */ | ||
| 73 | virtual int write_audio(SrsMpegtsFrame* af, SrsSimpleBuffer* ab); | 93 | virtual int write_audio(SrsMpegtsFrame* af, SrsSimpleBuffer* ab); |
| 94 | + /** | ||
| 95 | + * write a video frame to ts, | ||
| 96 | + * @remark write PSI first when not write yet. | ||
| 97 | + */ | ||
| 74 | virtual int write_video(SrsMpegtsFrame* vf, SrsSimpleBuffer* vb); | 98 | virtual int write_video(SrsMpegtsFrame* vf, SrsSimpleBuffer* vb); |
| 99 | + /** | ||
| 100 | + * close the writer. | ||
| 101 | + */ | ||
| 75 | virtual void close(); | 102 | virtual void close(); |
| 76 | }; | 103 | }; |
| 77 | 104 | ||
| @@ -125,6 +152,10 @@ public: | @@ -125,6 +152,10 @@ public: | ||
| 125 | SrsSimpleBuffer* ab; | 152 | SrsSimpleBuffer* ab; |
| 126 | SrsMpegtsFrame* vf; | 153 | SrsMpegtsFrame* vf; |
| 127 | SrsSimpleBuffer* vb; | 154 | SrsSimpleBuffer* vb; |
| 155 | +public: | ||
| 156 | + // the audio cache buffer start pts, to flush audio if full. | ||
| 157 | + // @remark the pts is not the adjust one, it's the orignal pts. | ||
| 158 | + int64_t audio_buffer_start_pts; | ||
| 128 | protected: | 159 | protected: |
| 129 | // time jitter for aac | 160 | // time jitter for aac |
| 130 | SrsTsAacJitter* aac_jitter; | 161 | SrsTsAacJitter* aac_jitter; |
| @@ -172,6 +203,9 @@ public: | @@ -172,6 +203,9 @@ public: | ||
| 172 | */ | 203 | */ |
| 173 | virtual int write_audio(int64_t timestamp, char* data, int size); | 204 | virtual int write_audio(int64_t timestamp, char* data, int size); |
| 174 | virtual int write_video(int64_t timestamp, char* data, int size); | 205 | virtual int write_video(int64_t timestamp, char* data, int size); |
| 206 | +private: | ||
| 207 | + virtual int flush_audio(); | ||
| 208 | + virtual int flush_video(); | ||
| 175 | }; | 209 | }; |
| 176 | 210 | ||
| 177 | #endif | 211 | #endif |
-
请 注册 或 登录 后发表评论