mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-20 03:25:16 +00:00
Vpost draft
This commit is contained in:
parent
f3a3a630c3
commit
17fa60c31c
8 changed files with 451 additions and 36 deletions
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
AVFrame& frame = *vdec->frame;
|
||||
|
||||
u8* buf = (u8*)malloc(vdec->buf_size);
|
||||
if (!buf)
|
||||
{
|
||||
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, const u32 picItem_ptr_addr)
|
||||
int cellVdecGetPicItem(u32 handle, mem32_t picItem_ptr)
|
||||
{
|
||||
cellVdec.Error("cellVdecGetPicItem(handle=%d, picItem_ptr_addr=0x%x)", handle, picItem_ptr_addr);
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
};
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
};
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue