diff --git a/trunk/auto/depends.sh b/trunk/auto/depends.sh index 57596ecbf..4cf1b7e0d 100755 --- a/trunk/auto/depends.sh +++ b/trunk/auto/depends.sh @@ -695,15 +695,16 @@ fi # ffmpeg-fit, for WebRTC to transcode AAC with Opus. ##################################################################################### if [[ $SRS_FFMPEG_FIT == YES ]]; then - FFMPEG_OPTIONS="" if [[ $SRS_CROSS_BUILD == YES ]]; then - FFMPEG_CONFIGURE=./configure + FFMPEG_CONFIGURE="./configure" else FFMPEG_CONFIGURE="env PKG_CONFIG_PATH=${SRS_DEPENDS_LIBS}/opus/lib/pkgconfig ./configure" fi + # Disable all features, note that there are still some options need to be disabled. + FFMPEG_OPTIONS="--disable-everything" # Disable all asm for FFmpeg, to compatible with ARM CPU. - FFMPEG_OPTIONS="--disable-asm --disable-x86asm --disable-inline-asm" + FFMPEG_OPTIONS="$FFMPEG_OPTIONS --disable-asm --disable-x86asm --disable-inline-asm" # Only build static libraries if no shared FFmpeg. if [[ $SRS_SHARED_FFMPEG == YES ]]; then FFMPEG_OPTIONS="$FFMPEG_OPTIONS --enable-shared" @@ -725,6 +726,17 @@ if [[ $SRS_FFMPEG_FIT == YES ]]; then else FFMPEG_OPTIONS="$FFMPEG_OPTIONS --enable-decoder=libopus --enable-encoder=libopus --enable-libopus" fi + # Disable features of ffmpeg. + FFMPEG_OPTIONS="$FFMPEG_OPTIONS --disable-avdevice --disable-avformat --disable-swscale --disable-postproc --disable-avfilter --disable-network" + FFMPEG_OPTIONS="$FFMPEG_OPTIONS --disable-dwt --disable-error-resilience --disable-lsp --disable-lzo --disable-faan --disable-pixelutils" + FFMPEG_OPTIONS="$FFMPEG_OPTIONS --disable-hwaccels --disable-devices --disable-audiotoolbox --disable-videotoolbox --disable-cuvid" + FFMPEG_OPTIONS="$FFMPEG_OPTIONS --disable-d3d11va --disable-dxva2 --disable-ffnvcodec --disable-nvdec --disable-nvenc --disable-v4l2-m2m --disable-vaapi" + FFMPEG_OPTIONS="$FFMPEG_OPTIONS --disable-vdpau --disable-appkit --disable-coreimage --disable-avfoundation --disable-securetransport --disable-iconv" + FFMPEG_OPTIONS="$FFMPEG_OPTIONS --disable-lzma --disable-sdl2" + # Enable FFmpeg native AAC encoder and decoder. + FFMPEG_OPTIONS="$FFMPEG_OPTIONS --enable-decoder=aac --enable-decoder=aac_fixed --enable-decoder=aac_latm --enable-encoder=aac" + # Enable FFmpeg native MP3 decoder, which depends on dct. + FFMPEG_OPTIONS="$FFMPEG_OPTIONS --enable-decoder=mp3 --enable-dct" if [[ -f ${SRS_OBJS}/${SRS_PLATFORM}/3rdpatry/ffmpeg/lib/libavcodec.a ]]; then rm -rf ${SRS_OBJS}/ffmpeg && cp -rf ${SRS_OBJS}/${SRS_PLATFORM}/3rdpatry/ffmpeg ${SRS_OBJS}/ && @@ -736,18 +748,9 @@ if [[ $SRS_FFMPEG_FIT == YES ]]; then cp -rf ${SRS_WORKDIR}/3rdparty/ffmpeg-4-fit ${SRS_OBJS}/${SRS_PLATFORM}/ && ( cd ${SRS_OBJS}/${SRS_PLATFORM}/ffmpeg-4-fit && - $FFMPEG_CONFIGURE \ - --prefix=${SRS_DEPENDS_LIBS}/${SRS_PLATFORM}/3rdpatry/ffmpeg --pkg-config=pkg-config \ - --pkg-config-flags="--static" --extra-libs="-lpthread" --extra-libs="-lm" \ - --disable-everything ${FFMPEG_OPTIONS} \ - --disable-programs --disable-doc --disable-htmlpages --disable-manpages --disable-podpages --disable-txtpages \ - --disable-avdevice --disable-avformat --disable-swscale --disable-postproc --disable-avfilter --disable-network \ - --disable-dct --disable-dwt --disable-error-resilience --disable-lsp --disable-lzo --disable-faan --disable-pixelutils \ - --disable-hwaccels --disable-devices --disable-audiotoolbox --disable-videotoolbox --disable-cuvid \ - --disable-d3d11va --disable-dxva2 --disable-ffnvcodec --disable-nvdec --disable-nvenc --disable-v4l2-m2m --disable-vaapi \ - --disable-vdpau --disable-appkit --disable-coreimage --disable-avfoundation --disable-securetransport --disable-iconv \ - --disable-lzma --disable-sdl2 --enable-decoder=aac --enable-decoder=aac_fixed --enable-decoder=aac_latm \ - --enable-encoder=aac + $FFMPEG_CONFIGURE --prefix=${SRS_DEPENDS_LIBS}/${SRS_PLATFORM}/3rdpatry/ffmpeg \ + --pkg-config=pkg-config --pkg-config-flags='--static' --extra-libs='-lpthread' --extra-libs='-lm' \ + ${FFMPEG_OPTIONS} ) && # See https://www.laoyuyu.me/2019/05/23/android/clang_compile_ffmpeg/ if [[ $SRS_CROSS_BUILD == YES ]]; then diff --git a/trunk/conf/mp3.rtc.conf b/trunk/conf/mp3.rtc.conf new file mode 100644 index 000000000..6268e0ae5 --- /dev/null +++ b/trunk/conf/mp3.rtc.conf @@ -0,0 +1,32 @@ +listen 1935; +max_connections 1000; +daemon off; +srs_log_tank console; +http_server { + enabled on; + listen 8080; + dir ./objs/nginx/html; +} +rtc_server { + enabled on; + listen 8000; # UDP port + # @see https://ossrs.net/lts/zh-cn/docs/v4/doc/webrtc#config-candidate + candidate $CANDIDATE; +} +vhost __defaultVhost__ { + http_remux { + enabled on; + mount [vhost]/[app]/[stream].flv; + } + hls { + enabled on; + hls_acodec mp3; + } + rtc { + enabled on; + # @see https://ossrs.net/lts/zh-cn/docs/v4/doc/webrtc#rtmp-to-rtc + rtmp_to_rtc on; + # @see https://ossrs.net/lts/zh-cn/docs/v4/doc/webrtc#rtc-to-rtmp + rtc_to_rtmp on; + } +} diff --git a/trunk/doc/CHANGELOG.md b/trunk/doc/CHANGELOG.md index d63452553..ad9dd1970 100644 --- a/trunk/doc/CHANGELOG.md +++ b/trunk/doc/CHANGELOG.md @@ -21,6 +21,7 @@ The changelog for SRS. ## SRS 5.0 Changelog +* v5.0, 2022-12-26, For [#296](https://github.com/ossrs/srs/issues/296): MP3: Convert RTMP(MP3) to WebRTC(OPUS). v5.0.118 * v5.0, 2022-12-25, For [#296](https://github.com/ossrs/srs/issues/296): MP3: Support dump stream information. v5.0.117 * v5.0, 2022-12-25, For [#296](https://github.com/ossrs/srs/issues/296): MP3: Support mp3 for RTMP/HLS/HTTP-FLV/HTTP-TS/HLS etc. v5.0.116 * v5.0, 2022-12-24, Fix [#3328](https://github.com/ossrs/srs/issues/3328): Docker: Avoiding duplicated copy files. v5.0.115 diff --git a/trunk/src/app/srs_app_rtc_codec.cpp b/trunk/src/app/srs_app_rtc_codec.cpp index 9a8b2575c..50e983321 100644 --- a/trunk/src/app/srs_app_rtc_codec.cpp +++ b/trunk/src/app/srs_app_rtc_codec.cpp @@ -14,6 +14,8 @@ static const AVCodec* srs_find_decoder_by_id(SrsAudioCodecId id) { if (id == SrsAudioCodecIdAAC) { return avcodec_find_decoder_by_name("aac"); + } else if (id == SrsAudioCodecIdMP3) { + return avcodec_find_decoder_by_name("mp3"); } else if (id == SrsAudioCodecIdOpus) { const AVCodec* codec = avcodec_find_decoder_by_name("libopus"); if (!codec) { diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index 0c760ccd2..4f57e5944 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -717,6 +717,7 @@ SrsRtcFromRtmpBridge::SrsRtcFromRtmpBridge(SrsRtcSource* source) source_ = source; format = new SrsRtmpFormat(); codec_ = new SrsAudioTranscoder(); + latest_codec_ = SrsAudioCodecIdForbidden; rtmp_to_rtc = false; keep_bframe = false; merge_nalus = false; @@ -766,12 +767,6 @@ srs_error_t SrsRtcFromRtmpBridge::initialize(SrsRequest* r) // Setup the SPS/PPS parsing strategy. format->try_annexb_first = _srs_config->try_annexb_first(r->vhost); - - int bitrate = 48000; // The output bitrate in bps. - if ((err = codec_->initialize(SrsAudioCodecIdAAC, SrsAudioCodecIdOpus, kAudioChannel, kAudioSamplerate, - bitrate)) != srs_success) { - return srs_error_wrap(err, "init codec"); - } } keep_bframe = _srs_config->get_rtc_keep_bframe(req->vhost); @@ -831,6 +826,11 @@ srs_error_t SrsRtcFromRtmpBridge::on_audio(SrsSharedPtrMessage* msg) return srs_error_wrap(err, "format consume audio"); } + // Try to init codec when startup or codec changed. + if (format->acodec && (err = init_codec(format->acodec->id)) != srs_success) { + return srs_error_wrap(err, "init codec"); + } + // Ignore if no format->acodec, it means the codec is not parsed, or unknown codec. // @issue https://github.com/ossrs/srs/issues/1506#issuecomment-562079474 if (!format->acodec) { @@ -843,14 +843,18 @@ srs_error_t SrsRtcFromRtmpBridge::on_audio(SrsSharedPtrMessage* msg) return err; } + // ignore sequence header + srs_assert(format->audio); + + if (format->acodec->id == SrsAudioCodecIdMP3) { + return transcode(format->audio); + } + // When drop aac audio packet, never transcode. if (acodec != SrsAudioCodecIdAAC) { return err; } - // ignore sequence header - srs_assert(format->audio); - char* adts_audio = NULL; int nn_adts_audio = 0; // TODO: FIXME: Reserve 7 bytes header when create shared message. @@ -875,6 +879,35 @@ srs_error_t SrsRtcFromRtmpBridge::on_audio(SrsSharedPtrMessage* msg) return err; } +srs_error_t SrsRtcFromRtmpBridge::init_codec(SrsAudioCodecId codec) +{ + srs_error_t err = srs_success; + + // Ignore if not changed. + if (latest_codec_ == codec) return err; + + // Create a new codec. + srs_freep(codec_); + codec_ = new SrsAudioTranscoder(); + + // Initialize the codec according to the codec in stream. + int bitrate = 48000; // The output bitrate in bps. + if ((err = codec_->initialize(codec, SrsAudioCodecIdOpus, kAudioChannel, kAudioSamplerate, bitrate)) != srs_success) { + return srs_error_wrap(err, "init codec=%d", codec); + } + + // Update the latest codec in stream. + if (latest_codec_ == SrsAudioCodecIdForbidden) { + srs_trace("RTMP2RTC: Init audio codec to %d(%s)", codec, srs_audio_codec_id2str(codec).c_str()); + } else { + srs_trace("RTMP2RTC: Switch audio codec %d(%s) to %d(%s)", latest_codec_, srs_audio_codec_id2str(latest_codec_).c_str(), + codec, srs_audio_codec_id2str(codec).c_str()); + } + latest_codec_ = codec; + + return err; +} + srs_error_t SrsRtcFromRtmpBridge::transcode(SrsAudioFrame* audio) { srs_error_t err = srs_success; diff --git a/trunk/src/app/srs_app_rtc_source.hpp b/trunk/src/app/srs_app_rtc_source.hpp index d7ec8dc07..d38e6d2ee 100644 --- a/trunk/src/app/srs_app_rtc_source.hpp +++ b/trunk/src/app/srs_app_rtc_source.hpp @@ -254,6 +254,7 @@ private: SrsMetaCache* meta; private: bool rtmp_to_rtc; + SrsAudioCodecId latest_codec_; SrsAudioTranscoder* codec_; bool keep_bframe; bool merge_nalus; @@ -272,6 +273,7 @@ public: virtual void on_unpublish(); virtual srs_error_t on_audio(SrsSharedPtrMessage* msg); private: + srs_error_t init_codec(SrsAudioCodecId codec); srs_error_t transcode(SrsAudioFrame* audio); srs_error_t package_opus(SrsAudioFrame* audio, SrsRtpPacket* pkt); public: diff --git a/trunk/src/core/srs_core_version5.hpp b/trunk/src/core/srs_core_version5.hpp index eff14fa38..25a9a934d 100644 --- a/trunk/src/core/srs_core_version5.hpp +++ b/trunk/src/core/srs_core_version5.hpp @@ -9,6 +9,6 @@ #define VERSION_MAJOR 5 #define VERSION_MINOR 0 -#define VERSION_REVISION 117 +#define VERSION_REVISION 118 #endif