diff --git a/core/libs/prx/libSceAudiodec/src/Codecs.cpp b/core/libs/prx/libSceAudiodec/src/Codecs.cpp index dfa428f9d..aca46d88d 100644 --- a/core/libs/prx/libSceAudiodec/src/Codecs.cpp +++ b/core/libs/prx/libSceAudiodec/src/Codecs.cpp @@ -82,6 +82,12 @@ protected: return result; } + void reopen(std::vector replacement) { + avcodec_free_context(&context); + extradata = std::move(replacement); + open(); + } + private: void open() { const AVCodec* codec = avcodec_find_decoder(id); @@ -118,7 +124,8 @@ public: class AacDecoder final : public FfmpegDecoder { public: - AacDecoder(std::int32_t wordSize, bool adts, std::vector extradata) : FfmpegDecoder(AV_CODEC_ID_AAC, wordSize, std::move(extradata)), adts(adts) {} + AacDecoder(std::int32_t wordSize, bool adts, std::vector> configs) + : FfmpegDecoder(AV_CODEC_ID_AAC, wordSize, configs.empty() ? std::vector{} : configs.front()), adts(adts), configs(std::move(configs)) {} DecodeResult Decode(const std::uint8_t* data, std::size_t size, std::uint8_t* pcm, std::size_t pcmSize) override { std::size_t frameBytes = size; @@ -128,11 +135,22 @@ public: if (frameBytes < 7) return {DecodeStatus::InvalidData}; if (frameBytes > size) return {DecodeStatus::PartialInput}; } - return decodePacket(data, frameBytes, pcm, pcmSize); + if (configs.size() <= 1) return decodePacket(data, frameBytes, pcm, pcmSize); + for (std::size_t index = 0; index < configs.size(); ++index) { + if (index != 0) reopen(configs[index]); + const DecodeResult result = decodePacket(data, frameBytes, pcm, pcmSize); + if (result.status != DecodeStatus::InvalidData) { + configs = {configs[index]}; + return result; + } + } + reopen(configs.front()); + return {DecodeStatus::InvalidData}; } private: bool adts; + std::vector> configs; }; class At9Decoder final : public Decoder { @@ -222,13 +240,19 @@ std::unique_ptr CreateMp3(std::int32_t wordSize) { } std::unique_ptr CreateAac(std::int32_t wordSize, bool adts, std::uint32_t samplingFreqIndex, std::uint32_t channels) { - std::vector config; + std::vector> configs; if (!adts) { const std::uint32_t lowComplexity = 2; - config = {static_cast(lowComplexity << 3 | samplingFreqIndex >> 1), - static_cast((samplingFreqIndex & 1) << 7 | channels << 3)}; + const auto config = [&](std::uint32_t channelConfiguration) { + return std::vector{static_cast(lowComplexity << 3 | samplingFreqIndex >> 1), + static_cast((samplingFreqIndex & 1) << 7 | channelConfiguration << 3)}; + }; + configs.push_back(config(channels < 2 ? 1 : 2)); + for (std::uint32_t channelConfiguration = 3; channelConfiguration <= 7; ++channelConfiguration) { + if ((channelConfiguration == 7 ? 8 : channelConfiguration) <= channels) configs.push_back(config(channelConfiguration)); + } } - return std::make_unique(wordSize, adts, std::move(config)); + return std::make_unique(wordSize, adts, std::move(configs)); } std::unique_ptr CreateAt9(std::int32_t wordSize, const std::uint8_t (&config)[4], At9Format& format) { diff --git a/core/libs/tests/GuestAudiodec.cpp b/core/libs/tests/GuestAudiodec.cpp index fb9a4b3e5..414b6d3e9 100644 --- a/core/libs/tests/GuestAudiodec.cpp +++ b/core/libs/tests/GuestAudiodec.cpp @@ -115,12 +115,12 @@ std::size_t AdtsLength(const std::uint8_t* frame) { return static_cast((frame[3] & 3) << 11 | frame[4] << 3 | frame[5] >> 5); } -void TestAac(bool adts) { - AudiodecParamM4aac param{sizeof(param), 1, adts ? 1u : 2u, 3, 2, 0}; +void TestAac(bool adts, std::uint32_t maxChannels = 2) { + AudiodecParamM4aac param{sizeof(param), 1, adts ? 1u : 2u, 3, maxChannels, 0}; AudiodecM4aacInfo info{sizeof(info), 0, 0, 0, 0}; AudiodecCtrl ctrl{¶m, &info, nullptr, nullptr}; const std::int32_t handle = sceAudiodecCreateDecoder(&ctrl, 3); - Require(handle > 0 && info.ui_sampling_freq == 48000 && info.ui_number_of_channels == 2); + Require(handle > 0 && info.ui_sampling_freq == 48000 && info.ui_number_of_channels == maxChannels); Streams streams; int crossings = 0; for (std::size_t offset = 0, frame = 0; offset < sizeof(AAC_ADTS); offset += AdtsLength(AAC_ADTS + offset), ++frame) { @@ -229,6 +229,8 @@ int main() { TestAac(true); TestAac(false); + TestAac(false, 6); + TestAac(false, 8); TestMp3(); TestAt9(); for (std::uint32_t type = 1; type <= 3; ++type) Require(sceAudiodecTermLibrary(type) == 0);