Vpost draft

This commit is contained in:
Nekotekina 2014-03-01 12:38:50 +04:00
parent f3a3a630c3
commit 17fa60c31c
8 changed files with 451 additions and 36 deletions

View File

@ -30,7 +30,7 @@ bool vfsDir::Create(const wxString& path)
bool vfsDir::IsExists(const wxString& path) const
{
return m_stream->IsExists(path);
return m_stream->IsExists(path); // Crash (Access violation reading location 0x0000000000000000)
}
const Array<DirEntryInfo>& vfsDir::GetEntries() const

View File

@ -85,9 +85,15 @@ u32 dmuxOpen(Demuxer* data)
break;
case PADDING_STREAM:
{
stream.skip(4);
stream.get(len);
stream.skip(len);
}
break;
case PRIVATE_STREAM_2:
{
// unknown
stream.skip(4);
stream.get(len);
stream.skip(len);
@ -127,19 +133,19 @@ u32 dmuxOpen(Demuxer* data)
stream.get(len);
PesHeader pes(stream);
if (!pes.size && !es.hasdata()) // fatal error
if (!pes.new_au && !es.hasdata()) // fatal error
{
ConLog.Error("PES not found");
return;
}
if (pes.size && es.hasdata()) // new AU detected
if (pes.new_au && es.hasdata()) // new AU detected
{
/*if (es.hasunseen())
if (es.hasunseen()) // hack, probably useless
{
stream = backup;
continue;
}*/
}
es.finish(stream);
// callback
mem_ptr_t<CellDmuxEsMsg> esMsg(a128(dmux.memAddr) + (cb_add ^= 16));
@ -151,7 +157,7 @@ u32 dmuxOpen(Demuxer* data)
cb.Branch(false);
}
if (pes.size)
if (pes.new_au)
{
ConLog.Write("*** AVC AU detected (pts=0x%llx, dts=0x%llx)", pes.pts, pes.dts);
}
@ -161,7 +167,6 @@ u32 dmuxOpen(Demuxer* data)
stream = backup;
continue;
}
es.push(stream, len - pes.size - 3, pes);
}
else
@ -217,6 +222,19 @@ task:
{
case dmuxSetStream:
{
bool do_wait = false;
for (u32 i = 0; i < 192; i++)
{
if (esALL[i])
{
if (esALL[i]->hasunseen()) // hack, probably useless
{
do_wait = true;
break;
}
}
}
if (do_wait) continue;
stream = task.stream;
ConLog.Write("*** stream updated(addr=0x%x, size=0x%x, discont=%d, userdata=0x%llx)",
stream.addr, stream.size, stream.discontinuity, stream.userdata);
@ -832,7 +850,9 @@ int cellDmuxPeekAuEx(u32 esHandle, mem32_t auInfoEx_ptr, mem32_t auSpecificInfo_
int cellDmuxReleaseAu(u32 esHandle)
{
cellDmux.Log("cellDmuxReleaseAu(esHandle=0x%x)", esHandle);
cellDmux.Warning("(disabled) cellDmuxReleaseAu(esHandle=0x%x)", esHandle);
return CELL_OK;
ElementaryStream* es;
if (!Emu.GetIdManager().GetIDData(esHandle, es))
@ -842,7 +862,9 @@ int cellDmuxReleaseAu(u32 esHandle)
if (!es->canrelease())
{
cellDmux.Error("cellDmuxReleaseAu: no AU");
return CELL_DMUX_ERROR_SEQ;
//return CELL_OK;
}
DemuxerTask task(dmuxReleaseAu);

View File

@ -366,23 +366,28 @@ struct PesHeader
u64 dts;
u8 ch;
u8 size;
bool new_au;
PesHeader(DemuxerStream& stream)
: pts(0)
, dts(0)
: pts(0xffffffffffffffff)
, dts(0xffffffffffffffff)
, ch(0)
, size(0)
, new_au(false)
{
u16 header;
stream.get(header);
stream.get(size);
new_au = true;
if (size)
{
//ConLog.Write(">>>>> Pes Header (size=%d)", size);
if (size < 10)
{
ConLog.Error("Unknown PesHeader size");
Emu.Pause();
stream.skip(size);
return;
}
new_au = true;
u8 v;
stream.get(v);
if ((v & 0xF0) != 0x30)
@ -454,8 +459,8 @@ public:
const u32 cbFunc;
const u32 cbArg;
u32 id;
bool is_finished;
bool is_running;
volatile bool is_finished;
volatile bool is_running;
Demuxer(u32 addr, u32 size, u32 func, u32 arg)

View File

@ -6,6 +6,7 @@
extern "C"
{
#include "libavcodec\avcodec.h"
#include "libavutil\imgutils.h"
}
#include "cellVdec.h"
@ -26,8 +27,8 @@ u32 vdecQueryAttr(CellVdecCodecType type, u32 profile, u32 spec_addr /* may be 0
// TODO: check values
attr->decoderVerLower = 0x280000; // from dmux
attr->decoderVerUpper = 0x260000;
attr->memSize = 64 * 1024 * 1024;
attr->cmdDepth = 15;
attr->memSize = 4 * 1024 * 1024;
attr->cmdDepth = 16;
return CELL_OK;
}
@ -59,6 +60,12 @@ u32 vdecOpen(VideoDecoder* data)
continue;
}
if (vdec.has_picture) // hack
{
Sleep(1);
continue;
}
if (!vdec.job.Pop(task))
{
break;
@ -76,7 +83,10 @@ u32 vdecOpen(VideoDecoder* data)
case vdecEndSeq:
{
// TODO: send callback
Callback cb;
cb.SetAddr(vdec.cbFunc);
cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_SEQDONE, 0, vdec.cbArg);
cb.Branch(false);
ConLog.Warning("vdecEndSeq()");
vdec.is_running = false;
}
@ -90,6 +100,7 @@ u32 vdecOpen(VideoDecoder* data)
{
av_new_packet(this, size + FF_INPUT_BUFFER_PADDING_SIZE);
memset(data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
this->size -= FF_INPUT_BUFFER_PADDING_SIZE; // ????????????????????
}
~vdecPacket()
@ -99,8 +110,13 @@ u32 vdecOpen(VideoDecoder* data)
} au(task.size);
au.pts = task.pts;
au.dts = task.dts;
if (task.pts || task.dts)
{
vdec.pts = task.pts;
vdec.dts = task.dts;
}
au.pts = vdec.pts;
au.dts = vdec.dts;
if (task.mode != CELL_VDEC_DEC_MODE_NORMAL)
{
@ -116,6 +132,9 @@ u32 vdecOpen(VideoDecoder* data)
int got_picture = 0;
//vdec.ctx->flags |= CODEC_FLAG_TRUNCATED;
//vdec.ctx->flags2 |= CODEC_FLAG2_CHUNKS;
int decode = avcodec_decode_video2(vdec.ctx, vdec.frame, &got_picture, &au);
if (decode < 0)
{
@ -123,7 +142,48 @@ u32 vdecOpen(VideoDecoder* data)
break;
}
ConLog.Write("Frame decoded (%d)", decode);
ConLog.Write("Frame decoded (pts=0x%llx, dts=0x%llx, addr=0x%x, result=0x%x)",
au.pts, au.dts, task.addr, decode);
Callback cb;
cb.SetAddr(vdec.cbFunc);
cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_AUDONE, 0, vdec.cbArg);
cb.Branch(false);
if (got_picture)
{
ConLog.Write("got_picture (%d, vdec: pts=0x%llx, dts=0x%llx)", got_picture, vdec.pts, vdec.dts);
vdec.pts += 3003;
vdec.dts += 3003;
/*if (vdec.out_data[0]) av_freep(vdec.out_data[0]);
int err = av_image_alloc(vdec.out_data, vdec.linesize, vdec.ctx->width, vdec.ctx->height, vdec.ctx->pix_fmt, 1);
if (err < 0)
{
ConLog.Error("vdecDecodeAu: av_image_alloc failed(%d)", err);
Emu.Pause();
return;
}
vdec.buf_size = err;
av_image_copy(vdec.out_data, vdec.linesize, (const u8**)(vdec.frame->data), vdec.frame->linesize,
vdec.ctx->pix_fmt, vdec.ctx->width, vdec.ctx->height);*/
vdec.buf_size = a128(av_image_get_buffer_size(vdec.ctx->pix_fmt, vdec.ctx->width, vdec.ctx->height, 1));
vdec.dts = task.dts;
vdec.pts = task.pts;
vdec.userdata = task.userData;
vdec.has_picture = true;
Callback cb;
cb.SetAddr(vdec.cbFunc);
cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_PICOUT, 0, vdec.cbArg);
cb.Branch(false);
}
}
break;
@ -137,6 +197,7 @@ u32 vdecOpen(VideoDecoder* data)
case vdecSetFrameRate:
{
ConLog.Error("TODO: vdecSetFrameRate(%d)", task.frc);
return;
}
default:
@ -297,13 +358,162 @@ int cellVdecDecodeAu(u32 handle, CellVdecDecodeMode mode, const mem_ptr_t<CellVd
int cellVdecGetPicture(u32 handle, const mem_ptr_t<CellVdecPicFormat> format, u32 out_addr)
{
cellVdec.Error("cellVdecGetPicture(handle=%d, format_addr=0x%x, out_addr=0x%x)", handle, format.GetAddr(), out_addr);
cellVdec.Warning("cellVdecGetPicture(handle=%d, format_addr=0x%x, out_addr=0x%x)", handle, format.GetAddr(), out_addr);
VideoDecoder* vdec;
if (!Emu.GetIdManager().GetIDData(handle, vdec))
{
return CELL_VDEC_ERROR_ARG;
}
if (!format.IsGood())
{
return CELL_VDEC_ERROR_FATAL;
}
if (!vdec->has_picture)
{
return CELL_VDEC_ERROR_EMPTY;
}
if (out_addr)
{
if (!Memory.IsGoodAddr(out_addr, vdec->buf_size))
{
return CELL_VDEC_ERROR_FATAL;
}
if (format->formatType != CELL_VDEC_PICFMT_YUV420_PLANAR)
{
cellVdec.Error("cellVdecGetPicture: TODO: unknown formatType(%d)", (u32)format->formatType);
return CELL_OK;
}
if (format->colorMatrixType != CELL_VDEC_COLOR_MATRIX_TYPE_BT709)
{
cellVdec.Error("cellVdecGetPicture: TODO: unknown colorMatrixType(%d)", (u32)format->colorMatrixType);
return CELL_OK;
}
int cellVdecGetPicItem(u32 handle, const u32 picItem_ptr_addr)
AVFrame& frame = *vdec->frame;
u8* buf = (u8*)malloc(vdec->buf_size);
if (!buf)
{
cellVdec.Error("cellVdecGetPicItem(handle=%d, picItem_ptr_addr=0x%x)", handle, picItem_ptr_addr);
cellVdec.Error("cellVdecGetPicture: malloc failed (out of memory)");
Emu.Pause();
return CELL_OK;
}
// TODO: zero padding bytes
int err = av_image_copy_to_buffer(buf, vdec->buf_size, frame.data, frame.linesize, vdec->ctx->pix_fmt, frame.width, frame.height, 1);
if (err < 0)
{
cellVdec.Error("cellVdecGetPicture: av_image_copy_to_buffer failed(%d)", err);
Emu.Pause();
}
if (!Memory.CopyFromReal(out_addr, buf, vdec->buf_size))
{
cellVdec.Error("cellVdecGetPicture: data copying failed");
Emu.Pause();
}
/*
u32 size0 = frame.linesize[0] * frame.height;
u32 size1 = frame.linesize[1] * frame.height / 2;
u32 size2 = frame.linesize[2] * frame.height / 2;
ConLog.Write("*** size0=0x%x, size1=0x%x, size2=0x%x, buf_size=0x%x (res=0x%x)", size0, size1, size2, vdec->buf_size, err);
*/
free(buf);
}
vdec->has_picture = false;
return CELL_OK;
}
int cellVdecGetPicItem(u32 handle, mem32_t picItem_ptr)
{
cellVdec.Warning("cellVdecGetPicItem(handle=%d, picItem_ptr_addr=0x%x)", handle, picItem_ptr.GetAddr());
VideoDecoder* vdec;
if (!Emu.GetIdManager().GetIDData(handle, vdec))
{
return CELL_VDEC_ERROR_ARG;
}
if (!picItem_ptr.IsGood())
{
return CELL_VDEC_ERROR_FATAL;
}
if (!vdec->has_picture)
{
return CELL_VDEC_ERROR_EMPTY;
}
mem_ptr_t<CellVdecPicItem> info(vdec->memAddr);
info->codecType = vdec->type;
info->startAddr = 0x00000123; // invalid value (no address for picture)
info->size = vdec->buf_size;
info->auNum = 1;
info->auPts[0].lower = vdec->pts;
info->auPts[0].upper = vdec->pts >> 32;
info->auPts[1].lower = 0xffffffff;
info->auPts[1].upper = 0xffffffff;
info->auDts[0].lower = vdec->dts;
info->auDts[0].upper = vdec->dts >> 32;
info->auDts[1].lower = 0xffffffff;
info->auDts[1].upper = 0xffffffff;
info->auUserData[0] = vdec->userdata;
info->auUserData[1] = 0;
info->status = CELL_OK;
info->attr = CELL_VDEC_PICITEM_ATTR_NORMAL;
info->picInfo_addr = vdec->memAddr + sizeof(CellVdecPicItem);
mem_ptr_t<CellVdecAvcInfo> avc(vdec->memAddr + sizeof(CellVdecPicItem));
avc->horizontalSize = vdec->frame->width; // ???
avc->verticalSize = vdec->frame->height;
switch (vdec->frame->pict_type)
{
case AV_PICTURE_TYPE_I: avc->pictureType[0] = CELL_VDEC_AVC_PCT_I; break;
case AV_PICTURE_TYPE_P: avc->pictureType[0] = CELL_VDEC_AVC_PCT_P; break;
case AV_PICTURE_TYPE_B: avc->pictureType[0] = CELL_VDEC_AVC_PCT_B; break;
default: avc->pictureType[0] = CELL_VDEC_AVC_PCT_UNKNOWN; break; // ???
}
avc->pictureType[1] = CELL_VDEC_AVC_PCT_UNKNOWN; // ???
avc->idrPictureFlag = false; // ???
avc->aspect_ratio_idc = CELL_VDEC_AVC_ARI_SAR_UNSPECIFIED; // ???
avc->sar_height = 0;
avc->sar_width = 0;
avc->pic_struct = CELL_VDEC_AVC_PSTR_FRAME; // ???
avc->picOrderCount[0] = 0; // ???
avc->picOrderCount[1] = 0;
avc->vui_parameters_present_flag = true; // ???
avc->frame_mbs_only_flag = true; // ??? progressive
avc->video_signal_type_present_flag = true; // ???
avc->video_format = CELL_VDEC_AVC_VF_COMPONENT; // ???
avc->video_full_range_flag = false; // ???
avc->colour_description_present_flag = true;
avc->colour_primaries = CELL_VDEC_AVC_CP_ITU_R_BT_709_5; // ???
avc->transfer_characteristics = CELL_VDEC_AVC_TC_ITU_R_BT_709_5;
avc->matrix_coefficients = CELL_VDEC_AVC_MXC_ITU_R_BT_709_5; // important
avc->timing_info_present_flag = true;
avc->frameRateCode = CELL_VDEC_AVC_FRC_30000DIV1001; // important (!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!)
avc->fixed_frame_rate_flag = true;
avc->low_delay_hrd_flag = true; // ???
avc->entropy_coding_mode_flag = true; // ???
avc->nalUnitPresentFlags = 0; // ???
avc->ccDataLength[0] = 0;
avc->ccDataLength[1] = 0;
avc->reserved[0] = 0;
avc->reserved[1] = 0;
picItem_ptr = info.GetAddr();
return CELL_OK;
}

View File

@ -2,6 +2,8 @@
#include "Utilities/SQueue.h"
#define a128(x) ((x + 127) & (~127))
// Error Codes
enum
{
@ -341,16 +343,18 @@ struct CellVdecAvcInfo
AVC_transfer_characteristics transfer_characteristics;
AVC_matrix_coefficients matrix_coefficients;
bool timing_info_present_flag;
CellVdecFrameRate frameRateCode;
AVC_FrameRateCode frameRateCode; // ???
bool fixed_frame_rate_flag;
bool low_delay_hrd_flag;
bool entropy_coding_mode_flag;
be_t<AVC_NulUnitPresentFlags> nalUnitPresentFlags;
be_t<u16> nalUnitPresentFlags;
u8 ccDataLength[2];
u8 ccData[2][CELL_VDEC_AVC_CCD_MAX];
be_t<u64> reserved[2];
};
const int sz = sizeof(CellVdecAvcInfo);
// DIVX Profile
enum DIVX_level : u8
{
@ -686,15 +690,21 @@ public:
AVCodec* codec;
AVCodecContext* ctx;
AVFrame* frame;
AVDictionary* opts;
u32 buf_size;
u64 pts;
u64 dts;
u64 userdata;
volatile bool has_picture;
const u32 type;
const CellVdecCodecType type;
const u32 profile;
const u32 memAddr;
const u32 memSize;
const u32 cbFunc;
const u32 cbArg;
VideoDecoder(u32 type, u32 profile, u32 addr, u32 size, u32 func, u32 arg)
VideoDecoder(CellVdecCodecType type, u32 profile, u32 addr, u32 size, u32 func, u32 arg)
: type(type)
, profile(profile)
, memAddr(addr)
@ -703,6 +713,7 @@ public:
, cbArg(arg)
, is_finished(false)
, is_running(false)
, has_picture(false)
{
codec = avcodec_find_decoder(AV_CODEC_ID_H264);
if (!codec)
@ -718,7 +729,9 @@ public:
Emu.Pause();
return;
}
if (int err = avcodec_open2(ctx, codec, NULL)) // TODO: not multithread safe
opts = nullptr;
int err = avcodec_open2(ctx, codec, &opts);
if (err) // TODO: not multithread safe
{
ConLog.Error("VideoDecoder(): avcodec_open2 failed(%d)", err);
Emu.Pause();
@ -731,6 +744,8 @@ public:
Emu.Pause();
return;
}
//memset(&out_data, 0, sizeof(out_data));
//memset(&linesize, 0, sizeof(linesize));
}
~VideoDecoder()
@ -741,5 +756,6 @@ public:
avcodec_close(ctx);
av_free(ctx);
}
//if (out_data[0]) av_freep(out_data[0]);
}
};

View File

@ -8,35 +8,186 @@ Module cellVpost(0x0008, cellVpost_init);
int cellVpostQueryAttr(const mem_ptr_t<CellVpostCfgParam> cfgParam, mem_ptr_t<CellVpostAttr> attr)
{
cellVpost.Error("cellVpostQueryAttr(cfgParam_addr=0x%x, attr_addr=0x%x)", cfgParam.GetAddr(), attr.GetAddr());
cellVpost.Warning("cellVpostQueryAttr(cfgParam_addr=0x%x, attr_addr=0x%x)", cfgParam.GetAddr(), attr.GetAddr());
if (!cfgParam.IsGood()) return CELL_VPOST_ERROR_Q_ARG_CFG_NULL;
if (!attr.IsGood()) return CELL_VPOST_ERROR_Q_ARG_ATTR_NULL;
// TODO: check cfgParam and output values
attr->delay = 0;
attr->memSize = 4 * 1024 * 1024;
attr->vpostVerLower = 0x280000; // from dmux
attr->vpostVerUpper = 0x260000;
return CELL_OK;
}
u32 vpostOpen(VpostInstance* data)
{
u32 id = cellVpost.GetNewId(data);
ConLog.Write("*** Vpost instance created (to_rgba=%d): id = %d", data->to_rgba, id);
return id;
}
int cellVpostOpen(const mem_ptr_t<CellVpostCfgParam> cfgParam, const mem_ptr_t<CellVpostResource> resource, mem32_t handle)
{
cellVpost.Error("cellVpostOpen(cfgParam_addr=0x%x, resource_addr=0x%x, handle_addr=0x%x)",
cellVpost.Warning("cellVpostOpen(cfgParam_addr=0x%x, resource_addr=0x%x, handle_addr=0x%x)",
cfgParam.GetAddr(), resource.GetAddr(), handle.GetAddr());
if (!cfgParam.IsGood()) return CELL_VPOST_ERROR_O_ARG_CFG_NULL;
if (!resource.IsGood()) return CELL_VPOST_ERROR_O_ARG_RSRC_NULL;
if (!handle.IsGood()) return CELL_VPOST_ERROR_O_ARG_HDL_NULL;
// TODO: check values
handle = vpostOpen(new VpostInstance(cfgParam->outPicFmt == CELL_VPOST_PIC_FMT_OUT_RGBA_ILV));
return CELL_OK;
}
int cellVpostOpenEx(const mem_ptr_t<CellVpostCfgParam> cfgParam, const mem_ptr_t<CellVpostResourceEx> resource, mem32_t handle)
{
cellVpost.Error("cellVpostOpenEx(cfgParam_addr=0x%x, resource_addr=0x%x, handle_addr=0x%x)",
cellVpost.Warning("cellVpostOpenEx(cfgParam_addr=0x%x, resource_addr=0x%x, handle_addr=0x%x)",
cfgParam.GetAddr(), resource.GetAddr(), handle.GetAddr());
if (!cfgParam.IsGood()) return CELL_VPOST_ERROR_O_ARG_CFG_NULL;
if (!resource.IsGood()) return CELL_VPOST_ERROR_O_ARG_RSRC_NULL;
if (!handle.IsGood()) return CELL_VPOST_ERROR_O_ARG_HDL_NULL;
// TODO: check values
handle = vpostOpen(new VpostInstance(cfgParam->outPicFmt == CELL_VPOST_PIC_FMT_OUT_RGBA_ILV));
return CELL_OK;
}
int cellVpostClose(u32 handle)
{
cellVpost.Error("cellVpostClose(handle=0x%x)", handle);
cellVpost.Warning("cellVpostClose(handle=0x%x)", handle);
VpostInstance* vpost;
if (!Emu.GetIdManager().GetIDData(handle, vpost))
{
return CELL_VPOST_ERROR_C_ARG_HDL_INVALID;
}
Emu.GetIdManager().RemoveID(handle);
return CELL_OK;
}
int cellVpostExec(u32 handle, const u32 inPicBuff_addr, const mem_ptr_t<CellVpostCtrlParam> ctrlParam,
u32 outPicBuff_addr, mem_ptr_t<CellVpostPictureInfo> picInfo)
{
cellVpost.Error("cellVpostExec(handle=0x%x, inPicBuff_addr=0x%x, ctrlParam_addr=0x%x, outPicBuff_addr=0x%x, picInfo_addr=0x%x)",
cellVpost.Warning("cellVpostExec(handle=0x%x, inPicBuff_addr=0x%x, ctrlParam_addr=0x%x, outPicBuff_addr=0x%x, picInfo_addr=0x%x)",
handle, inPicBuff_addr, ctrlParam.GetAddr(), outPicBuff_addr, picInfo.GetAddr());
VpostInstance* vpost;
if (!Emu.GetIdManager().GetIDData(handle, vpost))
{
return CELL_VPOST_ERROR_E_ARG_HDL_INVALID;
}
if (!ctrlParam.IsGood())
{
return CELL_VPOST_ERROR_E_ARG_CTRL_INVALID;
}
u32 w = ctrlParam->inWidth;
u32 h = ctrlParam->inHeight;
if (!Memory.IsGoodAddr(inPicBuff_addr, w*h*3/2))
{
return CELL_VPOST_ERROR_E_ARG_INPICBUF_INVALID;
}
if (!Memory.IsGoodAddr(outPicBuff_addr, w*h*4))
{
return CELL_VPOST_ERROR_E_ARG_OUTPICBUF_INVALID;
}
if (!picInfo.IsGood())
{
return CELL_VPOST_ERROR_E_ARG_PICINFO_NULL;
}
ctrlParam->inWindow; // ignored
ctrlParam->outWindow; // ignored
ctrlParam->execType; // ignored
ctrlParam->scalerType; // ignored
ctrlParam->ipcType; // ignored
picInfo->inWidth = ctrlParam->inWidth; // copy
picInfo->inHeight = ctrlParam->inHeight; // copy
picInfo->inDepth = CELL_VPOST_PIC_DEPTH_8; // fixed
picInfo->inScanType = CELL_VPOST_SCAN_TYPE_P; // TODO
picInfo->inPicFmt = CELL_VPOST_PIC_FMT_IN_YUV420_PLANAR; // fixed
picInfo->inChromaPosType = ctrlParam->inChromaPosType; // copy
picInfo->inPicStruct = CELL_VPOST_PIC_STRUCT_PFRM; // TODO
picInfo->inQuantRange = ctrlParam->inQuantRange; // copy
picInfo->inColorMatrix = ctrlParam->inColorMatrix; // copy
picInfo->outWidth = picInfo->inWidth; // TODO (resampling)
picInfo->outHeight = picInfo->inHeight; // TODO
picInfo->outDepth = CELL_VPOST_PIC_DEPTH_8; // fixed
picInfo->outScanType = CELL_VPOST_SCAN_TYPE_P; // TODO
picInfo->outPicFmt = CELL_VPOST_PIC_FMT_OUT_RGBA_ILV; // TODO
picInfo->outChromaPosType = ctrlParam->inChromaPosType; // ???
picInfo->outPicStruct = picInfo->inPicStruct; // ???
picInfo->outQuantRange = ctrlParam->inQuantRange; // ???
picInfo->outColorMatrix = ctrlParam->inColorMatrix; // ???
picInfo->userData = ctrlParam->userData; // copy
picInfo->reserved1 = 0;
picInfo->reserved2 = 0;
u8* pY = (u8*)malloc(w*h);
u8* pU = (u8*)malloc(w*h/4);
u8* pV = (u8*)malloc(w*h/4);
u32* res = (u32*)malloc(w*h*4);
const u8 alpha = ctrlParam->outAlpha;
if (!Memory.CopyToReal(pY, inPicBuff_addr, w*h))
{
cellVpost.Error("cellVpostExec: data copying failed(pY)");
}
if (!Memory.CopyToReal(pU, inPicBuff_addr + w*h, w*h/4))
{
cellVpost.Error("cellVpostExec: data copying failed(pU)");
}
if (!Memory.CopyToReal(pV, inPicBuff_addr + w*h + w*h/4, w*h/4))
{
cellVpost.Error("cellVpostExec: data copying failed(pV)");
}
for (u32 i = 0; i < h; i++) for (u32 j = 0; j < w; j++)
{
float Cr = pV[(i/2)*(w/2)+j/2];
float Cb = pU[(i/2)*(w/2)+j/2];
float Y = pY[i*w+j];
int R = Y + 1.5701f * Cr;
if (R < 0) R = 0;
if (R > 255) R = 255;
int G = Y - 0.1870f * Cb - 0.4664f * Cr;
if (G < 0) G = 0;
if (G > 255) G = 255;
int B = Y - 1.8556f * Cb;
if (B < 0) B = 0;
if (B > 255) B = 255;
res[i*w+j] = ((u32)alpha << 24) | (B << 16) | (G << 8) | (R);
}
if (!Memory.CopyFromReal(outPicBuff_addr, res, w*h*4))
{
cellVpost.Error("cellVpostExec: data copying failed(result)");
Emu.Pause();
}
free(pY);
free(pU);
free(pV);
free(res);
return CELL_OK;
}

View File

@ -315,3 +315,14 @@ struct CellVpostPictureInfo
be_t<u32> reserved1;
be_t<u32> reserved2;
};
class VpostInstance
{
public:
const bool to_rgba;
VpostInstance(bool rgba)
: to_rgba(rgba)
{
}
};

View File

@ -29,10 +29,10 @@ MemoryViewerPanel::MemoryViewerPanel(wxWindow* parent)
s_tools_mem_bytes.Add(sc_bytes);
wxStaticBoxSizer& s_tools_mem_buttons = *new wxStaticBoxSizer(wxHORIZONTAL, this, "Control");
wxButton* b_fprev = new wxButton(this, wxID_ANY, "\u00AB", wxDefaultPosition, wxSize(21, 21));
wxButton* b_fprev = new wxButton(this, wxID_ANY, "<<", wxDefaultPosition, wxSize(21, 21));
wxButton* b_prev = new wxButton(this, wxID_ANY, "<", wxDefaultPosition, wxSize(21, 21));
wxButton* b_next = new wxButton(this, wxID_ANY, ">", wxDefaultPosition, wxSize(21, 21));
wxButton* b_fnext = new wxButton(this, wxID_ANY, "\u00BB", wxDefaultPosition, wxSize(21, 21));
wxButton* b_fnext = new wxButton(this, wxID_ANY, ">>", wxDefaultPosition, wxSize(21, 21));
s_tools_mem_buttons.Add(b_fprev);
s_tools_mem_buttons.Add(b_prev);
s_tools_mem_buttons.Add(b_next);