mirror of https://github.com/RPCS3/rpcs3.git
Some errors fixed
This commit is contained in:
parent
8b952bf98c
commit
dbdae77780
|
@ -41,6 +41,8 @@
|
||||||
/bin/VertexProgram.txt
|
/bin/VertexProgram.txt
|
||||||
/bin/BreakPoints.dat
|
/bin/BreakPoints.dat
|
||||||
/bin/textures
|
/bin/textures
|
||||||
|
/bin/*.lib
|
||||||
|
/bin/*.exp
|
||||||
rpcs3/git-version.h
|
rpcs3/git-version.h
|
||||||
|
|
||||||
# Copyrighted files
|
# Copyrighted files
|
||||||
|
|
|
@ -117,10 +117,12 @@ thread::thread()
|
||||||
}
|
}
|
||||||
|
|
||||||
void thread::start(std::function<void()> func)
|
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;
|
g_tls_this_thread = &info;
|
||||||
|
|
||||||
try
|
try
|
||||||
|
@ -130,7 +132,7 @@ void thread::start(std::function<void()> func)
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
ConLog.Error("Crash :(");
|
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)
|
const u32 esSpecificInfo_addr, mem_ptr_t<CellDmuxEsAttr> attr)
|
||||||
{
|
{
|
||||||
if (esFilterId->filterIdMajor >= 0xe0)
|
if (esFilterId->filterIdMajor >= 0xe0)
|
||||||
attr->memSize = 0x500000; // 0x45fa49 from ps3
|
attr->memSize = 0x600000; // 0x45fa49 from ps3
|
||||||
else
|
else
|
||||||
attr->memSize = 0x10000; // 0x73d9 from ps3
|
attr->memSize = 0x10000; // 0x73d9 from ps3
|
||||||
|
|
||||||
|
@ -40,16 +40,13 @@ u32 dmuxOpen(Demuxer* data)
|
||||||
|
|
||||||
DemuxerTask task;
|
DemuxerTask task;
|
||||||
DemuxerStream stream;
|
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* 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;
|
u32 cb_add = 0;
|
||||||
|
|
||||||
|
@ -124,6 +121,8 @@ u32 dmuxOpen(Demuxer* data)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DemuxerStream backup = stream;
|
||||||
|
|
||||||
stream.skip(4);
|
stream.skip(4);
|
||||||
stream.get(len);
|
stream.get(len);
|
||||||
PesHeader pes(stream);
|
PesHeader pes(stream);
|
||||||
|
@ -136,6 +135,11 @@ u32 dmuxOpen(Demuxer* data)
|
||||||
|
|
||||||
if (pes.size && es.hasdata()) // new AU detected
|
if (pes.size && es.hasdata()) // new AU detected
|
||||||
{
|
{
|
||||||
|
/*if (es.hasunseen())
|
||||||
|
{
|
||||||
|
stream = backup;
|
||||||
|
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));
|
||||||
|
@ -149,7 +153,13 @@ u32 dmuxOpen(Demuxer* data)
|
||||||
|
|
||||||
if (pes.size)
|
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);
|
es.push(stream, len - pes.size - 3, pes);
|
||||||
|
@ -173,6 +183,7 @@ u32 dmuxOpen(Demuxer* data)
|
||||||
case 0x1dc: case 0x1dd: case 0x1de: case 0x1df:
|
case 0x1dc: case 0x1dd: case 0x1de: case 0x1df:
|
||||||
{
|
{
|
||||||
// unknown
|
// unknown
|
||||||
|
ConLog.Warning("Unknown MPEG stream found");
|
||||||
stream.skip(4);
|
stream.skip(4);
|
||||||
stream.get(len);
|
stream.get(len);
|
||||||
stream.skip(len);
|
stream.skip(len);
|
||||||
|
|
|
@ -321,7 +321,7 @@ struct DemuxerStream
|
||||||
{
|
{
|
||||||
if (sizeof(T) > size) return false;
|
if (sizeof(T) > size) return false;
|
||||||
|
|
||||||
out = *mem_ptr_t<T>(addr);
|
out = *(T*)Memory.VirtualToRealAddr(addr);
|
||||||
addr += sizeof(T);
|
addr += sizeof(T);
|
||||||
size -= sizeof(T);
|
size -= sizeof(T);
|
||||||
|
|
||||||
|
@ -333,7 +333,7 @@ struct DemuxerStream
|
||||||
{
|
{
|
||||||
if (sizeof(T) > size) return false;
|
if (sizeof(T) > size) return false;
|
||||||
|
|
||||||
out = *mem_ptr_t<T>(addr);
|
out = *(T*)Memory.VirtualToRealAddr(addr);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,13 +343,17 @@ struct DemuxerStream
|
||||||
size = size > count ? size - count : 0;
|
size = size > count ? size - count : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 get_ts(u8 c)
|
u64 get_ts(u8 c)
|
||||||
{
|
{
|
||||||
u16 v1, v2; get(v1); get(v2);
|
u8 v[4]; get((u32&)v);
|
||||||
return (((u32) (c & 0x0E)) << 29) | ((v1 >> 1) << 15) | (v2 >> 1);
|
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);
|
u8 v; get(v);
|
||||||
return get_ts(v);
|
return get_ts(v);
|
||||||
|
@ -358,8 +362,8 @@ struct DemuxerStream
|
||||||
|
|
||||||
struct PesHeader
|
struct PesHeader
|
||||||
{
|
{
|
||||||
u32 pts;
|
u64 pts;
|
||||||
u32 dts;
|
u64 dts;
|
||||||
u8 ch;
|
u8 ch;
|
||||||
u8 size;
|
u8 size;
|
||||||
|
|
||||||
|
@ -505,6 +509,11 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
volatile bool hasunseen()
|
||||||
|
{
|
||||||
|
return peek_addr;
|
||||||
|
}
|
||||||
|
|
||||||
volatile bool hasdata()
|
volatile bool hasdata()
|
||||||
{
|
{
|
||||||
return last_size;
|
return last_size;
|
||||||
|
@ -532,7 +541,7 @@ public:
|
||||||
void finish(DemuxerStream& stream) // not multithread-safe
|
void finish(DemuxerStream& stream) // not multithread-safe
|
||||||
{
|
{
|
||||||
SMutexLocker lock(mutex);
|
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)
|
if (!first_addr)
|
||||||
{
|
{
|
||||||
first_addr = last_addr;
|
first_addr = last_addr;
|
||||||
|
@ -556,6 +565,7 @@ public:
|
||||||
void push(DemuxerStream& stream, u32 size, PesHeader& pes)
|
void push(DemuxerStream& stream, u32 size, PesHeader& pes)
|
||||||
{
|
{
|
||||||
SMutexLocker lock(mutex);
|
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())
|
if (isfull())
|
||||||
{
|
{
|
||||||
ConLog.Error("ElementaryStream::push(): buffer is full");
|
ConLog.Error("ElementaryStream::push(): buffer is full");
|
||||||
|
@ -565,7 +575,12 @@ public:
|
||||||
|
|
||||||
u32 data_addr = last_addr + 128 + last_size;
|
u32 data_addr = last_addr + 128 + last_size;
|
||||||
last_size += 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);
|
stream.skip(size);
|
||||||
|
|
||||||
mem_ptr_t<CellDmuxAuInfoEx> info(last_addr);
|
mem_ptr_t<CellDmuxAuInfoEx> info(last_addr);
|
||||||
|
@ -573,10 +588,10 @@ public:
|
||||||
info->auSize = last_size;
|
info->auSize = last_size;
|
||||||
if (pes.size)
|
if (pes.size)
|
||||||
{
|
{
|
||||||
info->dts.lower = pes.dts;
|
info->dts.lower = (u32)pes.dts;
|
||||||
info->dts.upper = 0;
|
info->dts.upper = (u32)(pes.dts >> 32);
|
||||||
info->pts.lower = pes.pts;
|
info->pts.lower = (u32)pes.pts;
|
||||||
info->pts.upper = 0;
|
info->pts.upper = (u32)(pes.pts >> 32);
|
||||||
info->isRap = false; // TODO: set valid value
|
info->isRap = false; // TODO: set valid value
|
||||||
info->reserved = 0;
|
info->reserved = 0;
|
||||||
info->userData = stream.userdata;
|
info->userData = stream.userdata;
|
||||||
|
@ -590,10 +605,10 @@ public:
|
||||||
inf->auSize = last_size;
|
inf->auSize = last_size;
|
||||||
if (pes.size)
|
if (pes.size)
|
||||||
{
|
{
|
||||||
inf->dtsLower = pes.dts;
|
inf->dtsLower = (u32)pes.dts;
|
||||||
inf->dtsUpper = 0;
|
inf->dtsUpper = (u32)(pes.dts >> 32);
|
||||||
inf->ptsLower = pes.pts;
|
inf->ptsLower = (u32)pes.pts;
|
||||||
inf->ptsUpper = 0;
|
inf->ptsUpper = (u32)(pes.pts >> 32);
|
||||||
inf->auMaxSize = 0; // ?????
|
inf->auMaxSize = 0; // ?????
|
||||||
inf->userData = stream.userdata;
|
inf->userData = stream.userdata;
|
||||||
}
|
}
|
||||||
|
@ -607,6 +622,7 @@ public:
|
||||||
void release()
|
void release()
|
||||||
{
|
{
|
||||||
SMutexLocker lock(mutex);
|
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())
|
if (!canrelease())
|
||||||
{
|
{
|
||||||
ConLog.Error("ElementaryStream::release(): buffer is empty");
|
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)
|
bool peek(u32& out_data, bool no_ex, u32& out_spec, bool update_index)
|
||||||
{
|
{
|
||||||
SMutexLocker lock(mutex);
|
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;
|
if (!peek_addr) return false;
|
||||||
|
|
||||||
out_data = peek_addr;
|
out_data = peek_addr;
|
||||||
|
|
|
@ -1,81 +1,327 @@
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "Emu/SysCalls/SysCalls.h"
|
#include "Emu/SysCalls/SysCalls.h"
|
||||||
#include "Emu/SysCalls/SC_FUNC.h"
|
#include "Emu/SysCalls/SC_FUNC.h"
|
||||||
#include "cellVdec.h"
|
#include "cellPamf.h"
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
#include "libavformat\avformat.h"
|
#include "libavcodec\avcodec.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "cellVdec.h"
|
||||||
|
|
||||||
void cellVdec_init();
|
void cellVdec_init();
|
||||||
Module cellVdec(0x0005, 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)
|
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());
|
cellVdec.Warning("cellVdecQueryAttr(type_addr=0x%x, attr_addr=0x%x)", type.GetAddr(), attr.GetAddr());
|
||||||
return CELL_OK;
|
|
||||||
|
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)
|
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());
|
cellVdec.Warning("cellVdecQueryAttrEx(type_addr=0x%x, attr_addr=0x%x)", type.GetAddr(), attr.GetAddr());
|
||||||
return CELL_OK;
|
|
||||||
|
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)
|
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());
|
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;
|
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)
|
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());
|
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;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellVdecClose(u32 handle)
|
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;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellVdecStartSeq(u32 handle)
|
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;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellVdecEndSeq(u32 handle)
|
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;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellVdecDecodeAu(u32 handle, CellVdecDecodeMode mode, const mem_ptr_t<CellVdecAuInfo> auInfo)
|
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;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
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=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;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellVdecGetPicItem(u32 handle, const u32 picItem_ptr_addr)
|
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;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellVdecSetFrameRate(u32 handle, CellVdecFrameRate frc)
|
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;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,4 +338,6 @@ void cellVdec_init()
|
||||||
cellVdec.AddFunc(0x807c861a, cellVdecGetPicture);
|
cellVdec.AddFunc(0x807c861a, cellVdecGetPicture);
|
||||||
cellVdec.AddFunc(0x17c702b9, cellVdecGetPicItem);
|
cellVdec.AddFunc(0x17c702b9, cellVdecGetPicItem);
|
||||||
cellVdec.AddFunc(0xe13ef6fc, cellVdecSetFrameRate);
|
cellVdec.AddFunc(0xe13ef6fc, cellVdecSetFrameRate);
|
||||||
|
|
||||||
|
avcodec_register_all();
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "cellPamf.h"
|
|
||||||
|
#include "Utilities/SQueue.h"
|
||||||
|
|
||||||
// Error Codes
|
// Error Codes
|
||||||
enum
|
enum
|
||||||
|
@ -30,7 +31,7 @@ enum CellVdecMsgType
|
||||||
};
|
};
|
||||||
|
|
||||||
// Decoder Operation Mode
|
// Decoder Operation Mode
|
||||||
enum CellVdecDecodeMode
|
enum CellVdecDecodeMode : u32
|
||||||
{
|
{
|
||||||
CELL_VDEC_DEC_MODE_NORMAL,
|
CELL_VDEC_DEC_MODE_NORMAL,
|
||||||
CELL_VDEC_DEC_MODE_B_SKIP,
|
CELL_VDEC_DEC_MODE_B_SKIP,
|
||||||
|
@ -164,11 +165,13 @@ struct CellVdecPicFormat
|
||||||
u8 alpha;
|
u8 alpha;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef mem_func_ptr_t<void (*)(u32 handle_addr, CellVdecMsgType msgType, int msgData, u32 cbArg_addr)> CellVdecCbMsg;
|
||||||
|
|
||||||
// Callback Function Information
|
// Callback Function Information
|
||||||
struct CellVdecCb
|
struct CellVdecCb
|
||||||
{
|
{
|
||||||
be_t<mem_func_ptr_t<void (*)(u32 handle_addr, CellVdecMsgType msgType, int msgData, u32 cbArg_addr)>> cbFunc;
|
be_t<u32> cbFunc;
|
||||||
be_t<u32> cbArg_addr;
|
be_t<u32> cbArg;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Max CC Data Length
|
// Max CC Data Length
|
||||||
|
@ -634,4 +637,109 @@ struct CellVdecMpeg2Info
|
||||||
u8 ccDataLength[2];
|
u8 ccDataLength[2];
|
||||||
u8 ccData[2][128];
|
u8 ccData[2][128];
|
||||||
be_t<u64> reserved[2];
|
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->attribute = attr->attr_protocol | attr->attr_recursive;
|
||||||
lwmutex->all_info() = 0;
|
lwmutex->all_info() = ~0;
|
||||||
lwmutex->mutex.initialize();
|
lwmutex->mutex.initialize();
|
||||||
//lwmutex->waiter = lwmutex->owner.GetOwner();
|
//lwmutex->waiter = lwmutex->owner.GetOwner();
|
||||||
lwmutex->pad = 0;
|
lwmutex->pad = 0;
|
||||||
|
|
|
@ -65,7 +65,7 @@ struct SleepQueue
|
||||||
|
|
||||||
struct sys_lwmutex_t
|
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
|
/* volatile */ be_t<u32> waiter; // not used
|
||||||
u64 &all_info(){return *(reinterpret_cast<u64*>(this));}
|
u64 &all_info(){return *(reinterpret_cast<u64*>(this));}
|
||||||
be_t<u32> attribute;
|
be_t<u32> attribute;
|
||||||
|
|
|
@ -136,11 +136,22 @@ void LogWriter::WriteToLog(std::string prefix, std::string value, std::string co
|
||||||
if(wxThread::IsMain())
|
if(wxThread::IsMain())
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
while(LogBuffer.IsBusy()) wxYieldIfNeeded();
|
while(LogBuffer.IsBusy())
|
||||||
|
{
|
||||||
|
// need extra break condition?
|
||||||
|
wxYieldIfNeeded();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
while(LogBuffer.IsBusy()) Sleep(1);
|
while (LogBuffer.IsBusy())
|
||||||
|
{
|
||||||
|
if (Emu.IsStopped())
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Sleep(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//if(LogBuffer.put == LogBuffer.get) LogBuffer.Flush();
|
//if(LogBuffer.put == LogBuffer.get) LogBuffer.Flush();
|
||||||
|
|
Loading…
Reference in New Issue