1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-22 02:32:36 +01:00

cellAdec implementation part 1: abstraction layer

This commit is contained in:
capriots 2024-11-02 19:38:38 +01:00
parent 4838649c6f
commit 3b13c22a1f
No known key found for this signature in database
4 changed files with 1220 additions and 946 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
#pragma once
#include "Emu/Memory/vm_ptr.h"
#include "cellPamf.h" // CellCodecTimeStamp
// Error Codes
enum CellAdecError : u32
@ -222,14 +222,6 @@ enum AudioCodecType : s32
CELL_ADEC_TYPE_ATRAC3MULTI,
};
inline bool adecIsAtracX(s32 type)
{
return type == CELL_ADEC_TYPE_ATRACX
|| type == CELL_ADEC_TYPE_ATRACX_2CH
|| type == CELL_ADEC_TYPE_ATRACX_6CH
|| type == CELL_ADEC_TYPE_ATRACX_8CH;
}
// Output Channel Number
enum CellAdecChannel : s32
{
@ -295,14 +287,14 @@ struct CellAdecResourceEx
be_t<u32> ppuThreadPriority;
be_t<u32> ppuThreadStackSize;
be_t<u32> spurs_addr;
u8 priority[8];
be_t<u64, 1> priority;
be_t<u32> maxContention;
};
struct CellAdecResourceSpurs
{
be_t<u32> spurs_addr; // CellSpurs*
u8 priority[8];
be_t<u64, 1> priority;
be_t<u32> maxContention;
};
@ -315,7 +307,7 @@ enum CellAdecMsgType : s32
CELL_ADEC_MSG_TYPE_SEQDONE,
};
using CellAdecCbMsg = s32(u32 handle, CellAdecMsgType msgType, s32 msgData, u32 cbArg);
using CellAdecCbMsg = s32(vm::ptr<void> handle, CellAdecMsgType msgType, s32 msgData, vm::ptr<void> cbArg);
// Used for internal callbacks as well
template <typename F>
@ -339,14 +331,14 @@ struct CellAdecAuInfo
// BSI Info
struct CellAdecPcmAttr
{
be_t<u32> bsiInfo_addr;
vm::bptr<void> bsiInfo;
};
struct CellAdecPcmItem
{
be_t<u32> pcmHandle;
be_t<s32> pcmHandle;
be_t<u32> status;
be_t<u32> startAddr;
vm::bcptr<void> startAddr;
be_t<u32> size;
CellAdecPcmAttr pcmAttr;
CellAdecAuInfo auInfo;
@ -363,36 +355,31 @@ enum AdecCorrectPtsValueType : s8
ADEC_CORRECT_PTS_VALUE_TYPE_ATRACX_48000Hz = 2,
ADEC_CORRECT_PTS_VALUE_TYPE_ATRACX_44100Hz = 3,
ADEC_CORRECT_PTS_VALUE_TYPE_ATRACX_32000Hz = 4,
// 5: Dolby Digital
// 6: ATRAC3
// 7: MP3
// 8: MP3
// 9: MP3
// 39: ATRAC3 multi-track
ADEC_CORRECT_PTS_VALUE_TYPE_AC3 = 5,
ADEC_CORRECT_PTS_VALUE_TYPE_ATRAC3 = 6,
ADEC_CORRECT_PTS_VALUE_TYPE_MP3_48000Hz = 7,
ADEC_CORRECT_PTS_VALUE_TYPE_MP3_44100Hz = 8,
ADEC_CORRECT_PTS_VALUE_TYPE_MP3_32000Hz = 9,
ADEC_CORRECT_PTS_VALUE_TYPE_ATRAC3MULTI = 39,
// Calls a decoder function (_SceAdecCorrectPtsValue_codec())
// 17: Dolby Digital Plus
// 18
// 19
// 20
// 21: DTS HD
// 22
// 23
// 24: CELP
// 25: MPEG-2 AAC
// 26: MPEG-2 BC
// 27: Dolby TrueHD
// 28: DTS
// 29: MPEG-4 AAC
// 30: Windows Media Audio
// 31: DTS Express
// 32: MP1
// 33: MP3 Surround
// 34: CELP8
// 35: Windows Media Audio Professional
// 36: Windows Media Audio Lossless
// 37: DTS HD Core
// 38: DTS HD Core
ADEC_CORRECT_PTS_VALUE_TYPE_EAC3 = 17,
ADEC_CORRECT_PTS_VALUE_TYPE_DTSHD = 21,
ADEC_CORRECT_PTS_VALUE_TYPE_CELP = 24,
ADEC_CORRECT_PTS_VALUE_TYPE_M2AAC = 25,
ADEC_CORRECT_PTS_VALUE_TYPE_MPEG_L2 = 26,
ADEC_CORRECT_PTS_VALUE_TYPE_TRUEHD = 27,
ADEC_CORRECT_PTS_VALUE_TYPE_DTS = 28,
ADEC_CORRECT_PTS_VALUE_TYPE_M4AAC = 29,
ADEC_CORRECT_PTS_VALUE_TYPE_WMA = 30,
ADEC_CORRECT_PTS_VALUE_TYPE_DTSLBR = 31,
ADEC_CORRECT_PTS_VALUE_TYPE_MPEG_L1 = 32,
ADEC_CORRECT_PTS_VALUE_TYPE_MP3S = 33,
ADEC_CORRECT_PTS_VALUE_TYPE_CELP8 = 34,
ADEC_CORRECT_PTS_VALUE_TYPE_WMAPRO = 35,
ADEC_CORRECT_PTS_VALUE_TYPE_WMALSL = 36,
ADEC_CORRECT_PTS_VALUE_TYPE_DTSHDCORE_UNK1 = 37,
ADEC_CORRECT_PTS_VALUE_TYPE_DTSHDCORE_UNK2 = 38,
};
// Internal callbacks
@ -471,6 +458,175 @@ struct AdecCmdQueue
bool full() const { return size >= 4; }
};
struct AdecFrame
{
b8 in_use = false; // True after issuing a decode command until the frame is consumed
const be_t<s32> this_index; // Set when initialized in cellAdecOpen(), unused afterward
// Set when the corresponding callback is received, unused afterward
b8 au_done = false;
const b8 unk1 = false;
b8 pcm_out = false;
const b8 unk2 = false;
CellAdecAuInfo au_info;
CellAdecPcmItem pcm_item;
const u32 reserved1 = 0;
const u32 reserved2 = 0;
// Frames that are ready to be consumed form a linked list. However, this list is not used (AdecOutputQueue is used instead)
be_t<s32> next = 0; // Index of the next frame that can be consumed
be_t<s32> prev = 0; // Index of the previous frame that can be consumed
AdecFrame(s32 index, u32 bitstream_info_addr)
: this_index(index)
{
pcm_item.pcmAttr.bsiInfo.set(bitstream_info_addr);
}
};
CHECK_SIZE(AdecFrame, 0x68);
class AdecOutputQueue
{
struct entry
{
const be_t<s32> this_index; // Unused
be_t<s32> state = 0xff; // 0xff = empty, 0x10 = filled
vm::bptr<CellAdecPcmItem> pcm_item = vm::null;
be_t<s32> pcm_handle = -1;
}
entries[4];
be_t<s32> front = 0;
be_t<s32> back = 0;
be_t<s32> size = 0;
shared_mutex mutex; // sys_mutex_t
be_t<u32> cond{}; // sys_cond_t, unused
public:
AdecOutputQueue() : entries{ {0}, {1}, {2}, {3} } {}
error_code push(vm::ptr<CellAdecPcmItem> pcm_item, s32 pcm_handle)
{
std::lock_guard lock{mutex};
if (entries[back].state != 0xff)
{
return true; // LLE returns the result of the comparison above
}
entries[back].state = 0x10;
entries[back].pcm_item = pcm_item;
entries[back].pcm_handle = pcm_handle;
back = (back + 1) & 3;
size++;
return CELL_OK;
}
const entry* pop()
{
std::lock_guard lock{mutex};
if (entries[front].state == 0xff)
{
return nullptr;
}
const entry* const ret = &entries[front];
entries[front].state = 0xff;
entries[front].pcm_handle = -1;
front = (front + 1) & 3;
size--;
return ret;
}
const entry& peek()
{
std::lock_guard lock{mutex};
return entries[front];
}
};
CHECK_SIZE(AdecOutputQueue, 0x54);
enum class AdecSequenceState : u32
{
dormant = 0x100,
ready = 0x200,
closed = 0xa00,
};
struct AdecContext // CellAdecHandle = AdecContext*
{
vm::bptr<AdecContext> _this;
const be_t<u32> this_size; // Size of this struct + AdecFrames + bitstream info structs
const u32 unk = 0; // Unused
be_t<AdecSequenceState> sequence_state = AdecSequenceState::dormant;
const CellAdecType type;
const CellAdecResource res;
const CellAdecCb callback;
const vm::bptr<void> core_handle;
const vm::bcptr<CellAdecCoreOps> core_ops;
CellCodecTimeStamp previous_pts{ CODEC_TS_INVALID, CODEC_TS_INVALID };
const be_t<s32> frames_num;
const u32 reserved1 = 0;
be_t<s32> frames_head = -1; // Index of the oldest frame that can be consumed
be_t<s32> frames_tail = -1; // Index of the most recent frame that can be consumed
const vm::bptr<AdecFrame> frames; // Array of AdecFrames, number of elements is return value of CellAdecCoreOps::getPcmHandleNum
const be_t<u32> bitstream_info_size;
u64 mutex_attribute[5]{}; // sys_mutex_attribute_t
shared_mutex mutex; // sys_mutex_t
AdecOutputQueue pcm_queue; // Output queue for cellAdecGetPcm()
AdecOutputQueue pcm_item_queue; // Output queue for cellAdecGetPcmItem()
u8 reserved2[1028];
AdecContext(vm::bptr<AdecContext> _this, u32 this_size, const CellAdecType& type, const CellAdecResource& res, const CellAdecCb& callback, vm::bptr<void> core_handle, vm::bcptr<CellAdecCoreOps> core_ops,
s32 frames_num, vm::bptr<AdecFrame> frames, u32 bitstream_info_size, u32 bitstream_infos_addr)
: _this(_this), this_size(this_size), type(type), res(res), callback(callback), core_handle(core_handle), core_ops(core_ops), frames_num(frames_num), frames(frames), bitstream_info_size(bitstream_info_size)
{
ensure(this == _this.get_ptr());
for (s32 i = 0; i < frames_num; i++)
{
new (&frames[i]) AdecFrame(i, bitstream_infos_addr + bitstream_info_size * i);
}
}
[[nodiscard]] error_code get_new_pcm_handle(vm::ptr<CellAdecAuInfo> au_info) const;
error_code verify_pcm_handle(s32 pcm_handle) const;
vm::ptr<CellAdecAuInfo> get_au_info(s32 pcm_handle) const;
void set_state(s32 pcm_handle, u32 state) const;
error_code get_pcm_item(s32 pcm_handle, vm::ptr<CellAdecPcmItem>& pcm_item) const;
error_code set_pcm_item(s32 pcm_handle, vm::ptr<void> pcm_addr, u32 pcm_size, vm::cpptr<void> bitstream_info) const;
error_code link_frame(s32 pcm_handle);
error_code unlink_frame(s32 pcm_handle);
void reset_frame(s32 pcm_handle) const;
error_code correct_pts_value(ppu_thread& ppu, s32 pcm_handle, s8 correct_pts_type);
};
static_assert(std::is_standard_layout_v<AdecContext>);
CHECK_SIZE_ALIGN(AdecContext, 0x530, 8);
struct CellAdecParamLpcm
{
be_t<u32> channelNumber;
@ -1024,106 +1180,3 @@ struct CellAdecMpmcInfo
be_t<u32> lfePresent;
be_t<u32> channelCoufiguration;
};
/* Audio Decoder Thread Classes */
enum AdecJobType : u32
{
adecStartSeq,
adecEndSeq,
adecDecodeAu,
adecClose,
};
struct AdecTask
{
AdecJobType type;
union
{
struct
{
u32 auInfo_addr;
u32 addr;
u32 size;
u64 pts;
u64 userdata;
} au;
struct
{
s32 sample_rate;
s32 channel_config;
s32 channels;
s32 frame_size;
std::array<u8, 4> extra_config;
s32 output;
u8 downmix;
u8 ats_header;
} at3p;
};
AdecTask(AdecJobType type)
: type(type)
{
}
AdecTask()
{
}
};
struct AdecFrame
{
struct AVFrame* data;
u64 pts;
u64 userdata;
u32 auAddr;
u32 auSize;
u32 size;
};
int adecRead(void* opaque, u8* buf, int buf_size);
static const u32 at3freq[8] = { 32000, 44100, 48000, 88200, 96000, 0, 0, 0 };
struct OMAHeader // OMA Header
{
u32 magic; // 0x01334145
u16 size; // 96 << 8
u16 unk0; // 0xffff
u64 unk1; // 0x00500f0100000000ULL
u64 unk2; // 0xcef5000000000400ULL
u64 unk3; // 0x1c458024329192d2ULL
u8 codecId; // 1 for ATRAC3P
u8 code0; // 0
u8 code1;
u8 code2;
u32 reserved[15]; // 0
OMAHeader(u8 codec_id, u32 freq, u8 channel_count, u32 frame_size)
: magic(0x01334145)
, size(96 << 8)
, unk0(0xffff)
, unk1(0x00500f0100000000ULL)
, unk2(0xcef5000000000400ULL)
, unk3(0x1c458024329192d2ULL)
, codecId(codec_id)
, code0(0)
{
memset(reserved, 0, sizeof(reserved));
u8 freq_code;
for (freq_code = 0; freq_code < 5; freq_code++)
{
if (at3freq[freq_code] == freq)
{
break;
}
}
u32 prepared_frame_size = (frame_size - 8) / 8;
code1 = ((prepared_frame_size >> 8) & 0x3) | ((channel_count & 0x7) << 2) | (freq_code << 5);
code2 = prepared_frame_size & 0xff;
}
};
CHECK_SIZE(OMAHeader, 96);

View File

@ -182,6 +182,8 @@ static void ppu_initialize_modules(ppu_linkage_info* link, utils::serial* ar = n
{
&ppu_module_manager::cellAdec,
&ppu_module_manager::cellAtrac,
&ppu_module_manager::cellAtrac3dec,
&ppu_module_manager::cellAtrac3multidec,
&ppu_module_manager::cellAtracMulti,
&ppu_module_manager::cellAtracXdec,
&ppu_module_manager::cellAudio,
@ -189,12 +191,19 @@ static void ppu_initialize_modules(ppu_linkage_info* link, utils::serial* ar = n
&ppu_module_manager::cellAuthDialogUtility,
&ppu_module_manager::cellBGDL,
&ppu_module_manager::cellCamera,
&ppu_module_manager::cellCelp8Dec,
&ppu_module_manager::cellCelp8Enc,
&ppu_module_manager::cellCelpDec,
&ppu_module_manager::cellCelpEnc,
&ppu_module_manager::cellCrossController,
&ppu_module_manager::cellDaisy,
&ppu_module_manager::cellDDPdec,
&ppu_module_manager::cellDmux,
&ppu_module_manager::cellDtcpIpUtility,
&ppu_module_manager::cellDTSdec,
&ppu_module_manager::cellDTSHDCOREdec,
&ppu_module_manager::cellDTSHDdec,
&ppu_module_manager::cellDTSLBRdec,
&ppu_module_manager::cellFiber,
&ppu_module_manager::cellFont,
&ppu_module_manager::cellFontFT,
@ -213,8 +222,16 @@ static void ppu_initialize_modules(ppu_linkage_info* link, utils::serial* ar = n
&ppu_module_manager::cellJpgEnc,
&ppu_module_manager::cellKey2char,
&ppu_module_manager::cellL10n,
&ppu_module_manager::cell_libac3dec,
&ppu_module_manager::cellLibprof,
&ppu_module_manager::cellM2AACdec,
&ppu_module_manager::cellM2BCdec,
&ppu_module_manager::cellM4AacDec,
&ppu_module_manager::cellM4AacDec2ch,
&ppu_module_manager::cellM4AacDec2chmod,
&ppu_module_manager::cellMic,
&ppu_module_manager::cellMP3dec,
&ppu_module_manager::cellMP3Sdec,
&ppu_module_manager::cellMusic,
&ppu_module_manager::cellMusicDecode,
&ppu_module_manager::cellMusicExport,
@ -258,6 +275,7 @@ static void ppu_initialize_modules(ppu_linkage_info* link, utils::serial* ar = n
&ppu_module_manager::cellSysutilAvcExt,
&ppu_module_manager::cellSysutilNpEula,
&ppu_module_manager::cellSysutilMisc,
&ppu_module_manager::cellTRHDdec,
&ppu_module_manager::cellUsbd,
&ppu_module_manager::cellUsbPspcm,
&ppu_module_manager::cellUserInfo,
@ -267,6 +285,9 @@ static void ppu_initialize_modules(ppu_linkage_info* link, utils::serial* ar = n
&ppu_module_manager::cellVideoUpload,
&ppu_module_manager::cellVoice,
&ppu_module_manager::cellVpost,
&ppu_module_manager::cellWMAdec,
&ppu_module_manager::cellWMALSLdec,
&ppu_module_manager::cellWMAPROdec,
&ppu_module_manager::libad_async,
&ppu_module_manager::libad_core,
&ppu_module_manager::libfs_utility_init,

View File

@ -167,6 +167,8 @@ public:
static const ppu_static_module cellAdec;
static const ppu_static_module cellAtrac;
static const ppu_static_module cellAtrac3dec;
static const ppu_static_module cellAtrac3multidec;
static const ppu_static_module cellAtracMulti;
static const ppu_static_module cellAtracXdec;
static const ppu_static_module cellAudio;
@ -174,12 +176,19 @@ public:
static const ppu_static_module cellAuthDialogUtility;
static const ppu_static_module cellBGDL;
static const ppu_static_module cellCamera;
static const ppu_static_module cellCelp8Dec;
static const ppu_static_module cellCelp8Enc;
static const ppu_static_module cellCelpDec;
static const ppu_static_module cellCelpEnc;
static const ppu_static_module cellCrossController;
static const ppu_static_module cellDaisy;
static const ppu_static_module cellDDPdec;
static const ppu_static_module cellDmux;
static const ppu_static_module cellDtcpIpUtility;
static const ppu_static_module cellDTSdec;
static const ppu_static_module cellDTSHDCOREdec;
static const ppu_static_module cellDTSHDdec;
static const ppu_static_module cellDTSLBRdec;
static const ppu_static_module cellFiber;
static const ppu_static_module cellFont;
static const ppu_static_module cellFontFT;
@ -198,8 +207,17 @@ public:
static const ppu_static_module cellJpgEnc;
static const ppu_static_module cellKey2char;
static const ppu_static_module cellL10n;
static const ppu_static_module cell_libac3dec;
static const ppu_static_module cellLibprof;
static const ppu_static_module cellM2AACdec;
static const ppu_static_module cellM2BCdec;
static const ppu_static_module cellM4AacDec;
static const ppu_static_module cellM4AacDec2ch;
static const ppu_static_module cellM4AacDec2chmod;
static const ppu_static_module cellMic;
static const ppu_static_module cellMP3dec;
static const ppu_static_module cellMP3Sdec;
static const ppu_static_module cellMPL1dec;
static const ppu_static_module cellMusic;
static const ppu_static_module cellMusicDecode;
static const ppu_static_module cellMusicExport;
@ -243,6 +261,7 @@ public:
static const ppu_static_module cellSysutilAvcExt;
static const ppu_static_module cellSysutilNpEula;
static const ppu_static_module cellSysutilMisc;
static const ppu_static_module cellTRHDdec;
static const ppu_static_module cellUsbd;
static const ppu_static_module cellUsbPspcm;
static const ppu_static_module cellUserInfo;
@ -252,6 +271,9 @@ public:
static const ppu_static_module cellVideoUpload;
static const ppu_static_module cellVoice;
static const ppu_static_module cellVpost;
static const ppu_static_module cellWMAdec;
static const ppu_static_module cellWMALSLdec;
static const ppu_static_module cellWMAPROdec;
static const ppu_static_module libad_async;
static const ppu_static_module libad_core;
static const ppu_static_module libfs_utility_init;