mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-11-05 13:20:11 +00:00
Ghost of Yotei (PPSA26344, v1.008, eboot 0x2e1cfc) creates an M4AAC instance (codec 2) and calls sceAjmBatchJobControl with flags 0x200000006000 (RESET | INITIALIZE | SIDEBAND_GAPLESS_DECODE), 8 bytes of gapless decode plus 8 bytes of M4AAC initialize parameters and an 8-byte result (#884); INITIALIZE for M4AAC threw on main. - INITIALIZE (control and sceAjmBatchJobInitialize) reads the 8-byte {config type (1 ADTS, 2 raw), sampling frequency index} block of shadPS4 ajm_aac.h at 443f0224; an invalid type or a raw index above 11 returns the invalid parameter result. Raw input is configured from the instance channels (0 is stereo) as in shadPS4 ajm_aac.cpp. - RUN decodes ADTS frames (length from the header) and raw access units (the whole input, as fdk-aac's raw transport) with FFmpeg's AAC decoder into the instance's S16, S32 or float PCM, with the framework's gapless, resampling, stream, format and multiple-frames sidebands. - Without ENABLE_NONDELAY_OUTPUT the first two frames after initialization or reset produce no output, as in shadPS4. A decoder error returns CODEC_ERROR | FATAL. The codec info is {heaac, reserved}; the format reports the last frame's bitrate with fdk-aac's formula. - Throws for what the sources do not settle: ADTS resynchronization, profiles other than AAC LC, several raw data blocks per frame, channel configurations other than 1, 2 and 6, more channels than the instance, HE-AAC without ENABLE_SBR_DECODE, raw input with RUN_MULTIPLE_FRAMES or several access units, a frame longer than the reserved room, and unknown codec flags. guest_ajm decodes an embedded 5-frame stereo ADTS fixture (two chirps, encoded by FFmpeg 6.1.1's aac encoder at 64 kbit/s) frame by frame, in one multiple-frames run, as float, as raw access units and with gapless trimming, and checks sample counts, format, codec info, the delay frames, RESET, partial input, missing room and the correlation of each channel with its input chirp at the 1024-sample encoder delay; plus the INITIALIZE validation results and the refusals. Co-Authored-By: Claude Fable 5.1 <[email protected]>
8.8 KiB
8.8 KiB
libSceAjm.native technical debt
Unknown function info
- sceAjmDecWVorbisCreateHeaderPacket, sceAjmDecWVorbisCreateSetupPacket (libSceAjmWVorbis, implemented in libSceAjm.native) - unknown signatures
- sceAjmBatchJobGetInfo (libSceAjm.native) - writes the result and format sideband of a run job without buffers with the
SIDEBAND_FORMATflag (0x400000000000), as KytyPS5 does, not confirmed on a PS5 title; the format reports bitrate 0 for ATRAC9 as in KytyPS5, while shadPS4 derives it from the superframe size; before the instance is initialized it returns the not-initialized result (1) and no format, like the other run jobs here, while KytyPS5 returns result 0 with the format of the uninitialized decoder - sceAjmDecMp3ParseFrame (libSceAjm.native) - signature, result layout and rate tables taken from the shadPS4 reimplementation of the PS4 library, not confirmed on a PS5 title: the layer field is not checked and MPEG-2.5 stops at 64 kbps; the original file length (
parse_ofl) layout (Xing/Info + LAME tag, VBRI, Fraunhofer0xB4block with its CRC, encoder delay = samples per frame + LAME delay + 529) also comes from shadPS4 only, and the Fraunhofer block has no other public description - sceAjmBatchJobGetCodecInfo, sceAjmBatchJobGetGaplessDecode (libSceAjm.native) - the
RUN_GET_CODEC_INFOflag (0x800), the ATRAC9 codec info layout and its next frame size are taken from the shadPS4 and RPCSX reimplementations, not confirmed on a PS5 title; a run job without buffers returns result 0, as in shadPS4. The gapless sideband reports the total and skip counts the title set and does not count them down: RPCSX does the same, shadPS4 counts them down and BryKytyPS5 returns its current counts - AJM Opus decoder (libSceAjm.native, codec 24) - the initialize parameter layout and little-endian
u16packet byte count come from The Smurfs Dreams (2, 48000, 0) and Lost Soul Aside (4, 48000, 1). The third word is interpreted as the mapping family, as in KytyPS5's initialize structure. Family 1 uses the conventional stream counts, coupled counts and channel map from libopus 1.5.2's surround layout, passed to FFmpeg through an RFC 7845 section 5.1 header with zero pre-skip and gain; gapless skipping remains controlled by AJM sideband parameters. FFmpeg returns PCM in its native speaker order. The implicit stream layout, PCM channel order and invalid family-0 channel count result are not verified on a console. NHL 27 (PPSA34063) passes1, 48000, 255. Family 255 with one channel is decoded as one mono stream, the same as family 0; this is assumed, since the stream count, coupled stream count and channel mapping that a family-255 Opus header carries (RFC 7845 section 5.1.1) are not passed. Only 48000 Hz, mapping families 0 and 1, and family 255 with one channel are implemented; other rates and families, and family 255 with more channels, throw - sceAjmBatchJobSetResampleParametersEx (libSceAjm.native) - the
(info, instance, float ratio_start, float ratio_change_per_sample, flags, result)signature is inferred from the name and fromsceAjmBatchJobSetResampleParameters; with a zero change per sample it sets the ratio assceAjmBatchJobSetResampleParametersdoes (Watch Dogs: Legion, PPSA01500, calls it so). How a non-zero change ramps the ratio is unknown and throws - sceAjmBatchJobControl (libSceAjm.native) - RESET (bit 13), INITIALIZE (bit 14) and the sideband input order (gapless decode, then initialize parameters) come from shadPS4 (PS4); other flags throw
- sceAjmBatchJobControl (libSceAjm.native) - RESET is assumed to clear the context as sceAjmBatchJobClearContext does
- sceAjmBatchJobControl (libSceAjm.native) - initialize parameters are 8 bytes for ATRAC9 and M4AAC, 12 for Opus and none for MP3, as one title passes them; other codecs and sizes, and an output other than the 8-byte result, throw
- sceAjmBatchJobControl (libSceAjm.native) - SIDEBAND_GAPLESS_DECODE with RESET overwrites both counts as in RPCSX; shadPS4 ignores a zero count when the other is nonzero. Without RESET they differ, so it throws
- sceAjmBatchJobSetResampleParameters, sceAjmBatchJobGetResampleInfo (libSceAjm) - the ratio is taken as decoded samples per output sample and num_samples as the decoded samples the resampler holds, both inferred from FMOD (Hades II); the console's interpolation is unknown, a 4-point Catmull-Rom is used. The flags argument is ignored, as in shadPS4 and Kyty
Functional
- sceAjmDecMp3ParseFrame (libSceAjm.native) throws when the original file length is requested (
parse_oflnon-zero) for a layer other than III, for a CRC-protected frame, or for a VBRI header outside MPEG-1 stereo: shadPS4 looks for the tag after the CRC and after the side information, while LAME and FFmpeg place it without the CRC and VBRI always at byte 36. - ATRAC9 gapless segments (libSceAjm.native) - a run job stops after the gapless total of output samples counted from the start of the segment, leaving the rest of its input unconsumed, and the next run starts the next segment with the decoder as it is and without a second skip. FMOD in PPSA29141 sets a total shorter than a sound's frames and reads the frames after it on later runs; with the output held at the total its stream reader waited for them forever and the last buffer repeated. The console's handling of the frames after the total is not documented; a reset (
SetGaplessDecodewith the reset flag,ClearContext, initialization) starts a new segment. An ATRAC9 run job withoutRUN_MULTIPLE_FRAMESdecodes its whole input as one with it: FMOD in PPSA29141 puts two run jobs in one batch with the second's input right after the whole of the first's. Whether the console stops after one frame there is not verified; MP3 and Opus run jobs still stop after one frame - AJM M4AAC decoder (libSceAjm.native, codec 2) - Ghost of Yotei (PPSA26344) initializes it through
sceAjmBatchJobControl. The initialize parameters (u32config type, 1 ADTS or 2 raw, thenu32sampling frequency index), instance flags (channels in bits 3-6,ENABLE_SBR_DECODEbit 32,ENABLE_NONDELAY_OUTPUTbit 33, surround interleave order bits 34-35),{heaac, reserved}codec info and decoder error result (CODEC_ERROR | FATAL) follow shadPS4 (PS4, fdk-aac) and are unverified on PS5; decoding uses FFmpeg's AAC decoder. WithoutENABLE_NONDELAY_OUTPUT, the first two frames after initialization or reset are consumed without output. Raw input takes its channel configuration from the instance (0 means stereo) and is decoded as one access unit per run job. The format reports the last frame's bitrate. Invalid config type or raw sampling frequency index above 11 returns invalid-parameter result 4. The implementation throws for ADTS without a frame header, profiles other than AAC LC, multiple raw data blocks per ADTS frame, unsupported channel configurations, more channels than the instance supports, HE-AAC withoutENABLE_SBR_DECODE, raw input withRUN_MULTIPLE_FRAMES, output room smaller than the previous frame length, and unknown codec flags. - AJM, APR and NGS2 state is allocated with
newand never freed on purpose: title threads still call into these libraries whilestd::exitruns static destructors, so ordinary statics would be destroyed under them. Keep them leaked;guest_ajm_teardowncovers the AJM case on Unix.