mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-11-04 13:07:32 +00:00
fix(audiodec): validate aac sizes and extended mode ranges
This commit is contained in:
1 parent
fdcf961f5c
commit
8de11f73ee
3 files changed
+50
-4
No files matched your search
@@ -1,6 +1,8 @@
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include "SceTypes.hpp"
|
||||
@@ -88,7 +90,7 @@ std::int32_t validateCtrl(const AudiodecCtrl* ctrl, std::uint32_t codecType) {
|
||||
if (infoSize != sizeof(AudiodecMp3Info)) return ERROR_INVALID_BSI_INFO_SIZE;
|
||||
break;
|
||||
default:
|
||||
if (paramSize < sizeof(AudiodecParamM4aac)) return ERROR_INVALID_PARAM_SIZE;
|
||||
if (paramSize != sizeof(AudiodecParamM4aac) && paramSize != 28 && paramSize != 32) return ERROR_INVALID_PARAM_SIZE;
|
||||
if (infoSize != sizeof(AudiodecM4aacInfo)) return ERROR_INVALID_BSI_INFO_SIZE;
|
||||
break;
|
||||
}
|
||||
@@ -133,12 +135,20 @@ void fillMp3Info(AudiodecMp3Info* info, const Audiodec::Mp3Header& header) {
|
||||
}
|
||||
|
||||
std::int32_t createAac(const AudiodecParamM4aac* param, AudiodecM4aacInfo* info, Instance& instance) {
|
||||
std::uint32_t extensionMode = 0;
|
||||
std::uint32_t outputMode = 0;
|
||||
const auto* bytes = reinterpret_cast<const std::byte*>(param);
|
||||
if (param->ui_size >= 28) std::memcpy(&extensionMode, bytes + 24, sizeof(extensionMode));
|
||||
if (extensionMode > 1) return static_cast<std::int32_t>(0x807F0305);
|
||||
if (param->ui_size == 32) std::memcpy(&outputMode, bytes + 28, sizeof(outputMode));
|
||||
if (outputMode > 2) return static_cast<std::int32_t>(0x807F0306);
|
||||
if (extensionMode != 0 || outputMode != 0) throw std::runtime_error("M4AAC extended decoding modes are not implemented");
|
||||
if (param->ui_config_number != M4AAC_CONFIG_ADTS && param->ui_config_number != M4AAC_CONFIG_RAW) return ERROR_M4AAC_INVALID_CONFIG_NUMBER;
|
||||
const std::uint32_t sampleRate = Audiodec::AacSampleRate(param->ui_sampling_freq_index);
|
||||
if (param->ui_config_number == M4AAC_CONFIG_RAW && sampleRate == 0) return ERROR_M4AAC_INVALID_SAMPLING_FREQ;
|
||||
if (param->ui_max_channels > 8) return ERROR_M4AAC_INVALID_MAX_CHANNELS;
|
||||
if (param->ui_enable_heaac > 1) return ERROR_M4AAC_INVALID_ENABLE_HEAAC;
|
||||
const std::uint32_t channels = param->ui_max_channels == 0 ? 2 : param->ui_max_channels;
|
||||
if (param->ui_max_channels != 1 && param->ui_max_channels != 2 && param->ui_max_channels != 6 && param->ui_max_channels != 8) return ERROR_M4AAC_INVALID_MAX_CHANNELS;
|
||||
if (param->ui_enable_heaac > 1 || (param->ui_enable_heaac == 1 && param->ui_max_channels > 2)) return ERROR_M4AAC_INVALID_ENABLE_HEAAC;
|
||||
const std::uint32_t channels = param->ui_max_channels;
|
||||
instance.decoder = Audiodec::CreateAac(param->i_bw_pcm, param->ui_config_number == M4AAC_CONFIG_ADTS, param->ui_sampling_freq_index, channels, param->ui_enable_heaac == 1);
|
||||
instance.channels = channels;
|
||||
instance.sampleRate = sampleRate;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <numbers>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
extern "C" {
|
||||
@@ -410,6 +411,39 @@ int main() {
|
||||
aac.i_bw_pcm = 2;
|
||||
const std::int32_t floatAac = sceAudiodecCreateDecoder(&aacCtrl, 3);
|
||||
Require(floatAac > 0 && sceAudiodecDeleteDecoder(floatAac) == 0);
|
||||
for (const std::uint32_t channels : {0u, 3u, 4u, 5u, 7u, 9u}) {
|
||||
aac.ui_max_channels = channels;
|
||||
Require(sceAudiodecCreateDecoder(&aacCtrl, 3) == static_cast<std::int32_t>(0x807F0304));
|
||||
}
|
||||
aac.ui_max_channels = 6;
|
||||
aac.ui_enable_heaac = 1;
|
||||
Require(sceAudiodecCreateDecoder(&aacCtrl, 3) == static_cast<std::int32_t>(0x807F0302));
|
||||
struct ExtendedParam {
|
||||
AudiodecParamM4aac base;
|
||||
std::uint32_t extensionMode;
|
||||
std::uint32_t outputMode;
|
||||
} extended{{32, 1, 1, 3, 2, 0}, 0, 0};
|
||||
aacCtrl.pParam = &extended;
|
||||
for (const std::uint32_t size : {25u, 27u, 29u, 31u, 33u}) {
|
||||
extended.base.ui_size = size;
|
||||
Require(sceAudiodecCreateDecoder(&aacCtrl, 3) == errorInvalidParamSize);
|
||||
}
|
||||
for (const std::uint32_t size : {28u, 32u}) {
|
||||
extended.base.ui_size = size;
|
||||
extended.extensionMode = 2;
|
||||
Require(sceAudiodecCreateDecoder(&aacCtrl, 3) == static_cast<std::int32_t>(0x807F0305));
|
||||
extended.extensionMode = 1;
|
||||
bool threw = false;
|
||||
try { sceAudiodecCreateDecoder(&aacCtrl, 3); }
|
||||
catch (const std::runtime_error&) { threw = true; }
|
||||
Require(threw);
|
||||
extended.extensionMode = 0;
|
||||
const auto extendedHandle = sceAudiodecCreateDecoder(&aacCtrl, 3);
|
||||
Require(extendedHandle > 0);
|
||||
Require(sceAudiodecDeleteDecoder(extendedHandle) == 0);
|
||||
}
|
||||
extended.outputMode = 3;
|
||||
Require(sceAudiodecCreateDecoder(&aacCtrl, 3) == static_cast<std::int32_t>(0x807F0306));
|
||||
|
||||
const std::int32_t handle = sceAudiodecCreateDecoder(&ctrl, 2);
|
||||
Require(handle > 0);
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
### Unknown function info
|
||||
|
||||
- [M4AAC extended parameters](../../../core/libs/prx/libSceAudiodec/Export.cpp): 28-byte and 32-byte parameter variants add fields at offsets 24 and 28. Their accepted ranges are 0..1 and 0..2; nonzero modes throw until the corresponding decoder configuration is implemented. Zero extensions use the base decoding configuration.
|
||||
|
||||
- [sceAudiodecDecode](../../../core/libs/prx/libSceAudiodec/src/Codecs.cpp) (libSceAudiodec) - a raw M4AAC stream carries no channel configuration, so the decoder tries the mono/stereo configuration and then configurations 3 to 7 within `ui_max_channels` until one decodes the first access unit, and keeps that one. No reference documents how the library picks the layout (shadPS4 maps the channel count straight to the configuration; SharpProspero only describes the maximum). With the stereo configuration a mono raw stream decodes as 2 channels, so 2 is reported, not 1
|
||||
- [sceAudiodecDecode](../../../core/libs/prx/libSceAudiodec/src/Codecs.cpp) (libSceAudiodec) - the HE-AAC handling follows one console measurement of an HE-AAC v2 ADTS stream: SBR output at 48 kHz in one channel with `ui_enable_heaac` 1, the 24 kHz mono core with 0. Not measured: whether the console, like FFmpeg, decodes a stream without SBR data in its first access unit as AAC-LC with `ui_enable_heaac` 1, and what it reports in `ui_sampling_freq` and `ui_heaac` with `ui_enable_heaac` 0 (here the rate of the returned PCM and 0)
|
||||
|
||||
|
||||
Reference in new issue
Block a user