mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 02:32:36 +01:00
Some errors fixed
This commit is contained in:
parent
8b952bf98c
commit
dbdae77780
2
.gitignore
vendored
2
.gitignore
vendored
@ -41,6 +41,8 @@
|
||||
/bin/VertexProgram.txt
|
||||
/bin/BreakPoints.dat
|
||||
/bin/textures
|
||||
/bin/*.lib
|
||||
/bin/*.exp
|
||||
rpcs3/git-version.h
|
||||
|
||||
# Copyrighted files
|
||||
|
@ -117,10 +117,12 @@ thread::thread()
|
||||
}
|
||||
|
||||
void thread::start(std::function<void()> func)
|
||||
{ // got a crash related with strings
|
||||
m_thr = std::thread([this, func]()
|
||||
{
|
||||
std::string name = m_name;
|
||||
|
||||
m_thr = std::thread([func, name]()
|
||||
{
|
||||
NamedThreadBase info(m_name);
|
||||
NamedThreadBase info(name);
|
||||
g_tls_this_thread = &info;
|
||||
|
||||
try
|
||||
@ -130,7 +132,7 @@ void thread::start(std::function<void()> func)
|
||||
catch(...)
|
||||
{
|
||||
ConLog.Error("Crash :(");
|
||||
std::terminate();
|
||||
//std::terminate();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ void dmuxQueryEsAttr(u32 info_addr /* may be 0 */, const mem_ptr_t<CellCodecEsFi
|
||||
const u32 esSpecificInfo_addr, mem_ptr_t<CellDmuxEsAttr> attr)
|
||||
{
|
||||
if (esFilterId->filterIdMajor >= 0xe0)
|
||||
attr->memSize = 0x500000; // 0x45fa49 from ps3
|
||||
attr->memSize = 0x600000; // 0x45fa49 from ps3
|
||||
else
|
||||
attr->memSize = 0x10000; // 0x73d9 from ps3
|
||||
|
||||
@ -40,16 +40,13 @@ u32 dmuxOpen(Demuxer* data)
|
||||
|
||||
DemuxerTask task;
|
||||
DemuxerStream stream;
|
||||
/*
|
||||
ElementaryStream* esAVC[16]; memset(esAVC, 0, sizeof(esAVC));
|
||||
ElementaryStream* esM2V[16]; memset(esM2V, 0, sizeof(esM2V));
|
||||
ElementaryStream* esDATA[16]; memset(esDATA, 0, sizeof(esDATA));
|
||||
ElementaryStream* esATRAX[48]; memset(esATRAX, 0, sizeof(esATRAX));
|
||||
ElementaryStream* esAC3[48]; memset(esAC3, 0, sizeof(esAC3));
|
||||
ElementaryStream* esLPCM[48]; memset(esLPCM, 0, sizeof(esLPCM));
|
||||
*/
|
||||
ElementaryStream* esALL[192]; memset(esALL, 0, sizeof(esALL));
|
||||
ElementaryStream** esAVC = &esALL[0];
|
||||
ElementaryStream** esAVC = &esALL[0]; // AVC (max 16)
|
||||
ElementaryStream** esM2V = &esALL[16]; // MPEG-2 (max 16)
|
||||
ElementaryStream** esDATA = &esALL[32]; // user data (max 16)
|
||||
ElementaryStream** esATX = &esALL[48]; // ATRAC3+ (max 48)
|
||||
ElementaryStream** esAC3 = &esALL[96]; // AC3 (max 48)
|
||||
ElementaryStream** esPCM = &esALL[144]; // LPCM (max 48)
|
||||
|
||||
u32 cb_add = 0;
|
||||
|
||||
@ -124,6 +121,8 @@ u32 dmuxOpen(Demuxer* data)
|
||||
continue;
|
||||
}
|
||||
|
||||
DemuxerStream backup = stream;
|
||||
|
||||
stream.skip(4);
|
||||
stream.get(len);
|
||||
PesHeader pes(stream);
|
||||
@ -136,6 +135,11 @@ u32 dmuxOpen(Demuxer* data)
|
||||
|
||||
if (pes.size && es.hasdata()) // new AU detected
|
||||
{
|
||||
/*if (es.hasunseen())
|
||||
{
|
||||
stream = backup;
|
||||
continue;
|
||||
}*/
|
||||
es.finish(stream);
|
||||
// callback
|
||||
mem_ptr_t<CellDmuxEsMsg> esMsg(a128(dmux.memAddr) + (cb_add ^= 16));
|
||||
@ -149,7 +153,13 @@ u32 dmuxOpen(Demuxer* data)
|
||||
|
||||
if (pes.size)
|
||||
{
|
||||
ConLog.Write("*** AVC AU detected (pts=0x%x, dts=0x%x)", pes.pts, pes.dts);
|
||||
ConLog.Write("*** AVC AU detected (pts=0x%llx, dts=0x%llx)", pes.pts, pes.dts);
|
||||
}
|
||||
|
||||
if (es.isfull())
|
||||
{
|
||||
stream = backup;
|
||||
continue;
|
||||
}
|
||||
|
||||
es.push(stream, len - pes.size - 3, pes);
|
||||
@ -173,6 +183,7 @@ u32 dmuxOpen(Demuxer* data)
|
||||
case 0x1dc: case 0x1dd: case 0x1de: case 0x1df:
|
||||
{
|
||||
// unknown
|
||||
ConLog.Warning("Unknown MPEG stream found");
|
||||
stream.skip(4);
|
||||
stream.get(len);
|
||||
stream.skip(len);
|
||||
|
@ -321,7 +321,7 @@ struct DemuxerStream
|
||||
{
|
||||
if (sizeof(T) > size) return false;
|
||||
|
||||
out = *mem_ptr_t<T>(addr);
|
||||
out = *(T*)Memory.VirtualToRealAddr(addr);
|
||||
addr += sizeof(T);
|
||||
size -= sizeof(T);
|
||||
|
||||
@ -333,7 +333,7 @@ struct DemuxerStream
|
||||
{
|
||||
if (sizeof(T) > size) return false;
|
||||
|
||||
out = *mem_ptr_t<T>(addr);
|
||||
out = *(T*)Memory.VirtualToRealAddr(addr);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -343,13 +343,17 @@ struct DemuxerStream
|
||||
size = size > count ? size - count : 0;
|
||||
}
|
||||
|
||||
u32 get_ts(u8 c)
|
||||
u64 get_ts(u8 c)
|
||||
{
|
||||
u16 v1, v2; get(v1); get(v2);
|
||||
return (((u32) (c & 0x0E)) << 29) | ((v1 >> 1) << 15) | (v2 >> 1);
|
||||
u8 v[4]; get((u32&)v);
|
||||
return
|
||||
(((u64)c & 0x0e) << 29) |
|
||||
(((u64)v[0]) << 21) |
|
||||
(((u64)v[1] & 0x7e) << 15) |
|
||||
(((u64)v[2]) << 7) | ((u64)v[3] >> 1);
|
||||
}
|
||||
|
||||
u32 get_ts()
|
||||
u64 get_ts()
|
||||
{
|
||||
u8 v; get(v);
|
||||
return get_ts(v);
|
||||
@ -358,8 +362,8 @@ struct DemuxerStream
|
||||
|
||||
struct PesHeader
|
||||
{
|
||||
u32 pts;
|
||||
u32 dts;
|
||||
u64 pts;
|
||||
u64 dts;
|
||||
u8 ch;
|
||||
u8 size;
|
||||
|
||||
@ -505,6 +509,11 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
volatile bool hasunseen()
|
||||
{
|
||||
return peek_addr;
|
||||
}
|
||||
|
||||
volatile bool hasdata()
|
||||
{
|
||||
return last_size;
|
||||
@ -532,7 +541,7 @@ public:
|
||||
void finish(DemuxerStream& stream) // not multithread-safe
|
||||
{
|
||||
SMutexLocker lock(mutex);
|
||||
|
||||
//ConLog.Write("es::finish(): peek=0x%x, first=0x%x, last=0x%x, size=0x%x", peek_addr, first_addr, last_addr, last_size);
|
||||
if (!first_addr)
|
||||
{
|
||||
first_addr = last_addr;
|
||||
@ -556,6 +565,7 @@ public:
|
||||
void push(DemuxerStream& stream, u32 size, PesHeader& pes)
|
||||
{
|
||||
SMutexLocker lock(mutex);
|
||||
//ConLog.Write("es::push(): peek=0x%x, first=0x%x, last=0x%x, size=0x%x", peek_addr, first_addr, last_addr, last_size);
|
||||
if (isfull())
|
||||
{
|
||||
ConLog.Error("ElementaryStream::push(): buffer is full");
|
||||
@ -565,7 +575,12 @@ public:
|
||||
|
||||
u32 data_addr = last_addr + 128 + last_size;
|
||||
last_size += size;
|
||||
Memory.Copy(data_addr, stream.addr, size);
|
||||
if (!Memory.Copy(data_addr, stream.addr, size))
|
||||
{
|
||||
ConLog.Error("ElementaryStream::push(): data copying failed");
|
||||
Emu.Pause();
|
||||
return;
|
||||
}
|
||||
stream.skip(size);
|
||||
|
||||
mem_ptr_t<CellDmuxAuInfoEx> info(last_addr);
|
||||
@ -573,10 +588,10 @@ public:
|
||||
info->auSize = last_size;
|
||||
if (pes.size)
|
||||
{
|
||||
info->dts.lower = pes.dts;
|
||||
info->dts.upper = 0;
|
||||
info->pts.lower = pes.pts;
|
||||
info->pts.upper = 0;
|
||||
info->dts.lower = (u32)pes.dts;
|
||||
info->dts.upper = (u32)(pes.dts >> 32);
|
||||
info->pts.lower = (u32)pes.pts;
|
||||
info->pts.upper = (u32)(pes.pts >> 32);
|
||||
info->isRap = false; // TODO: set valid value
|
||||
info->reserved = 0;
|
||||
info->userData = stream.userdata;
|
||||
@ -590,10 +605,10 @@ public:
|
||||
inf->auSize = last_size;
|
||||
if (pes.size)
|
||||
{
|
||||
inf->dtsLower = pes.dts;
|
||||
inf->dtsUpper = 0;
|
||||
inf->ptsLower = pes.pts;
|
||||
inf->ptsUpper = 0;
|
||||
inf->dtsLower = (u32)pes.dts;
|
||||
inf->dtsUpper = (u32)(pes.dts >> 32);
|
||||
inf->ptsLower = (u32)pes.pts;
|
||||
inf->ptsUpper = (u32)(pes.pts >> 32);
|
||||
inf->auMaxSize = 0; // ?????
|
||||
inf->userData = stream.userdata;
|
||||
}
|
||||
@ -607,6 +622,7 @@ public:
|
||||
void release()
|
||||
{
|
||||
SMutexLocker lock(mutex);
|
||||
ConLog.Write("es::release(): peek=0x%x, first=0x%x, last=0x%x, size=0x%x", peek_addr, first_addr, last_addr, last_size);
|
||||
if (!canrelease())
|
||||
{
|
||||
ConLog.Error("ElementaryStream::release(): buffer is empty");
|
||||
@ -634,7 +650,8 @@ public:
|
||||
bool peek(u32& out_data, bool no_ex, u32& out_spec, bool update_index)
|
||||
{
|
||||
SMutexLocker lock(mutex);
|
||||
ConLog.Write("es::peek(): peek_addr=0x%x", peek_addr);
|
||||
/*ConLog.Write("es::peek(%sAu%s): peek=0x%x, first=0x%x, last=0x%x, size=0x%x", wxString(update_index ? "Get" : "Peek").wx_str(),
|
||||
wxString(no_ex ? "" : "Ex").wx_str(), peek_addr, first_addr, last_addr, last_size);*/
|
||||
if (!peek_addr) return false;
|
||||
|
||||
out_data = peek_addr;
|
||||
|
@ -1,81 +1,327 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/SysCalls/SysCalls.h"
|
||||
#include "Emu/SysCalls/SC_FUNC.h"
|
||||
#include "cellVdec.h"
|
||||
#include "cellPamf.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "libavformat\avformat.h"
|
||||
#include "libavcodec\avcodec.h"
|
||||
}
|
||||
|
||||
#include "cellVdec.h"
|
||||
|
||||
void cellVdec_init();
|
||||
Module cellVdec(0x0005, cellVdec_init);
|
||||
|
||||
u32 vdecQueryAttr(CellVdecCodecType type, u32 profile, u32 spec_addr /* may be 0 */, mem_ptr_t<CellVdecAttr> attr)
|
||||
{
|
||||
switch (type) // TODO: check profile levels
|
||||
{
|
||||
case CELL_VDEC_CODEC_TYPE_AVC: cellVdec.Warning("cellVdecQueryAttr: AVC (profile=%d)", profile); break;
|
||||
case CELL_VDEC_CODEC_TYPE_MPEG2: cellVdec.Error("TODO: MPEG2 not supported"); break;
|
||||
case CELL_VDEC_CODEC_TYPE_DIVX: cellVdec.Error("TODO: DIVX not supported"); break;
|
||||
default: return CELL_VDEC_ERROR_ARG;
|
||||
}
|
||||
|
||||
// TODO: check values
|
||||
attr->decoderVerLower = 0x280000; // from dmux
|
||||
attr->decoderVerUpper = 0x260000;
|
||||
attr->memSize = 64 * 1024 * 1024;
|
||||
attr->cmdDepth = 15;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
u32 vdecOpen(VideoDecoder* data)
|
||||
{
|
||||
VideoDecoder& vdec = *data;
|
||||
|
||||
u32 vdec_id = cellVdec.GetNewId(data);
|
||||
|
||||
vdec.id = vdec_id;
|
||||
|
||||
thread t("Video Decoder[" + std::to_string(vdec_id) + "] Thread", [&]()
|
||||
{
|
||||
ConLog.Write("Video Decoder enter()");
|
||||
|
||||
VdecTask task;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (vdec.job.IsEmpty() && vdec.is_running)
|
||||
{
|
||||
// TODO: default task (not needed?)
|
||||
Sleep(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!vdec.job.Pop(task))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
switch (task.type)
|
||||
{
|
||||
case vdecStartSeq:
|
||||
{
|
||||
// TODO: reset data
|
||||
ConLog.Warning("vdecStartSeq()");
|
||||
vdec.is_running = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case vdecEndSeq:
|
||||
{
|
||||
// TODO: send callback
|
||||
ConLog.Warning("vdecEndSeq()");
|
||||
vdec.is_running = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case vdecDecodeAu:
|
||||
{
|
||||
struct vdecPacket : AVPacket
|
||||
{
|
||||
vdecPacket(u32 size)
|
||||
{
|
||||
av_new_packet(this, size + FF_INPUT_BUFFER_PADDING_SIZE);
|
||||
memset(data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
|
||||
}
|
||||
|
||||
~vdecPacket()
|
||||
{
|
||||
av_free_packet(this);
|
||||
}
|
||||
|
||||
} au(task.size);
|
||||
|
||||
au.pts = task.pts;
|
||||
au.dts = task.dts;
|
||||
|
||||
if (task.mode != CELL_VDEC_DEC_MODE_NORMAL)
|
||||
{
|
||||
ConLog.Error("vdecDecodeAu: unsupported decoding mode(%d)", task.mode);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!Memory.CopyToReal(au.data, task.addr, task.size))
|
||||
{
|
||||
ConLog.Error("vdecDecodeAu: AU data accessing failed(addr=0x%x, size=0x%x)", task.addr, task.size);
|
||||
break;
|
||||
}
|
||||
|
||||
int got_picture = 0;
|
||||
|
||||
int decode = avcodec_decode_video2(vdec.ctx, vdec.frame, &got_picture, &au);
|
||||
if (decode < 0)
|
||||
{
|
||||
ConLog.Error("vdecDecodeAu: AU decoding error(%d)", decode);
|
||||
break;
|
||||
}
|
||||
|
||||
ConLog.Write("Frame decoded (%d)", decode);
|
||||
}
|
||||
break;
|
||||
|
||||
case vdecClose:
|
||||
{
|
||||
vdec.is_finished = true;
|
||||
ConLog.Write("Video Decoder exit");
|
||||
return;
|
||||
}
|
||||
|
||||
case vdecSetFrameRate:
|
||||
{
|
||||
ConLog.Error("TODO: vdecSetFrameRate(%d)", task.frc);
|
||||
}
|
||||
|
||||
default:
|
||||
ConLog.Error("Video Decoder error: unknown task(%d)", task.type);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ConLog.Warning("Video Decoder aborted");
|
||||
});
|
||||
|
||||
t.detach();
|
||||
|
||||
return vdec_id;
|
||||
}
|
||||
|
||||
int cellVdecQueryAttr(const mem_ptr_t<CellVdecType> type, mem_ptr_t<CellVdecAttr> attr)
|
||||
{
|
||||
cellVdec.Error("cellVdecQueryAttr(type_addr=0x%x, attr_addr=0x%x)", type.GetAddr(), attr.GetAddr());
|
||||
return CELL_OK;
|
||||
cellVdec.Warning("cellVdecQueryAttr(type_addr=0x%x, attr_addr=0x%x)", type.GetAddr(), attr.GetAddr());
|
||||
|
||||
if (!type.IsGood() || !attr.IsGood())
|
||||
{
|
||||
return CELL_VDEC_ERROR_FATAL;
|
||||
}
|
||||
|
||||
return vdecQueryAttr(type->codecType, type->profileLevel, 0, attr);
|
||||
}
|
||||
|
||||
int cellVdecQueryAttrEx(const mem_ptr_t<CellVdecTypeEx> type, mem_ptr_t<CellVdecAttr> attr)
|
||||
{
|
||||
cellVdec.Error("cellVdecQueryAttrEx(type_addr=0x%x, attr_addr=0x%x)", type.GetAddr(), attr.GetAddr());
|
||||
return CELL_OK;
|
||||
cellVdec.Warning("cellVdecQueryAttrEx(type_addr=0x%x, attr_addr=0x%x)", type.GetAddr(), attr.GetAddr());
|
||||
|
||||
if (!type.IsGood() || !attr.IsGood())
|
||||
{
|
||||
return CELL_VDEC_ERROR_FATAL;
|
||||
}
|
||||
|
||||
return vdecQueryAttr(type->codecType, type->profileLevel, type->codecSpecificInfo_addr, attr);
|
||||
}
|
||||
|
||||
int cellVdecOpen(const mem_ptr_t<CellVdecType> type, const mem_ptr_t<CellVdecResource> res, const mem_ptr_t<CellVdecCb> cb, mem32_t handle)
|
||||
{
|
||||
cellVdec.Error("cellVdecOpen(type_addr=0x%x, res_addr=0x%x, cb_addr=0x%x, handle_addr=0x%x)",
|
||||
cellVdec.Warning("cellVdecOpen(type_addr=0x%x, res_addr=0x%x, cb_addr=0x%x, handle_addr=0x%x)",
|
||||
type.GetAddr(), res.GetAddr(), cb.GetAddr(), handle.GetAddr());
|
||||
|
||||
if (!type.IsGood() || !res.IsGood() || !cb.IsGood() || !handle.IsGood())
|
||||
{
|
||||
return CELL_VDEC_ERROR_FATAL;
|
||||
}
|
||||
|
||||
if (!Memory.IsGoodAddr(res->memAddr, res->memSize) || !Memory.IsGoodAddr(cb->cbFunc))
|
||||
{
|
||||
return CELL_VDEC_ERROR_FATAL;
|
||||
}
|
||||
|
||||
handle = vdecOpen(new VideoDecoder(type->codecType, type->profileLevel, res->memAddr, res->memSize, cb->cbFunc, cb->cbArg));
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellVdecOpenEx(const mem_ptr_t<CellVdecTypeEx> type, const mem_ptr_t<CellVdecResourceEx> res, const mem_ptr_t<CellVdecCb> cb, mem32_t handle)
|
||||
{
|
||||
cellVdec.Error("cellVdecOpenEx(type_addr=0x%x, res_addr=0x%x, cb_addr=0x%x, handle_addr=0x%x)",
|
||||
cellVdec.Warning("cellVdecOpenEx(type_addr=0x%x, res_addr=0x%x, cb_addr=0x%x, handle_addr=0x%x)",
|
||||
type.GetAddr(), res.GetAddr(), cb.GetAddr(), handle.GetAddr());
|
||||
|
||||
if (!type.IsGood() || !res.IsGood() || !cb.IsGood() || !handle.IsGood())
|
||||
{
|
||||
return CELL_VDEC_ERROR_FATAL;
|
||||
}
|
||||
|
||||
if (!Memory.IsGoodAddr(res->memAddr, res->memSize) || !Memory.IsGoodAddr(cb->cbFunc))
|
||||
{
|
||||
return CELL_VDEC_ERROR_FATAL;
|
||||
}
|
||||
|
||||
handle = vdecOpen(new VideoDecoder(type->codecType, type->profileLevel, res->memAddr, res->memSize, cb->cbFunc, cb->cbArg));
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellVdecClose(u32 handle)
|
||||
{
|
||||
cellVdec.Error("cellVdecClose(handle=0x%x)", handle);
|
||||
cellVdec.Warning("cellVdecClose(handle=%d)", handle);
|
||||
|
||||
VideoDecoder* vdec;
|
||||
if (!Emu.GetIdManager().GetIDData(handle, vdec))
|
||||
{
|
||||
return CELL_VDEC_ERROR_ARG;
|
||||
}
|
||||
|
||||
vdec->job.Push(VdecTask(vdecClose));
|
||||
|
||||
while (!vdec->is_finished)
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
ConLog.Warning("cellVdecClose(%d) aborted", handle);
|
||||
break;
|
||||
}
|
||||
Sleep(1);
|
||||
}
|
||||
|
||||
Emu.GetIdManager().RemoveID(handle);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellVdecStartSeq(u32 handle)
|
||||
{
|
||||
cellVdec.Error("cellVdecStartSeq(handle=0x%x)", handle);
|
||||
cellVdec.Log("cellVdecStartSeq(handle=%d)", handle);
|
||||
|
||||
VideoDecoder* vdec;
|
||||
if (!Emu.GetIdManager().GetIDData(handle, vdec))
|
||||
{
|
||||
return CELL_VDEC_ERROR_ARG;
|
||||
}
|
||||
|
||||
vdec->job.Push(VdecTask(vdecStartSeq));
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellVdecEndSeq(u32 handle)
|
||||
{
|
||||
cellVdec.Error("cellVdecEndSeq(handle=0x%x)", handle);
|
||||
cellVdec.Log("cellVdecEndSeq(handle=%d)", handle);
|
||||
|
||||
VideoDecoder* vdec;
|
||||
if (!Emu.GetIdManager().GetIDData(handle, vdec))
|
||||
{
|
||||
return CELL_VDEC_ERROR_ARG;
|
||||
}
|
||||
|
||||
vdec->job.Push(VdecTask(vdecEndSeq));
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellVdecDecodeAu(u32 handle, CellVdecDecodeMode mode, const mem_ptr_t<CellVdecAuInfo> auInfo)
|
||||
{
|
||||
cellVdec.Error("cellVdecDecodeAu(handle=0x%x, mode=0x%x, auInfo_addr=0x%x)", handle, mode, auInfo.GetAddr());
|
||||
cellVdec.Log("cellVdecDecodeAu(handle=%d, mode=0x%x, auInfo_addr=0x%x)", handle, mode, auInfo.GetAddr());
|
||||
|
||||
VideoDecoder* vdec;
|
||||
if (!Emu.GetIdManager().GetIDData(handle, vdec))
|
||||
{
|
||||
return CELL_VDEC_ERROR_ARG;
|
||||
}
|
||||
|
||||
// TODO: check info
|
||||
VdecTask task(vdecDecodeAu);
|
||||
task.mode = mode;
|
||||
task.addr = auInfo->startAddr;
|
||||
task.size = auInfo->size;
|
||||
task.dts = (u64)auInfo->dts.lower | ((u64)auInfo->dts.upper << 32);
|
||||
task.pts = (u64)auInfo->pts.lower | ((u64)auInfo->pts.upper << 32);
|
||||
task.userData = auInfo->userData;
|
||||
task.specData = auInfo->codecSpecificData;
|
||||
|
||||
vdec->job.Push(task);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellVdecGetPicture(u32 handle, const mem_ptr_t<CellVdecPicFormat> format, u32 out_addr)
|
||||
{
|
||||
cellVdec.Error("cellVdecGetPicture(handle=0x%x, format_addr=0x%x, out_addr=0x%x)", handle, format.GetAddr(), out_addr);
|
||||
cellVdec.Error("cellVdecGetPicture(handle=%d, format_addr=0x%x, out_addr=0x%x)", handle, format.GetAddr(), out_addr);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellVdecGetPicItem(u32 handle, const u32 picItem_ptr_addr)
|
||||
{
|
||||
cellVdec.Error("cellVdecGetPicItem(handle=0x%x, picItem_ptr_addr=0x%x)", handle, picItem_ptr_addr);
|
||||
cellVdec.Error("cellVdecGetPicItem(handle=%d, picItem_ptr_addr=0x%x)", handle, picItem_ptr_addr);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellVdecSetFrameRate(u32 handle, CellVdecFrameRate frc)
|
||||
{
|
||||
cellVdec.Error("cellVdecSetFrameRate(handle=0x%x, frc=0x%x)", handle, frc);
|
||||
cellVdec.Log("cellVdecSetFrameRate(handle=%d, frc=0x%x)", handle, frc);
|
||||
|
||||
VideoDecoder* vdec;
|
||||
if (!Emu.GetIdManager().GetIDData(handle, vdec))
|
||||
{
|
||||
return CELL_VDEC_ERROR_ARG;
|
||||
}
|
||||
|
||||
// TODO: check frc value and set frame rate
|
||||
VdecTask task(vdecSetFrameRate);
|
||||
task.frc = frc;
|
||||
|
||||
vdec->job.Push(task);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -92,4 +338,6 @@ void cellVdec_init()
|
||||
cellVdec.AddFunc(0x807c861a, cellVdecGetPicture);
|
||||
cellVdec.AddFunc(0x17c702b9, cellVdecGetPicItem);
|
||||
cellVdec.AddFunc(0xe13ef6fc, cellVdecSetFrameRate);
|
||||
|
||||
avcodec_register_all();
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include "cellPamf.h"
|
||||
|
||||
#include "Utilities/SQueue.h"
|
||||
|
||||
// Error Codes
|
||||
enum
|
||||
@ -30,7 +31,7 @@ enum CellVdecMsgType
|
||||
};
|
||||
|
||||
// Decoder Operation Mode
|
||||
enum CellVdecDecodeMode
|
||||
enum CellVdecDecodeMode : u32
|
||||
{
|
||||
CELL_VDEC_DEC_MODE_NORMAL,
|
||||
CELL_VDEC_DEC_MODE_B_SKIP,
|
||||
@ -164,11 +165,13 @@ struct CellVdecPicFormat
|
||||
u8 alpha;
|
||||
};
|
||||
|
||||
typedef mem_func_ptr_t<void (*)(u32 handle_addr, CellVdecMsgType msgType, int msgData, u32 cbArg_addr)> CellVdecCbMsg;
|
||||
|
||||
// Callback Function Information
|
||||
struct CellVdecCb
|
||||
{
|
||||
be_t<mem_func_ptr_t<void (*)(u32 handle_addr, CellVdecMsgType msgType, int msgData, u32 cbArg_addr)>> cbFunc;
|
||||
be_t<u32> cbArg_addr;
|
||||
be_t<u32> cbFunc;
|
||||
be_t<u32> cbArg;
|
||||
};
|
||||
|
||||
// Max CC Data Length
|
||||
@ -634,4 +637,109 @@ struct CellVdecMpeg2Info
|
||||
u8 ccDataLength[2];
|
||||
u8 ccData[2][128];
|
||||
be_t<u64> reserved[2];
|
||||
};
|
||||
|
||||
/* Video Decoder Thread Classes */
|
||||
|
||||
enum VdecJobType : u32
|
||||
{
|
||||
vdecStartSeq,
|
||||
vdecEndSeq,
|
||||
vdecDecodeAu,
|
||||
vdecSetFrameRate,
|
||||
vdecClose,
|
||||
};
|
||||
|
||||
struct VdecTask
|
||||
{
|
||||
VdecJobType type;
|
||||
union
|
||||
{
|
||||
u32 frc;
|
||||
CellVdecDecodeMode mode;
|
||||
};
|
||||
u32 addr;
|
||||
u32 size;
|
||||
u64 pts;
|
||||
u64 dts;
|
||||
u64 userData;
|
||||
u64 specData;
|
||||
|
||||
VdecTask(VdecJobType type)
|
||||
: type(type)
|
||||
{
|
||||
}
|
||||
|
||||
VdecTask()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class VideoDecoder
|
||||
{
|
||||
public:
|
||||
SQueue<VdecTask> job;
|
||||
u32 id;
|
||||
volatile bool is_running;
|
||||
volatile bool is_finished;
|
||||
|
||||
AVCodec* codec;
|
||||
AVCodecContext* ctx;
|
||||
AVFrame* frame;
|
||||
|
||||
const u32 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)
|
||||
: type(type)
|
||||
, profile(profile)
|
||||
, memAddr(addr)
|
||||
, memSize(size)
|
||||
, cbFunc(func)
|
||||
, cbArg(arg)
|
||||
, is_finished(false)
|
||||
, is_running(false)
|
||||
{
|
||||
codec = avcodec_find_decoder(AV_CODEC_ID_H264);
|
||||
if (!codec)
|
||||
{
|
||||
ConLog.Error("VideoDecoder(): avcodec_find_decoder failed");
|
||||
Emu.Pause();
|
||||
return;
|
||||
}
|
||||
ctx = avcodec_alloc_context3(codec);
|
||||
if (!ctx)
|
||||
{
|
||||
ConLog.Error("VideoDecoder(): avcodec_alloc_context3 failed");
|
||||
Emu.Pause();
|
||||
return;
|
||||
}
|
||||
if (int err = avcodec_open2(ctx, codec, NULL)) // TODO: not multithread safe
|
||||
{
|
||||
ConLog.Error("VideoDecoder(): avcodec_open2 failed(%d)", err);
|
||||
Emu.Pause();
|
||||
return;
|
||||
}
|
||||
frame = av_frame_alloc();
|
||||
if (!frame)
|
||||
{
|
||||
ConLog.Error("VideoDecoder(): av_frame_alloc failed");
|
||||
Emu.Pause();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
~VideoDecoder()
|
||||
{
|
||||
if (frame) av_frame_free(&frame);
|
||||
if (ctx)
|
||||
{
|
||||
avcodec_close(ctx);
|
||||
av_free(ctx);
|
||||
}
|
||||
}
|
||||
};
|
@ -28,7 +28,7 @@ int sys_lwmutex_create(mem_ptr_t<sys_lwmutex_t> lwmutex, mem_ptr_t<sys_lwmutex_a
|
||||
}
|
||||
|
||||
lwmutex->attribute = attr->attr_protocol | attr->attr_recursive;
|
||||
lwmutex->all_info() = 0;
|
||||
lwmutex->all_info() = ~0;
|
||||
lwmutex->mutex.initialize();
|
||||
//lwmutex->waiter = lwmutex->owner.GetOwner();
|
||||
lwmutex->pad = 0;
|
||||
|
@ -65,7 +65,7 @@ struct SleepQueue
|
||||
|
||||
struct sys_lwmutex_t
|
||||
{
|
||||
/* volatile */ SMutexBase<be_t<u32>, 0xffffffff, 0> mutex;
|
||||
/* volatile */ SMutexBase<be_t<u32>, ~0, 0> mutex;
|
||||
/* volatile */ be_t<u32> waiter; // not used
|
||||
u64 &all_info(){return *(reinterpret_cast<u64*>(this));}
|
||||
be_t<u32> attribute;
|
||||
|
@ -136,11 +136,22 @@ void LogWriter::WriteToLog(std::string prefix, std::string value, std::string co
|
||||
if(wxThread::IsMain())
|
||||
#endif
|
||||
{
|
||||
while(LogBuffer.IsBusy()) wxYieldIfNeeded();
|
||||
while(LogBuffer.IsBusy())
|
||||
{
|
||||
// need extra break condition?
|
||||
wxYieldIfNeeded();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while(LogBuffer.IsBusy()) Sleep(1);
|
||||
while (LogBuffer.IsBusy())
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
break;
|
||||
}
|
||||
Sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
//if(LogBuffer.put == LogBuffer.get) LogBuffer.Flush();
|
||||
|
Loading…
Reference in New Issue
Block a user