From bb2d7063c4c99f958ec94de3ad44a364c8e6e894 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Tue, 16 May 2023 20:24:55 +0200 Subject: [PATCH] Update ffmpeg --- .ci/build-linux.sh | 1 + .ci/build-mac.sh | 3 +- 3rdparty/CMakeLists.txt | 23 +++------------ 3rdparty/ffmpeg | 2 +- CMakeLists.txt | 1 + buildfiles/msvc/rpcs3_default.props | 2 +- rpcs3/Emu/Cell/Modules/cellAdec.cpp | 43 +++++++++++++++-------------- rpcs3/util/media_utils.cpp | 37 +++++++++++++++++++++---- 8 files changed, 64 insertions(+), 48 deletions(-) diff --git a/.ci/build-linux.sh b/.ci/build-linux.sh index a0e609efb1..3e42e6d2bb 100755 --- a/.ci/build-linux.sh +++ b/.ci/build-linux.sh @@ -40,6 +40,7 @@ cmake .. \ -DCMAKE_RANLIB="$RANLIB" \ -DUSE_SYSTEM_CURL=ON \ -DUSE_SDL=ON \ + -DUSE_SYSTEM_FFMPEG=OFF \ -DOpenGL_GL_PREFERENCE=LEGACY \ -DLLVM_DIR=/opt/llvm/lib/cmake/llvm \ -DSTATIC_LINK_LLVM=ON \ diff --git a/.ci/build-mac.sh b/.ci/build-mac.sh index 8116d93484..6276fe92d9 100755 --- a/.ci/build-mac.sh +++ b/.ci/build-mac.sh @@ -6,7 +6,7 @@ brew install -f --overwrite nasm ninja git p7zip create-dmg ccache pipenv #/usr/sbin/softwareupdate --install-rosetta --agree-to-license arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" arch -x86_64 /usr/local/bin/brew update -arch -x86_64 /usr/local/bin/brew install -f --overwrite llvm@16 sdl2 glew cmake faudio vulkan-headers +arch -x86_64 /usr/local/bin/brew install -f --overwrite llvm@16 sdl2 glew cmake faudio vulkan-headers ffmpeg arch -x86_64 /usr/local/bin/brew link -f llvm@16 # moltenvk based on commit for 1.2.4 release @@ -74,6 +74,7 @@ mkdir build && cd build || exit 1 -DUSE_ALSA=OFF \ -DUSE_PULSE=OFF \ -DUSE_AUDIOUNIT=ON \ + -DUSE_SYSTEM_FFMPEG=ON \ -DLLVM_CCACHE_BUILD=OFF \ -DLLVM_BUILD_RUNTIME=OFF \ -DLLVM_BUILD_TOOLS=OFF \ diff --git a/3rdparty/CMakeLists.txt b/3rdparty/CMakeLists.txt index 021a9f16ab..1fc11fb4d9 100644 --- a/3rdparty/CMakeLists.txt +++ b/3rdparty/CMakeLists.txt @@ -267,32 +267,17 @@ if(USE_SYSTEM_FFMPEG) target_link_libraries(3rdparty_ffmpeg INTERFACE ${FFMPEG_LIBRARIES}) else() if (NOT MSVC AND WIN32) - message(STATUS "RPCS3: building ffmpeg submodule") - - include(ProcessorCount) - ProcessorCount(N) - - ExternalProject_Add(ffmpeg-mingw - DOWNLOAD_COMMAND "" - SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/ffmpeg - BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/ffmpeg - CONFIGURE_COMMAND bash ${CMAKE_CURRENT_SOURCE_DIR}/ffmpeg/configure --prefix=./windows/x86_64 --arch=x86_64 --disable-avdevice --disable-programs --disable-avfilter --disable-postproc --disable-doc --disable-pthreads --enable-w32threads --disable-network --disable-everything --disable-encoders --disable-muxers --disable-hwaccels --disable-parsers --disable-protocols --enable-dxva2 --enable-static --disable-shared --enable-decoder=aac --enable-decoder=aac_latm --enable-decoder=atrac3 --enable-decoder=atrac3p --enable-decoder=mp3 --enable-decoder=pcm_s16le --enable-decoder=pcm_s8 --enable-decoder=h264 --enable-decoder=mpeg4 --enable-decoder=mpeg2video --enable-decoder=mjpeg --enable-decoder=mjpegb --enable-encoder=pcm_s16le --enable-encoder=ffv1 --enable-encoder=mpeg4 --enable-parser=h264 --enable-parser=mpeg4video --enable-parser=mpegaudio --enable-parser=mpegvideo --enable-parser=mjpeg --enable-parser=aac --enable-parser=aac_latm --enable-muxer=avi --enable-demuxer=h264 --enable-demuxer=m4v --enable-demuxer=mp3 --enable-demuxer=mpegvideo --enable-demuxer=mpegps --enable-demuxer=mjpeg --enable-demuxer=avi --enable-demuxer=aac --enable-demuxer=pmp --enable-demuxer=oma --enable-demuxer=pcm_s16le --enable-demuxer=pcm_s8 --enable-demuxer=wav --enable-hwaccel=h264_dxva2 --enable-indev=dshow --enable-protocol=file - BUILD_COMMAND make -j ${N} - INSTALL_COMMAND make install - ) - - target_link_directories(3rdparty_ffmpeg INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/ffmpeg/windows/x86_64/lib") - target_link_libraries(3rdparty_ffmpeg INTERFACE avformat avcodec avutil swscale swresample iconv) + message(FATAL_ERROR "-- RPCS3: building ffmpeg submodule is currently not supported") else() message(STATUS "RPCS3: using builtin ffmpeg") if (WIN32) - set(FFMPEG_LIB_DIR "ffmpeg/windows/x86_64") + set(FFMPEG_LIB_DIR "ffmpeg/lib/windows/x86_64") target_link_libraries(3rdparty_ffmpeg INTERFACE "Bcrypt.lib") elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") - set(FFMPEG_LIB_DIR "ffmpeg/linux/x86_64") + set(FFMPEG_LIB_DIR "ffmpeg/lib/linux/ubuntu-20.04/x86_64") elseif(APPLE) - set(FFMPEG_LIB_DIR "ffmpeg/macos/x86_64") + set(FFMPEG_LIB_DIR "ffmpeg/lib/macos/x86_64") else() message(FATAL_ERROR "Prebuilt ffmpeg is not available on this platform! Try USE_SYSTEM_FFMPEG=ON.") endif() diff --git a/3rdparty/ffmpeg b/3rdparty/ffmpeg index bf019f8c88..d9f2a87e81 160000 --- a/3rdparty/ffmpeg +++ b/3rdparty/ffmpeg @@ -1 +1 @@ -Subproject commit bf019f8c88bc64638fccef62840e935ab2689a4a +Subproject commit d9f2a87e8112d1c1217adabb0dc945d8ad2da657 diff --git a/CMakeLists.txt b/CMakeLists.txt index 4c6eadc999..8887c21d36 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,6 +26,7 @@ option(USE_VULKAN "Vulkan render backend" ON) option(USE_PRECOMPILED_HEADERS "Use precompiled headers" OFF) option(USE_SDL "Enables SDL input handler" OFF) option(USE_SYSTEM_SDL "Prefer system SDL instead of the builtin one" OFF) +option(USE_SYSTEM_FFMPEG "Prefer system ffmpeg instead of the prebuild one" OFF) set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/buildfiles/cmake") diff --git a/buildfiles/msvc/rpcs3_default.props b/buildfiles/msvc/rpcs3_default.props index b3ac8aae1c..6f5030c91d 100644 --- a/buildfiles/msvc/rpcs3_default.props +++ b/buildfiles/msvc/rpcs3_default.props @@ -24,7 +24,7 @@ xxhash.lib;ws2_32.lib;Iphlpapi.lib;Bcrypt.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib - ..\3rdparty\ffmpeg\windows\x86_64 + ..\3rdparty\ffmpeg\lib\windows\x86_64 8388608 1048576 diff --git a/rpcs3/Emu/Cell/Modules/cellAdec.cpp b/rpcs3/Emu/Cell/Modules/cellAdec.cpp index 77deedc265..5a62e03b11 100644 --- a/rpcs3/Emu/Cell/Modules/cellAdec.cpp +++ b/rpcs3/Emu/Cell/Modules/cellAdec.cpp @@ -588,10 +588,10 @@ public: frame.auAddr = task.au.addr; frame.auSize = task.au.size; frame.userdata = task.au.userdata; - frame.size = frame.data->nb_samples * frame.data->channels * nbps; + frame.size = frame.data->nb_samples * frame.data->ch_layout.nb_channels * nbps; //cellAdec.notice("got audio frame (pts=0x%llx, nb_samples=%d, ch=%d, sample_rate=%d, nbps=%d)", - //frame.pts, frame.data->nb_samples, frame.data->channels, frame.data->sample_rate, nbps); + //frame.pts, frame.data->nb_samples, frame.data->ch_layout.nb_channels, frame.data->sample_rate, nbps); if (frames.push(frame, &is_closed)) { @@ -944,7 +944,7 @@ error_code cellAdecGetPcm(u32 handle, vm::ptr outBuffer) if (outBuffer) { // reverse byte order: - if (frame->format == AV_SAMPLE_FMT_FLTP && frame->channels == 1) + if (frame->format == AV_SAMPLE_FMT_FLTP && frame->ch_layout.nb_channels == 1) { float* in_f = reinterpret_cast(frame->extended_data[0]); for (u32 i = 0; i < af.size / 4; i++) @@ -952,7 +952,7 @@ error_code cellAdecGetPcm(u32 handle, vm::ptr outBuffer) outBuffer[i] = in_f[i]; } } - else if (frame->format == AV_SAMPLE_FMT_FLTP && frame->channels == 2) + else if (frame->format == AV_SAMPLE_FMT_FLTP && frame->ch_layout.nb_channels == 2) { float* in_f[2]; in_f[0] = reinterpret_cast(frame->extended_data[0]); @@ -963,7 +963,7 @@ error_code cellAdecGetPcm(u32 handle, vm::ptr outBuffer) outBuffer[i * 2 + 1] = in_f[1][i]; } } - else if (frame->format == AV_SAMPLE_FMT_FLTP && frame->channels == 6) + else if (frame->format == AV_SAMPLE_FMT_FLTP && frame->ch_layout.nb_channels == 6) { float* in_f[6]; in_f[0] = reinterpret_cast(frame->extended_data[0]); @@ -982,7 +982,7 @@ error_code cellAdecGetPcm(u32 handle, vm::ptr outBuffer) outBuffer[i * 6 + 5] = in_f[5][i]; } } - else if (frame->format == AV_SAMPLE_FMT_FLTP && frame->channels == 8) + else if (frame->format == AV_SAMPLE_FMT_FLTP && frame->ch_layout.nb_channels == 8) { float* in_f[8]; in_f[0] = reinterpret_cast(frame->extended_data[0]); @@ -1005,7 +1005,7 @@ error_code cellAdecGetPcm(u32 handle, vm::ptr outBuffer) outBuffer[i * 8 + 7] = in_f[7][i]; } } - else if (frame->format == AV_SAMPLE_FMT_S16P && frame->channels == 1) + else if (frame->format == AV_SAMPLE_FMT_S16P && frame->ch_layout.nb_channels == 1) { s16* in_i = reinterpret_cast(frame->extended_data[0]); for (u32 i = 0; i < af.size / 2; i++) @@ -1013,7 +1013,7 @@ error_code cellAdecGetPcm(u32 handle, vm::ptr outBuffer) outBuffer[i] = in_i[i] / 32768.f; } } - else if (frame->format == AV_SAMPLE_FMT_S16P && frame->channels == 2) + else if (frame->format == AV_SAMPLE_FMT_S16P && frame->ch_layout.nb_channels == 2) { s16* in_i[2]; in_i[0] = reinterpret_cast(frame->extended_data[0]); @@ -1026,7 +1026,7 @@ error_code cellAdecGetPcm(u32 handle, vm::ptr outBuffer) } else { - fmt::throw_exception("Unsupported frame format (channels=%d, format=%d)", frame->channels, frame->format); + fmt::throw_exception("Unsupported frame format (channels=%d, format=%d)", frame->ch_layout.nb_channels, frame->format); } } @@ -1078,25 +1078,26 @@ error_code cellAdecGetPcmItem(u32 handle, vm::pptr pcmItem) atx->samplingFreq = frame->sample_rate; atx->nbytes = frame->nb_samples * u32{sizeof(float)}; - if (frame->channels == 1) + + switch (frame->ch_layout.nb_channels) { - atx->channelConfigIndex = 1; - } - else if (frame->channels == 2) + case 1: + case 2: + case 6: { - atx->channelConfigIndex = 2; + atx->channelConfigIndex = frame->ch_layout.nb_channels; + break; } - else if (frame->channels == 6) - { - atx->channelConfigIndex = 6; - } - else if (frame->channels == 8) + case 8: { atx->channelConfigIndex = 7; + break; } - else + default: { - cellAdec.fatal("cellAdecGetPcmItem(): unsupported channel count (%d)", frame->channels); + cellAdec.fatal("cellAdecGetPcmItem(): unsupported channel count (%d)", frame->ch_layout.nb_channels); + break; + } } } else if (adec->type == CELL_ADEC_TYPE_MP3) diff --git a/rpcs3/util/media_utils.cpp b/rpcs3/util/media_utils.cpp index 7eb16a7878..f99617f98f 100644 --- a/rpcs3/util/media_utils.cpp +++ b/rpcs3/util/media_utils.cpp @@ -363,14 +363,14 @@ namespace utils } const int dst_channels = 2; - const u64 dst_channel_layout = AV_CH_LAYOUT_STEREO; + const AVChannelLayout dst_channel_layout = AV_CHANNEL_LAYOUT_STEREO; const AVSampleFormat dst_format = AV_SAMPLE_FMT_FLT; int set_err = 0; - if ((set_err = av_opt_set_int(av.swr, "in_channel_count", stream->codecpar->channels, 0)) || + if ((set_err = av_opt_set_int(av.swr, "in_channel_count", stream->codecpar->ch_layout.nb_channels, 0)) || (set_err = av_opt_set_int(av.swr, "out_channel_count", dst_channels, 0)) || - (set_err = av_opt_set_channel_layout(av.swr, "in_channel_layout", stream->codecpar->channel_layout, 0)) || - (set_err = av_opt_set_channel_layout(av.swr, "out_channel_layout", dst_channel_layout, 0)) || + (set_err = av_opt_set_chlayout(av.swr, "in_channel_layout", &stream->codecpar->ch_layout, 0)) || + (set_err = av_opt_set_chlayout(av.swr, "out_channel_layout", &dst_channel_layout, 0)) || (set_err = av_opt_set_int(av.swr, "in_sample_rate", stream->codecpar->sample_rate, 0)) || (set_err = av_opt_set_int(av.swr, "out_sample_rate", sample_rate, 0)) || (set_err = av_opt_set_sample_fmt(av.swr, "in_sample_fmt", static_cast(stream->codecpar->format), 0)) || @@ -710,15 +710,42 @@ namespace utils if (!codec) return nullptr; + // Try to find a preferable output format + std::vector oformats; + void* opaque = nullptr; for (const AVOutputFormat* oformat = av_muxer_iterate(&opaque); !!oformat; oformat = av_muxer_iterate(&opaque)) { if (avformat_query_codec(oformat, codec->id, FF_COMPLIANCE_STRICT) == 1) { - return oformat->name; + media_log.notice("video_encoder: Found output format '%s'", oformat->name); + + switch (codec->id) + { + case AV_CODEC_ID_MPEG4: + if (strcmp(oformat->name, "avi") == 0) + return oformat->name; + break; + case AV_CODEC_ID_H264: + case AV_CODEC_ID_MJPEG: + // TODO + break; + default: + break; + } + + oformats.push_back(oformat); } } + // Fallback to first found format + if (!oformats.empty() && oformats.front()) + { + const AVOutputFormat* oformat = oformats.front(); + media_log.notice("video_encoder: Falling back to output format '%s'", oformat->name); + return oformat->name; + } + return nullptr; };