diff --git a/3rdparty/ffmpeg b/3rdparty/ffmpeg index ec6367d3ba..49c364cdc7 160000 --- a/3rdparty/ffmpeg +++ b/3rdparty/ffmpeg @@ -1 +1 @@ -Subproject commit ec6367d3ba9d0d57b9d22d4b87da8144acaf428f +Subproject commit 49c364cdc7a0188cd7db30283559869624b713e5 diff --git a/rpcs3/Emu/Cell/Modules/cellAtracXdec.cpp b/rpcs3/Emu/Cell/Modules/cellAtracXdec.cpp index 36228d8a5e..955727b05b 100644 --- a/rpcs3/Emu/Cell/Modules/cellAtracXdec.cpp +++ b/rpcs3/Emu/Cell/Modules/cellAtracXdec.cpp @@ -113,6 +113,42 @@ void AtracXdecDecoder::alloc_avcodec() ensure(!(codec->capabilities & AV_CODEC_CAP_SUBFRAMES)); + packet = av_packet_alloc(); + if (!packet) + { + fmt::throw_exception("av_packet_alloc() failed"); + } + + frame = av_frame_alloc(); + if (!frame) + { + fmt::throw_exception("av_frame_alloc() failed"); + } +} + +void AtracXdecDecoder::free_avcodec() +{ + if (packet) + { + av_packet_free(&packet); + } + if (frame) + { + av_frame_free(&frame); + } + if (ctx) + { + avcodec_free_context(&ctx); + } +} + +void AtracXdecDecoder::init_avcodec() +{ + if (ctx) + { + avcodec_free_context(&ctx); + } + ctx = avcodec_alloc_context3(codec); if (!ctx) { @@ -133,34 +169,6 @@ void AtracXdecDecoder::alloc_avcodec() frame->buf[0] = av_buffer_create(frame->data[0], ATXDEC_SAMPLES_PER_FRAME * sizeof(f32) * frame->ch_layout.nb_channels, [](void*, uint8_t*){}, nullptr, 0); return 0; }; - - packet = av_packet_alloc(); - if (!packet) - { - fmt::throw_exception("av_packet_alloc() failed"); - } - - frame = av_frame_alloc(); - if (!frame) - { - fmt::throw_exception("av_frame_alloc() failed"); - } -} - -void AtracXdecDecoder::free_avcodec() -{ - av_packet_free(&packet); - av_frame_free(&frame); - avcodec_free_context(&ctx); -} - -void AtracXdecDecoder::init_avcodec() -{ - if (int err = avcodec_close(ctx); err) - { - fmt::throw_exception("avcodec_close() failed (err=0x%x='%s')", err, utils::av_error_to_string(err)); - } - ctx->block_align = nbytes; ctx->ch_layout.nb_channels = nch_in; ctx->sample_rate = sampling_freq; diff --git a/rpcs3/util/media_utils.cpp b/rpcs3/util/media_utils.cpp index 73bc86ef46..b25415617e 100644 --- a/rpcs3/util/media_utils.cpp +++ b/rpcs3/util/media_utils.cpp @@ -347,9 +347,22 @@ namespace utils { if (!codec) return false; - for (const AVSampleFormat* p = codec->sample_fmts; p && *p != AV_SAMPLE_FMT_NONE; p++) + const void* sample_formats = nullptr; + int num = 0; + + if (const int err = avcodec_get_supported_config(nullptr, codec, AVCodecConfig::AV_CODEC_CONFIG_SAMPLE_FORMAT, 0, &sample_formats, &num)) { - if (*p == sample_fmt) + media_log.error("check_sample_fmt: avcodec_get_supported_config error: %d='%s'", err, av_error_to_string(err)); + return false; + } + + if (!sample_formats) + return true; // All supported + + int i = 0; + for (const AVSampleFormat* fmt = static_cast(sample_formats); fmt && *fmt != AV_SAMPLE_FMT_NONE && i < num; fmt++, i++) + { + if (*fmt == sample_fmt) { return true; } @@ -360,18 +373,33 @@ namespace utils // just pick the highest supported samplerate static int select_sample_rate(const AVCodec* codec) { - if (!codec || !codec->supported_samplerates) - return 48000; + constexpr int default_sample_rate = 48000; - int best_samplerate = 0; - for (const int* samplerate = codec->supported_samplerates; samplerate && *samplerate != 0; samplerate++) + if (!codec) + return default_sample_rate; + + const void* sample_rates = nullptr; + int num = 0; + + if (const int err = avcodec_get_supported_config(nullptr, codec, AVCodecConfig::AV_CODEC_CONFIG_SAMPLE_RATE, 0, &sample_rates, &num)) { - if (!best_samplerate || abs(48000 - *samplerate) < abs(48000 - best_samplerate)) + media_log.error("select_sample_rate: avcodec_get_supported_config error: %d='%s'", err, av_error_to_string(err)); + return default_sample_rate; + } + + if (!sample_rates) + return default_sample_rate; + + int i = 0; + int best_sample_rate = 0; + for (const int* sample_rate = static_cast(sample_rates); sample_rate && *sample_rate != 0 && i < num; sample_rate++, i++) + { + if (!best_sample_rate || abs(default_sample_rate - *sample_rate) < abs(default_sample_rate - best_sample_rate)) { - best_samplerate = *samplerate; + best_sample_rate = *sample_rate; } } - return best_samplerate; + return best_sample_rate; } AVChannelLayout get_preferred_channel_layout(int channels) @@ -397,12 +425,25 @@ namespace utils { if (!codec) return nullptr; + const void* ch_layouts = nullptr; + int num = 0; + + if (const int err = avcodec_get_supported_config(nullptr, codec, AVCodecConfig::AV_CODEC_CONFIG_CHANNEL_LAYOUT, 0, &ch_layouts, &num)) + { + media_log.error("select_channel_layout: avcodec_get_supported_config error: %d='%s'", err, av_error_to_string(err)); + return nullptr; + } + + if (!ch_layouts) + return nullptr; + const AVChannelLayout preferred_ch_layout = get_preferred_channel_layout(channels); const AVChannelLayout* found_ch_layout = nullptr; - for (const AVChannelLayout* ch_layout = codec->ch_layouts; - ch_layout && memcmp(ch_layout, &empty_ch_layout, sizeof(AVChannelLayout)) != 0; - ch_layout++) + int i = 0; + for (const AVChannelLayout* ch_layout = static_cast(ch_layouts); + i < num && ch_layout && memcmp(ch_layout, &empty_ch_layout, sizeof(AVChannelLayout)) != 0; + ch_layout++, i++) { media_log.notice("select_channel_layout: listing channel layout '%s' with %d channels", channel_layout_name(*ch_layout), ch_layout->nb_channels);