mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-15 19:28:43 +12: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
|
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
|
const Array<DirEntryInfo>& vfsDir::GetEntries() const
|
||||||
|
|
|
@ -85,9 +85,15 @@ u32 dmuxOpen(Demuxer* data)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PADDING_STREAM:
|
case PADDING_STREAM:
|
||||||
|
{
|
||||||
|
stream.skip(4);
|
||||||
|
stream.get(len);
|
||||||
|
stream.skip(len);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case PRIVATE_STREAM_2:
|
case PRIVATE_STREAM_2:
|
||||||
{
|
{
|
||||||
// unknown
|
|
||||||
stream.skip(4);
|
stream.skip(4);
|
||||||
stream.get(len);
|
stream.get(len);
|
||||||
stream.skip(len);
|
stream.skip(len);
|
||||||
|
@ -127,19 +133,19 @@ u32 dmuxOpen(Demuxer* data)
|
||||||
stream.get(len);
|
stream.get(len);
|
||||||
PesHeader pes(stream);
|
PesHeader pes(stream);
|
||||||
|
|
||||||
if (!pes.size && !es.hasdata()) // fatal error
|
if (!pes.new_au && !es.hasdata()) // fatal error
|
||||||
{
|
{
|
||||||
ConLog.Error("PES not found");
|
ConLog.Error("PES not found");
|
||||||
return;
|
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;
|
stream = backup;
|
||||||
continue;
|
continue;
|
||||||
}*/
|
}
|
||||||
es.finish(stream);
|
es.finish(stream);
|
||||||
// callback
|
// callback
|
||||||
mem_ptr_t<CellDmuxEsMsg> esMsg(a128(dmux.memAddr) + (cb_add ^= 16));
|
mem_ptr_t<CellDmuxEsMsg> esMsg(a128(dmux.memAddr) + (cb_add ^= 16));
|
||||||
|
@ -151,7 +157,7 @@ u32 dmuxOpen(Demuxer* data)
|
||||||
cb.Branch(false);
|
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);
|
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;
|
stream = backup;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
es.push(stream, len - pes.size - 3, pes);
|
es.push(stream, len - pes.size - 3, pes);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -217,6 +222,19 @@ task:
|
||||||
{
|
{
|
||||||
case dmuxSetStream:
|
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;
|
stream = task.stream;
|
||||||
ConLog.Write("*** stream updated(addr=0x%x, size=0x%x, discont=%d, userdata=0x%llx)",
|
ConLog.Write("*** stream updated(addr=0x%x, size=0x%x, discont=%d, userdata=0x%llx)",
|
||||||
stream.addr, stream.size, stream.discontinuity, stream.userdata);
|
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)
|
int cellDmuxReleaseAu(u32 esHandle)
|
||||||
{
|
{
|
||||||
cellDmux.Log("cellDmuxReleaseAu(esHandle=0x%x)", esHandle);
|
cellDmux.Warning("(disabled) cellDmuxReleaseAu(esHandle=0x%x)", esHandle);
|
||||||
|
|
||||||
|
return CELL_OK;
|
||||||
|
|
||||||
ElementaryStream* es;
|
ElementaryStream* es;
|
||||||
if (!Emu.GetIdManager().GetIDData(esHandle, es))
|
if (!Emu.GetIdManager().GetIDData(esHandle, es))
|
||||||
|
@ -842,7 +862,9 @@ int cellDmuxReleaseAu(u32 esHandle)
|
||||||
|
|
||||||
if (!es->canrelease())
|
if (!es->canrelease())
|
||||||
{
|
{
|
||||||
|
cellDmux.Error("cellDmuxReleaseAu: no AU");
|
||||||
return CELL_DMUX_ERROR_SEQ;
|
return CELL_DMUX_ERROR_SEQ;
|
||||||
|
//return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
DemuxerTask task(dmuxReleaseAu);
|
DemuxerTask task(dmuxReleaseAu);
|
||||||
|
|
|
@ -366,23 +366,28 @@ struct PesHeader
|
||||||
u64 dts;
|
u64 dts;
|
||||||
u8 ch;
|
u8 ch;
|
||||||
u8 size;
|
u8 size;
|
||||||
|
bool new_au;
|
||||||
|
|
||||||
PesHeader(DemuxerStream& stream)
|
PesHeader(DemuxerStream& stream)
|
||||||
: pts(0)
|
: pts(0xffffffffffffffff)
|
||||||
, dts(0)
|
, dts(0xffffffffffffffff)
|
||||||
, ch(0)
|
, ch(0)
|
||||||
, size(0)
|
, size(0)
|
||||||
|
, new_au(false)
|
||||||
{
|
{
|
||||||
u16 header;
|
u16 header;
|
||||||
stream.get(header);
|
stream.get(header);
|
||||||
stream.get(size);
|
stream.get(size);
|
||||||
|
new_au = true;
|
||||||
if (size)
|
if (size)
|
||||||
{
|
{
|
||||||
|
//ConLog.Write(">>>>> Pes Header (size=%d)", size);
|
||||||
if (size < 10)
|
if (size < 10)
|
||||||
{
|
{
|
||||||
ConLog.Error("Unknown PesHeader size");
|
stream.skip(size);
|
||||||
Emu.Pause();
|
return;
|
||||||
}
|
}
|
||||||
|
new_au = true;
|
||||||
u8 v;
|
u8 v;
|
||||||
stream.get(v);
|
stream.get(v);
|
||||||
if ((v & 0xF0) != 0x30)
|
if ((v & 0xF0) != 0x30)
|
||||||
|
@ -454,8 +459,8 @@ public:
|
||||||
const u32 cbFunc;
|
const u32 cbFunc;
|
||||||
const u32 cbArg;
|
const u32 cbArg;
|
||||||
u32 id;
|
u32 id;
|
||||||
bool is_finished;
|
volatile bool is_finished;
|
||||||
bool is_running;
|
volatile bool is_running;
|
||||||
|
|
||||||
|
|
||||||
Demuxer(u32 addr, u32 size, u32 func, u32 arg)
|
Demuxer(u32 addr, u32 size, u32 func, u32 arg)
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
#include "libavcodec\avcodec.h"
|
#include "libavcodec\avcodec.h"
|
||||||
|
#include "libavutil\imgutils.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "cellVdec.h"
|
#include "cellVdec.h"
|
||||||
|
@ -26,8 +27,8 @@ u32 vdecQueryAttr(CellVdecCodecType type, u32 profile, u32 spec_addr /* may be 0
|
||||||
// TODO: check values
|
// TODO: check values
|
||||||
attr->decoderVerLower = 0x280000; // from dmux
|
attr->decoderVerLower = 0x280000; // from dmux
|
||||||
attr->decoderVerUpper = 0x260000;
|
attr->decoderVerUpper = 0x260000;
|
||||||
attr->memSize = 64 * 1024 * 1024;
|
attr->memSize = 4 * 1024 * 1024;
|
||||||
attr->cmdDepth = 15;
|
attr->cmdDepth = 16;
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,6 +60,12 @@ u32 vdecOpen(VideoDecoder* data)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (vdec.has_picture) // hack
|
||||||
|
{
|
||||||
|
Sleep(1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!vdec.job.Pop(task))
|
if (!vdec.job.Pop(task))
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
|
@ -76,7 +83,10 @@ u32 vdecOpen(VideoDecoder* data)
|
||||||
|
|
||||||
case vdecEndSeq:
|
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()");
|
ConLog.Warning("vdecEndSeq()");
|
||||||
vdec.is_running = false;
|
vdec.is_running = false;
|
||||||
}
|
}
|
||||||
|
@ -90,6 +100,7 @@ u32 vdecOpen(VideoDecoder* data)
|
||||||
{
|
{
|
||||||
av_new_packet(this, size + FF_INPUT_BUFFER_PADDING_SIZE);
|
av_new_packet(this, size + FF_INPUT_BUFFER_PADDING_SIZE);
|
||||||
memset(data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
|
memset(data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
|
||||||
|
this->size -= FF_INPUT_BUFFER_PADDING_SIZE; // ????????????????????
|
||||||
}
|
}
|
||||||
|
|
||||||
~vdecPacket()
|
~vdecPacket()
|
||||||
|
@ -99,8 +110,13 @@ u32 vdecOpen(VideoDecoder* data)
|
||||||
|
|
||||||
} au(task.size);
|
} au(task.size);
|
||||||
|
|
||||||
au.pts = task.pts;
|
if (task.pts || task.dts)
|
||||||
au.dts = 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)
|
if (task.mode != CELL_VDEC_DEC_MODE_NORMAL)
|
||||||
{
|
{
|
||||||
|
@ -116,6 +132,9 @@ u32 vdecOpen(VideoDecoder* data)
|
||||||
|
|
||||||
int got_picture = 0;
|
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);
|
int decode = avcodec_decode_video2(vdec.ctx, vdec.frame, &got_picture, &au);
|
||||||
if (decode < 0)
|
if (decode < 0)
|
||||||
{
|
{
|
||||||
|
@ -123,7 +142,48 @@ u32 vdecOpen(VideoDecoder* data)
|
||||||
break;
|
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;
|
break;
|
||||||
|
|
||||||
|
@ -137,6 +197,7 @@ u32 vdecOpen(VideoDecoder* data)
|
||||||
case vdecSetFrameRate:
|
case vdecSetFrameRate:
|
||||||
{
|
{
|
||||||
ConLog.Error("TODO: vdecSetFrameRate(%d)", task.frc);
|
ConLog.Error("TODO: vdecSetFrameRate(%d)", task.frc);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
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)
|
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;
|
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;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
#include "Utilities/SQueue.h"
|
#include "Utilities/SQueue.h"
|
||||||
|
|
||||||
|
#define a128(x) ((x + 127) & (~127))
|
||||||
|
|
||||||
// Error Codes
|
// Error Codes
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -341,16 +343,18 @@ struct CellVdecAvcInfo
|
||||||
AVC_transfer_characteristics transfer_characteristics;
|
AVC_transfer_characteristics transfer_characteristics;
|
||||||
AVC_matrix_coefficients matrix_coefficients;
|
AVC_matrix_coefficients matrix_coefficients;
|
||||||
bool timing_info_present_flag;
|
bool timing_info_present_flag;
|
||||||
CellVdecFrameRate frameRateCode;
|
AVC_FrameRateCode frameRateCode; // ???
|
||||||
bool fixed_frame_rate_flag;
|
bool fixed_frame_rate_flag;
|
||||||
bool low_delay_hrd_flag;
|
bool low_delay_hrd_flag;
|
||||||
bool entropy_coding_mode_flag;
|
bool entropy_coding_mode_flag;
|
||||||
be_t<AVC_NulUnitPresentFlags> nalUnitPresentFlags;
|
be_t<u16> nalUnitPresentFlags;
|
||||||
u8 ccDataLength[2];
|
u8 ccDataLength[2];
|
||||||
u8 ccData[2][CELL_VDEC_AVC_CCD_MAX];
|
u8 ccData[2][CELL_VDEC_AVC_CCD_MAX];
|
||||||
be_t<u64> reserved[2];
|
be_t<u64> reserved[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const int sz = sizeof(CellVdecAvcInfo);
|
||||||
|
|
||||||
// DIVX Profile
|
// DIVX Profile
|
||||||
enum DIVX_level : u8
|
enum DIVX_level : u8
|
||||||
{
|
{
|
||||||
|
@ -686,15 +690,21 @@ public:
|
||||||
AVCodec* codec;
|
AVCodec* codec;
|
||||||
AVCodecContext* ctx;
|
AVCodecContext* ctx;
|
||||||
AVFrame* frame;
|
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 profile;
|
||||||
const u32 memAddr;
|
const u32 memAddr;
|
||||||
const u32 memSize;
|
const u32 memSize;
|
||||||
const u32 cbFunc;
|
const u32 cbFunc;
|
||||||
const u32 cbArg;
|
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)
|
: type(type)
|
||||||
, profile(profile)
|
, profile(profile)
|
||||||
, memAddr(addr)
|
, memAddr(addr)
|
||||||
|
@ -703,6 +713,7 @@ public:
|
||||||
, cbArg(arg)
|
, cbArg(arg)
|
||||||
, is_finished(false)
|
, is_finished(false)
|
||||||
, is_running(false)
|
, is_running(false)
|
||||||
|
, has_picture(false)
|
||||||
{
|
{
|
||||||
codec = avcodec_find_decoder(AV_CODEC_ID_H264);
|
codec = avcodec_find_decoder(AV_CODEC_ID_H264);
|
||||||
if (!codec)
|
if (!codec)
|
||||||
|
@ -718,7 +729,9 @@ public:
|
||||||
Emu.Pause();
|
Emu.Pause();
|
||||||
return;
|
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);
|
ConLog.Error("VideoDecoder(): avcodec_open2 failed(%d)", err);
|
||||||
Emu.Pause();
|
Emu.Pause();
|
||||||
|
@ -731,6 +744,8 @@ public:
|
||||||
Emu.Pause();
|
Emu.Pause();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
//memset(&out_data, 0, sizeof(out_data));
|
||||||
|
//memset(&linesize, 0, sizeof(linesize));
|
||||||
}
|
}
|
||||||
|
|
||||||
~VideoDecoder()
|
~VideoDecoder()
|
||||||
|
@ -741,5 +756,6 @@ public:
|
||||||
avcodec_close(ctx);
|
avcodec_close(ctx);
|
||||||
av_free(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)
|
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;
|
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)
|
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());
|
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;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellVpostOpenEx(const mem_ptr_t<CellVpostCfgParam> cfgParam, const mem_ptr_t<CellVpostResourceEx> resource, mem32_t handle)
|
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());
|
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;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellVpostClose(u32 handle)
|
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;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellVpostExec(u32 handle, const u32 inPicBuff_addr, const mem_ptr_t<CellVpostCtrlParam> ctrlParam,
|
int cellVpostExec(u32 handle, const u32 inPicBuff_addr, const mem_ptr_t<CellVpostCtrlParam> ctrlParam,
|
||||||
u32 outPicBuff_addr, mem_ptr_t<CellVpostPictureInfo> picInfo)
|
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());
|
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;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -315,3 +315,14 @@ struct CellVpostPictureInfo
|
||||||
be_t<u32> reserved1;
|
be_t<u32> reserved1;
|
||||||
be_t<u32> reserved2;
|
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);
|
s_tools_mem_bytes.Add(sc_bytes);
|
||||||
|
|
||||||
wxStaticBoxSizer& s_tools_mem_buttons = *new wxStaticBoxSizer(wxHORIZONTAL, this, "Control");
|
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_prev = new wxButton(this, wxID_ANY, "<", wxDefaultPosition, wxSize(21, 21));
|
||||||
wxButton* b_next = 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_fprev);
|
||||||
s_tools_mem_buttons.Add(b_prev);
|
s_tools_mem_buttons.Add(b_prev);
|
||||||
s_tools_mem_buttons.Add(b_next);
|
s_tools_mem_buttons.Add(b_next);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue