From 982f7cba5965b8fb2dc592d81ea2e43c27189402 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 13 Dec 2014 19:54:01 +0300 Subject: [PATCH] cellPamfReaderGetStreamInfo() improved --- rpcs3/Emu/SysCalls/Modules/cellPamf.cpp | 322 +++++++++++++++++------- rpcs3/Emu/SysCalls/Modules/cellPamf.h | 173 ++++++++----- 2 files changed, 332 insertions(+), 163 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp b/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp index 4be694dac8..f768cd7001 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp @@ -107,9 +107,10 @@ s32 pamfStreamTypeToEsFilterId(u8 type, u8 ch, CellCodecEsFilterId& pEsFilterId) return CELL_OK; } -u8 pamfGetStreamType(vm::ptr pSelf, u8 stream) +u8 pamfGetStreamType(vm::ptr pSelf, u32 stream) { // TODO: get stream type correctly + assert(stream < (u32)pSelf->pAddr->stream_count); auto& header = pSelf->pAddr->stream_headers[stream]; switch (header.type) @@ -127,9 +128,10 @@ u8 pamfGetStreamType(vm::ptr pSelf, u8 stream) return 0xff; } -u8 pamfGetStreamChannel(vm::ptr pSelf, u8 stream) +u8 pamfGetStreamChannel(vm::ptr pSelf, u32 stream) { // TODO: get stream channel correctly + assert(stream < (u32)pSelf->pAddr->stream_count); auto& header = pSelf->pAddr->stream_headers[stream]; switch (header.type) @@ -446,6 +448,7 @@ s32 cellPamfReaderGetEsFilterId(vm::ptr pSelf, vm::ptrstream < (u32)pSelf->pAddr->stream_count); auto& header = pSelf->pAddr->stream_headers[pSelf->stream]; pEsFilterId->filterIdMajor = header.fid_major; pEsFilterId->filterIdMinor = header.fid_minor; @@ -458,103 +461,232 @@ s32 cellPamfReaderGetStreamInfo(vm::ptr pSelf, u32 pInfo_addr, u { cellPamf->Warning("cellPamfReaderGetStreamInfo(pSelf=0x%x, stream=%d, pInfo_addr=0x%x, size=%d)", pSelf.addr(), pSelf->stream, pInfo_addr, size); - // TODO (many parameters are wrong) - memset(vm::get_ptr(pInfo_addr), 0, size); + assert((u32)pSelf->stream < (u32)pSelf->pAddr->stream_count); + auto& header = pSelf->pAddr->stream_headers[pSelf->stream]; + const u8 type = pamfGetStreamType(pSelf, pSelf->stream); + const u8 ch = pamfGetStreamChannel(pSelf, pSelf->stream); - switch (pamfGetStreamType(pSelf, pSelf->stream)) + switch (type) { case CELL_PAMF_STREAM_TYPE_AVC: + { + if (size < sizeof(CellPamfAvcInfo)) { - auto pInfo = vm::ptr::make(pInfo_addr); - auto pAVC = vm::ptr::make(pSelf->pAddr.addr() + 0x98 + pSelf->stream * 0x30); - - if (size != sizeof(CellPamfAvcInfo)) - { - cellPamf->Error("cellPamfReaderGetStreamInfo: wrong AVC data size(%d)", size); - return CELL_PAMF_ERROR_INVALID_ARG; - } - - pInfo->profileIdc = pAVC->profileIdc; - pInfo->levelIdc = pAVC->levelIdc; - - pInfo->frameMbsOnlyFlag = 1; //fake - pInfo->frameRateInfo = (pAVC->unk0 & 0x7) - 1; - pInfo->aspectRatioIdc = 1; //fake - - pInfo->horizontalSize = 16 * (u16)pAVC->horizontalSize; - pInfo->verticalSize = 16 * (u16)pAVC->verticalSize; - - pInfo->videoSignalInfoFlag = 1; //fake - pInfo->colourPrimaries = 1; //fake - pInfo->transferCharacteristics = 1; //fake - pInfo->matrixCoefficients = 1; //fake - //pInfo->deblockingFilterFlag = 1; //??? - - cellPamf->Warning("cellPamfReaderGetStreamInfo: CELL_PAMF_STREAM_TYPE_AVC"); - } - break; - case CELL_PAMF_STREAM_TYPE_M2V: - { - //TODO - cellPamf->Error("TODO: cellPamfReaderGetStreamInfo: CELL_PAMF_STREAM_TYPE_M2V"); - } - break; - case CELL_PAMF_STREAM_TYPE_ATRAC3PLUS: - { - auto pInfo = vm::ptr::make(pInfo_addr); - auto pAudio = vm::ptr::make(pSelf->pAddr.addr() + 0x98 + pSelf->stream * 0x30); - - if (size != sizeof(CellPamfAtrac3plusInfo)) - { - cellPamf->Error("cellPamfReaderGetStreamInfo: wrong ATRAC3+ data size(%d)", size); - return CELL_PAMF_ERROR_INVALID_ARG; - } - - pInfo->numberOfChannels = pAudio->channels; - pInfo->samplingFrequency = CELL_PAMF_FS_48kHz; - } - break; - case CELL_PAMF_STREAM_TYPE_AC3: - { - auto pInfo = vm::ptr::make(pInfo_addr); - auto pAudio = vm::ptr::make(pSelf->pAddr.addr() + 0x98 + pSelf->stream * 0x30); - - if (size != sizeof(CellPamfAc3Info)) - { - cellPamf->Error("cellPamfReaderGetStreamInfo: wrong AC3 data size(%d)", size); - return CELL_PAMF_ERROR_INVALID_ARG; - } - - pInfo->numberOfChannels = pAudio->channels; - pInfo->samplingFrequency = CELL_PAMF_FS_48kHz; - } - break; - case CELL_PAMF_STREAM_TYPE_PAMF_LPCM: - { - auto pInfo = vm::ptr::make(pInfo_addr); - auto pAudio = vm::ptr::make(pSelf->pAddr.addr() + 0x98 + pSelf->stream * 0x30); - - if (size != sizeof(CellPamfLpcmInfo)) - { - cellPamf->Error("cellPamfReaderGetStreamInfo: wrong LPCM data size(%d)", size); - return CELL_PAMF_ERROR_INVALID_ARG; - } - - pInfo->numberOfChannels = pAudio->channels; - pInfo->samplingFrequency = CELL_PAMF_FS_48kHz; - - if (pAudio->bps == 0x40) - pInfo->bitsPerSample = CELL_PAMF_BIT_LENGTH_16; - else - //TODO: CELL_PAMF_BIT_LENGTH_24 - cellPamf->Error("cellPamfReaderGetStreamInfo: unknown bps(0x%x)", (u8)pAudio->bps); - } - break; - case CELL_PAMF_STREAM_TYPE_USER_DATA: - { - cellPamf->Error("cellPamfReaderGetStreamInfo: CELL_PAMF_STREAM_TYPE_USER_DATA"); return CELL_PAMF_ERROR_INVALID_ARG; } + + auto info = vm::ptr::make(pInfo_addr); + + info->profileIdc = header.AVC.profileIdc; + info->levelIdc = header.AVC.levelIdc; + info->frameMbsOnlyFlag = (header.AVC.x2 & 0x80) >> 7; + info->videoSignalInfoFlag = (header.AVC.x2 & 0x40) >> 6; + info->frameRateInfo = (header.AVC.x2 & 0x0f) - 1; + info->aspectRatioIdc = header.AVC.aspectRatioIdc; + + if (header.AVC.aspectRatioIdc == 0xff) + { + info->sarWidth = header.AVC.sarWidth; + info->sarHeight = header.AVC.sarHeight; + } + else + { + info->sarWidth = 0; + info->sarHeight = 0; + } + + info->horizontalSize = ((u16)header.AVC.horizontalSize & 0xff) * 16; + info->verticalSize = ((u16)header.AVC.verticalSize & 0xff) * 16; + info->frameCropLeftOffset = header.AVC.frameCropLeftOffset; + info->frameCropRightOffset = header.AVC.frameCropRightOffset; + info->frameCropTopOffset = header.AVC.frameCropTopOffset; + info->frameCropBottomOffset = header.AVC.frameCropBottomOffset; + + if (info->videoSignalInfoFlag) + { + info->videoFormat = header.AVC.x14 >> 5; + info->videoFullRangeFlag = (header.AVC.x14 & 0x10) >> 4; + info->colourPrimaries = header.AVC.colourPrimaries; + info->transferCharacteristics = header.AVC.transferCharacteristics; + info->matrixCoefficients = header.AVC.matrixCoefficients; + } + else + { + info->videoFormat = 0; + info->videoFullRangeFlag = 0; + info->colourPrimaries = 0; + info->transferCharacteristics = 0; + info->matrixCoefficients = 0; + } + + info->entropyCodingModeFlag = (header.AVC.x18 & 0x80) >> 7; + info->deblockingFilterFlag = (header.AVC.x18 & 0x40) >> 6; + info->minNumSlicePerPictureIdc = (header.AVC.x18 & 0x30) >> 4; + info->nfwIdc = header.AVC.x18 & 0x03; + info->maxMeanBitrate = header.AVC.maxMeanBitrate; + + cellPamf->Notice("cellPamfReaderGetStreamInfo(): CELL_PAMF_STREAM_TYPE_AVC"); + break; + } + + case CELL_PAMF_STREAM_TYPE_M2V: + { + if (size < sizeof(CellPamfM2vInfo)) + { + return CELL_PAMF_ERROR_INVALID_ARG; + } + + auto info = vm::ptr::make(pInfo_addr); + + switch (header.M2V.x0) + { + case 0x44: info->profileAndLevelIndication = 3; break; + case 0x48: info->profileAndLevelIndication = 1; break; + default: info->profileAndLevelIndication = CELL_PAMF_M2V_UNKNOWN; + } + + info->progressiveSequence = (header.M2V.x2 & 0x80) >> 7; + info->videoSignalInfoFlag = (header.M2V.x2 & 0x40) >> 6; + info->frameRateInfo = header.M2V.x2 & 0xf; + info->aspectRatioIdc = header.M2V.aspectRatioIdc; + + if (header.M2V.aspectRatioIdc == 0xff) + { + info->sarWidth = header.M2V.sarWidth; + info->sarHeight = header.M2V.sarHeight; + } + else + { + info->sarWidth = 0; + info->sarHeight = 0; + } + + info->horizontalSize = ((u16)header.M2V.horizontalSize & 0xff) * 16; + info->verticalSize = ((u16)header.M2V.verticalSize & 0xff) * 16; + info->horizontalSizeValue = header.M2V.horizontalSizeValue; + info->verticalSizeValue = header.M2V.verticalSizeValue; + + if (info->videoSignalInfoFlag) + { + info->videoFormat = header.M2V.x14 >> 5; + info->videoFullRangeFlag = (header.M2V.x14 & 0x10) >> 4; + info->colourPrimaries = header.M2V.colourPrimaries; + info->transferCharacteristics = header.M2V.transferCharacteristics; + info->matrixCoefficients = header.M2V.matrixCoefficients; + } + else + { + info->videoFormat = 0; + info->videoFullRangeFlag = 0; + info->colourPrimaries = 0; + info->transferCharacteristics = 0; + info->matrixCoefficients = 0; + } + + cellPamf->Notice("cellPamfReaderGetStreamInfo(): CELL_PAMF_STREAM_TYPE_M2V"); + break; + } + + case CELL_PAMF_STREAM_TYPE_ATRAC3PLUS: + { + if (size < sizeof(CellPamfAtrac3plusInfo)) + { + return CELL_PAMF_ERROR_INVALID_ARG; + } + + auto info = vm::ptr::make(pInfo_addr); + + info->samplingFrequency = header.audio.freq & 0xf; + info->numberOfChannels = header.audio.channels & 0xf; + + cellPamf->Notice("cellPamfReaderGetStreamInfo(): CELL_PAMF_STREAM_TYPE_ATRAC3PLUS"); + break; + } + + case CELL_PAMF_STREAM_TYPE_PAMF_LPCM: + { + if (size < sizeof(CellPamfLpcmInfo)) + { + return CELL_PAMF_ERROR_INVALID_ARG; + } + + auto info = vm::ptr::make(pInfo_addr); + + info->samplingFrequency = header.audio.freq & 0xf; + info->numberOfChannels = header.audio.channels & 0xf; + info->bitsPerSample = header.audio.bps >> 6; + + cellPamf->Notice("cellPamfReaderGetStreamInfo(): CELL_PAMF_STREAM_TYPE_PAMF_LPCM"); + break; + } + + case CELL_PAMF_STREAM_TYPE_AC3: + { + if (size < sizeof(CellPamfAc3Info)) + { + return CELL_PAMF_ERROR_INVALID_ARG; + } + + auto info = vm::ptr::make(pInfo_addr); + + info->samplingFrequency = header.audio.freq & 0xf; + info->numberOfChannels = header.audio.channels & 0xf; + + cellPamf->Notice("cellPamfReaderGetStreamInfo(): CELL_PAMF_STREAM_TYPE_AC3"); + break; + } + + case CELL_PAMF_STREAM_TYPE_USER_DATA: + { + cellPamf->Error("cellPamfReaderGetStreamInfo(): invalid type CELL_PAMF_STREAM_TYPE_USER_DATA"); + return CELL_PAMF_ERROR_INVALID_ARG; + } + + case 6: + { + if (size < 4) + { + return CELL_PAMF_ERROR_INVALID_ARG; + } + + cellPamf->Todo("cellPamfReaderGetStreamInfo(): type 6"); + break; + } + + case 7: + { + if (size < 2) + { + return CELL_PAMF_ERROR_INVALID_ARG; + } + + cellPamf->Todo("cellPamfReaderGetStreamInfo(): type 7"); + break; + } + + case 8: + { + if (size < 2) + { + return CELL_PAMF_ERROR_INVALID_ARG; + } + + cellPamf->Todo("cellPamfReaderGetStreamInfo(): type 8"); + break; + } + + case 9: + { + cellPamf->Error("cellPamfReaderGetStreamInfo(): invalid type 9"); + return CELL_PAMF_ERROR_INVALID_ARG; + } + + default: + { + // invalid type or getting type/ch failed + cellPamf->Error("cellPamfReaderGetStreamInfo(): invalid type %d (ch=%d)", type, ch); + return CELL_PAMF_ERROR_INVALID_PAMF; + } } return CELL_OK; @@ -562,10 +694,10 @@ s32 cellPamfReaderGetStreamInfo(vm::ptr pSelf, u32 pInfo_addr, u u32 cellPamfReaderGetNumberOfEp(vm::ptr pSelf) { - cellPamf->Warning("cellPamfReaderGetNumberOfEp(pSelf=0x%x, stream=%d)", pSelf.addr(), pSelf->stream); + cellPamf->Todo("cellPamfReaderGetNumberOfEp(pSelf=0x%x, stream=%d)", pSelf.addr(), pSelf->stream); // cannot return error code - return pSelf->pAddr->stream_headers[pSelf->stream].ep_num; + return 0; //pSelf->pAddr->stream_headers[pSelf->stream].ep_num; } s32 cellPamfReaderGetEpIteratorWithIndex(vm::ptr pSelf, u32 epIndex, vm::ptr pIt) diff --git a/rpcs3/Emu/SysCalls/Modules/cellPamf.h b/rpcs3/Emu/SysCalls/Modules/cellPamf.h index 681c43ca4e..13a051285c 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPamf.h +++ b/rpcs3/Emu/SysCalls/Modules/cellPamf.h @@ -178,31 +178,33 @@ struct CellPamfAvcInfo u8 videoSignalInfoFlag; u8 frameRateInfo; u8 aspectRatioIdc; - be_t sarWidth; //reserved - be_t sarHeight; //reserved + be_t sarWidth; + be_t sarHeight; be_t horizontalSize; be_t verticalSize; - be_t frameCropLeftOffset; //reserved - be_t frameCropRightOffset; //reserved - be_t frameCropTopOffset; //reserved - be_t frameCropBottomOffset; //!!!!! - u8 videoFormat; //reserved + be_t frameCropLeftOffset; + be_t frameCropRightOffset; + be_t frameCropTopOffset; + be_t frameCropBottomOffset; + u8 videoFormat; u8 videoFullRangeFlag; u8 colourPrimaries; u8 transferCharacteristics; u8 matrixCoefficients; - u8 entropyCodingModeFlag; //reserved + u8 entropyCodingModeFlag; u8 deblockingFilterFlag; - u8 minNumSlicePerPictureIdc; //reserved - u8 nfwIdc; //reserved - u8 maxMeanBitrate; //reserved + u8 minNumSlicePerPictureIdc; + u8 nfwIdc; + u8 maxMeanBitrate; }; +static_assert(sizeof(CellPamfAvcInfo) == 0x20, "Invalid CellPamfAvcInfo size"); + // M2V (MPEG2 Video) Specific Information struct CellPamfM2vInfo { u8 profileAndLevelIndication; - bool progressiveSequence; + u8 progressiveSequence; u8 videoSignalInfoFlag; u8 frameRateInfo; u8 aspectRatioIdc; @@ -219,13 +221,7 @@ struct CellPamfM2vInfo u8 matrixCoefficients; }; -// LPCM Audio Specific Information -struct CellPamfLpcmInfo -{ - be_t samplingFrequency; - u8 numberOfChannels; - be_t bitsPerSample; -}; +static_assert(sizeof(CellPamfM2vInfo) == 0x18, "Invalid CellPamfM2vInfo size"); // ATRAC3+ Audio Specific Information struct CellPamfAtrac3plusInfo @@ -234,6 +230,8 @@ struct CellPamfAtrac3plusInfo u8 numberOfChannels; }; +static_assert(sizeof(CellPamfAtrac3plusInfo) == 8, "Invalid CellPamfAtrac3plusInfo size"); + // AC3 Audio Specific Information struct CellPamfAc3Info { @@ -241,61 +239,100 @@ struct CellPamfAc3Info u8 numberOfChannels; }; +static_assert(sizeof(CellPamfAc3Info) == 8, "Invalid CellPamfAc3Info size"); + +// LPCM Audio Specific Information +struct CellPamfLpcmInfo +{ + be_t samplingFrequency; + u8 numberOfChannels; + be_t bitsPerSample; +}; + + + #pragma pack(push, 1) // file data -// AVC specific information -struct PamfStreamHeader_AVC -{ - u8 profileIdc; - u8 levelIdc; - u8 unk0; - u8 unk1; //1 - u32 unk2; //0 - be_t horizontalSize; //divided by 16 - be_t verticalSize; //divided by 16 - u32 unk3; //0 - u32 unk4; //0 - u8 unk5; //0xA0 - u8 unk6; //1 - u8 unk7; //1 - u8 unk8; //1 - u8 unk9; //0xB0 - u8 unk10; - u16 unk11; //0 - u32 unk12; //0 -}; - -// M2V specific information -struct PamfStreamHeader_M2V -{ - u8 unknown[32]; -}; - -// Audio specific information -struct PamfStreamHeader_Audio -{ - u16 unknown; //== 0 - u8 channels; //number of channels (1, 2, 6 or 8) - u8 freq; //== 1 (always 48000) - u8 bps; //(LPCM only, 0x40 for 16 bit, ???? for 24) - u8 reserved[27]; //probably nothing -}; - struct PamfStreamHeader { - //TODO: look for correct beginning of stream header - u8 type; //0x1B for video (AVC), 0xDC ATRAC3+, 0x80 LPCM, 0xDD userdata - u8 unknown[3]; //0 - //TODO: examine stream_ch encoding + u8 type; + u8 unknown[3]; u8 fid_major; u8 fid_minor; - u8 unknown1; //????? - u8 unknown2; //????? - //Entry Point Info - be_t ep_offset; //offset of EP section in header - be_t ep_num; //count of EPs - //Specific Info - u8 data[32]; + u8 unknown1; + u8 unknown2; + be_t ep_offset; // offset of EP section in header + be_t ep_num; // count of EPs + + union + { + u8 data[32]; // specific info + + // AVC specific information + struct + { + u8 profileIdc; + u8 levelIdc; + u8 x2; // contains frameMbsOnlyFlag, videoSignalInfoFlag, frameRateInfo + u8 aspectRatioIdc; + u32 x4; // 0 (not used) + be_t horizontalSize; // divided by 16 + be_t verticalSize; // divided by 16 + be_t frameCropLeftOffset; + be_t frameCropRightOffset; + be_t frameCropTopOffset; + be_t frameCropBottomOffset; + union + { + struct + { + be_t sarWidth; + be_t sarHeight; + }; + struct + { + u8 x14; // contains videoFormat and videoFullRangeFlag + u8 colourPrimaries; + u8 transferCharacteristics; + u8 matrixCoefficients; + }; + }; + u8 x18; // contains entropyCodingModeFlag, deblockingFilterFlag, minNumSlicePerPictureIdc, nfwIdc + u8 maxMeanBitrate; + + } AVC; + + // M2V specific information + struct + { + s8 x0; // contains profileAndLevelIndication + u8 x1; // not used + u8 x2; // contains progressiveSequence, videoSignalInfoFlag, frameRateInfo + u8 aspectRatioIdc; + be_t sarWidth; + be_t sarHeight; + be_t horizontalSize; + be_t verticalSize; + be_t horizontalSizeValue; + be_t verticalSizeValue; + u32 x10; // not used + u8 x14; // contains videoFormat and videoFullRangeFlag + u8 colourPrimaries; + u8 transferCharacteristics; + u8 matrixCoefficients; + + } M2V; + + // Audio specific information + struct + { + u16 unknown; // 0 + u8 channels; // number of channels (1, 2, 6, 8) + u8 freq; // 1 (always 48000) + u8 bps; // LPCM only + + } audio; + }; }; static_assert(sizeof(PamfStreamHeader) == 48, "Invalid PamfStreamHeader size");