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;
};