mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-04 22:11:26 +12:00
cellAdecClose, cellVdecClose fix
This commit is contained in:
parent
18930a43f2
commit
318d06efda
8 changed files with 401 additions and 392 deletions
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "Utilities/SMutex.h"
|
||||
static const volatile bool sq_no_wait = true;
|
||||
|
||||
template<typename T, u32 SQSize = 666>
|
||||
class SQueue
|
||||
|
@ -22,13 +22,13 @@ public:
|
|||
return SQSize;
|
||||
}
|
||||
|
||||
bool Push(const T& data)
|
||||
bool Push(const T& data, const volatile bool* do_exit)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (m_count >= SQSize)
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
if (Emu.IsStopped() || do_exit && *do_exit)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -49,13 +49,13 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
bool Pop(T& data)
|
||||
bool Pop(T& data, const volatile bool* do_exit)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (!m_count)
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
if (Emu.IsStopped() || do_exit && *do_exit)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -101,13 +101,13 @@ public:
|
|||
m_count = 0;
|
||||
}
|
||||
|
||||
T& Peek(u32 pos = 0)
|
||||
T& Peek(const volatile bool* do_exit, u32 pos = 0)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (m_count <= pos)
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
if (Emu.IsStopped() || do_exit && *do_exit)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
@ -126,19 +126,4 @@ public:
|
|||
}
|
||||
return m_data[(m_pos + pos) % SQSize];
|
||||
}
|
||||
|
||||
T& PeekIfExist(u32 pos = 0)
|
||||
{
|
||||
static T def_value;
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
if (m_count <= pos)
|
||||
{
|
||||
return def_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_data[(m_pos + pos) % SQSize];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -28,6 +28,7 @@ AudioDecoder::AudioDecoder(AudioCodecType type, u32 addr, u32 size, vm::ptr<Cell
|
|||
, cbArg(arg)
|
||||
, adecCb(nullptr)
|
||||
, is_running(false)
|
||||
, is_closed(false)
|
||||
, is_finished(false)
|
||||
, just_started(false)
|
||||
, just_finished(false)
|
||||
|
@ -64,14 +65,14 @@ AudioDecoder::AudioDecoder(AudioCodecType type, u32 addr, u32 size, vm::ptr<Cell
|
|||
AudioDecoder::~AudioDecoder()
|
||||
{
|
||||
// TODO: check finalization
|
||||
if (ctx)
|
||||
{
|
||||
for (u32 i = frames.GetCount() - 1; ~i; i--)
|
||||
{
|
||||
AdecFrame& af = frames.Peek(i);
|
||||
AdecFrame& af = frames.Peek(nullptr, i);
|
||||
av_frame_unref(af.data);
|
||||
av_frame_free(&af.data);
|
||||
}
|
||||
if (ctx)
|
||||
{
|
||||
avcodec_close(ctx);
|
||||
avformat_close_input(&fmt);
|
||||
}
|
||||
|
@ -97,15 +98,15 @@ next:
|
|||
{
|
||||
while (!adec.job.GetCountUnsafe())
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
if (Emu.IsStopped() || adec.is_closed)
|
||||
{
|
||||
cellAdec->Warning("adecRawRead(): aborted");
|
||||
if (Emu.IsStopped()) cellAdec->Warning("adecRawRead(): aborted");
|
||||
return 0;
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
|
||||
switch (adec.job.Peek().type)
|
||||
switch (auto jtype = adec.job.Peek(nullptr).type)
|
||||
{
|
||||
case adecEndSeq:
|
||||
case adecClose:
|
||||
|
@ -113,6 +114,7 @@ next:
|
|||
buf_size = adec.reader.size;
|
||||
}
|
||||
break;
|
||||
|
||||
case adecDecodeAu:
|
||||
{
|
||||
memcpy(buf, vm::get_ptr<void>(adec.reader.addr), adec.reader.size);
|
||||
|
@ -123,17 +125,21 @@ next:
|
|||
|
||||
adec.cbFunc.call(*adec.adecCb, adec.id, CELL_ADEC_MSG_TYPE_AUDONE, adec.task.au.auInfo_addr, adec.cbArg);
|
||||
|
||||
adec.job.Pop(adec.task);
|
||||
adec.job.Pop(adec.task, nullptr);
|
||||
|
||||
adec.reader.addr = adec.task.au.addr;
|
||||
adec.reader.size = adec.task.au.size;
|
||||
//LOG_NOTICE(HLE, "Audio AU: size = 0x%x, pts = 0x%llx", adec.task.au.size, adec.task.au.pts);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
cellAdec->Error("adecRawRead(): sequence error (task %d)", adec.job.Peek().type);
|
||||
{
|
||||
cellAdec->Error("adecRawRead(): unknown task (%d)", jtype);
|
||||
Emu.Pause();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
goto next;
|
||||
}
|
||||
|
@ -264,7 +270,7 @@ u32 adecOpen(AudioDecoder* data)
|
|||
|
||||
while (true)
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
if (Emu.IsStopped() || adec.is_closed)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
@ -281,7 +287,7 @@ u32 adecOpen(AudioDecoder* data)
|
|||
continue;
|
||||
}*/
|
||||
|
||||
if (!adec.job.Pop(task))
|
||||
if (!adec.job.Pop(task, &adec.is_closed))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
@ -428,10 +434,10 @@ u32 adecOpen(AudioDecoder* data)
|
|||
|
||||
while (true)
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
if (Emu.IsStopped() || adec.is_closed)
|
||||
{
|
||||
cellAdec->Warning("adecDecodeAu: aborted");
|
||||
return;
|
||||
if (Emu.IsStopped()) cellAdec->Warning("adecDecodeAu: aborted");
|
||||
break;
|
||||
}
|
||||
|
||||
/*if (!adec.ctx) // fake
|
||||
|
@ -534,30 +540,32 @@ u32 adecOpen(AudioDecoder* data)
|
|||
//frame.pts, frame.data->nb_samples, frame.data->channels, frame.data->sample_rate,
|
||||
//av_get_bytes_per_sample((AVSampleFormat)frame.data->format));
|
||||
|
||||
adec.frames.Push(frame);
|
||||
if (adec.frames.Push(frame, &adec.is_closed))
|
||||
{
|
||||
frame.data = nullptr; // to prevent destruction
|
||||
|
||||
adec.cbFunc.call(*adec.adecCb, adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
adec.cbFunc.call(*adec.adecCb, adec.id, CELL_ADEC_MSG_TYPE_AUDONE, task.au.auInfo_addr, adec.cbArg);
|
||||
}
|
||||
break;
|
||||
|
||||
case adecClose:
|
||||
{
|
||||
adec.is_finished = true;
|
||||
cellAdec->Notice("Audio Decoder thread ended");
|
||||
return;
|
||||
}
|
||||
case adecClose: break;
|
||||
|
||||
default:
|
||||
{
|
||||
cellAdec->Error("Audio Decoder thread error: unknown task(%d)", task.type);
|
||||
Emu.Pause();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
adec.is_finished = true;
|
||||
cellAdec->Warning("Audio Decoder thread aborted");
|
||||
if (adec.is_closed) cellAdec->Notice("Audio Decoder thread ended");
|
||||
if (Emu.IsStopped()) cellAdec->Warning("Audio Decoder thread aborted");
|
||||
});
|
||||
|
||||
t.detach();
|
||||
|
@ -639,7 +647,8 @@ int cellAdecClose(u32 handle)
|
|||
return CELL_ADEC_ERROR_ARG;
|
||||
}
|
||||
|
||||
adec->job.Push(AdecTask(adecClose));
|
||||
adec->is_closed = true;
|
||||
adec->job.Push(AdecTask(adecClose), &sq_no_wait);
|
||||
|
||||
while (!adec->is_finished)
|
||||
{
|
||||
|
@ -676,7 +685,7 @@ int cellAdecStartSeq(u32 handle, u32 param_addr)
|
|||
cellAdec->Todo("cellAdecStartSeq(): initialization");
|
||||
}
|
||||
|
||||
adec->job.Push(task);
|
||||
adec->job.Push(task, &adec->is_closed);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -690,7 +699,7 @@ int cellAdecEndSeq(u32 handle)
|
|||
return CELL_ADEC_ERROR_ARG;
|
||||
}
|
||||
|
||||
adec->job.Push(AdecTask(adecEndSeq));
|
||||
adec->job.Push(AdecTask(adecEndSeq), &adec->is_closed);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -711,7 +720,7 @@ int cellAdecDecodeAu(u32 handle, vm::ptr<CellAdecAuInfo> auInfo)
|
|||
task.au.pts = ((u64)auInfo->pts.upper << 32) | (u64)auInfo->pts.lower;
|
||||
task.au.userdata = auInfo->userData;
|
||||
|
||||
adec->job.Push(task);
|
||||
adec->job.Push(task, &adec->is_closed);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -731,7 +740,10 @@ int cellAdecGetPcm(u32 handle, vm::ptr<float> outBuffer)
|
|||
}
|
||||
|
||||
AdecFrame af;
|
||||
adec->frames.Pop(af);
|
||||
if (!adec->frames.Pop(af, &adec->is_closed))
|
||||
{
|
||||
return CELL_ADEC_ERROR_EMPTY;
|
||||
}
|
||||
AVFrame* frame = af.data;
|
||||
|
||||
if (!af.data) // fake: empty data
|
||||
|
@ -773,7 +785,7 @@ int cellAdecGetPcmItem(u32 handle, vm::ptr<u32> pcmItem_ptr)
|
|||
return CELL_ADEC_ERROR_EMPTY;
|
||||
}
|
||||
|
||||
AdecFrame& af = adec->frames.Peek();
|
||||
AdecFrame& af = adec->frames.Peek(nullptr);
|
||||
|
||||
AVFrame* frame = af.data;
|
||||
|
||||
|
|
|
@ -1074,6 +1074,7 @@ public:
|
|||
SQueue<AdecTask> job;
|
||||
u32 id;
|
||||
volatile bool is_running;
|
||||
volatile bool is_closed;
|
||||
volatile bool is_finished;
|
||||
bool just_started;
|
||||
bool just_finished;
|
||||
|
|
|
@ -105,9 +105,9 @@ int cellAudioInit()
|
|||
float* oal_buffer_float = nullptr;
|
||||
|
||||
if (g_is_u16)
|
||||
queue.Pop(oal_buffer);
|
||||
queue.Pop(oal_buffer, nullptr);
|
||||
else
|
||||
queue_float.Pop(oal_buffer_float);
|
||||
queue_float.Pop(oal_buffer_float, nullptr);
|
||||
|
||||
if (g_is_u16)
|
||||
{
|
||||
|
@ -153,7 +153,6 @@ int cellAudioInit()
|
|||
m_config.counter++;
|
||||
|
||||
const u32 oal_pos = m_config.counter % BUFFER_NUM;
|
||||
const u32 oal_pos_float = m_config.counter % BUFFER_NUM;
|
||||
|
||||
if (Emu.IsPaused())
|
||||
{
|
||||
|
@ -350,10 +349,10 @@ int cellAudioInit()
|
|||
_mm_cvtps_epi32(_mm_mul_ps((__m128&)(buf2ch[i + 4]), float2u16)));
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
for (u32 i = 0; i < (sizeof(buf2ch) / sizeof(float)); i++)
|
||||
{
|
||||
oal_buffer_float[oal_pos_float][oal_buffer_offset + i] = buf2ch[i];
|
||||
oal_buffer_float[oal_pos][oal_buffer_offset + i] = buf2ch[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -361,8 +360,8 @@ int cellAudioInit()
|
|||
|
||||
if (first_mix)
|
||||
{
|
||||
memset(&oal_buffer[oal_pos][0], 0, oal_buffer_size * sizeof(s16));
|
||||
memset(&oal_buffer_float[oal_pos_float][0], 0, oal_buffer_size * sizeof(float));
|
||||
if (g_is_u16) memset(&oal_buffer[oal_pos][0], 0, oal_buffer_size * sizeof(s16));
|
||||
else memset(&oal_buffer_float[oal_pos][0], 0, oal_buffer_size * sizeof(float));
|
||||
}
|
||||
oal_buffer_offset += sizeof(buf2ch) / sizeof(float);
|
||||
|
||||
|
@ -371,9 +370,9 @@ int cellAudioInit()
|
|||
if(m_audio_out)
|
||||
{
|
||||
if (g_is_u16)
|
||||
queue.Push(&oal_buffer[oal_pos][0]);
|
||||
queue.Push(&oal_buffer[oal_pos][0], nullptr);
|
||||
|
||||
queue_float.Push(&oal_buffer_float[oal_pos_float][0]);
|
||||
queue_float.Push(&oal_buffer_float[oal_pos][0], nullptr);
|
||||
}
|
||||
|
||||
oal_buffer_offset = 0;
|
||||
|
@ -439,8 +438,8 @@ int cellAudioInit()
|
|||
}
|
||||
cellAudio->Notice("Audio thread ended");
|
||||
abort:
|
||||
queue.Push(nullptr);
|
||||
queue_float.Push(nullptr);
|
||||
queue.Push(nullptr, nullptr);
|
||||
queue_float.Push(nullptr, nullptr);
|
||||
|
||||
if(do_dump)
|
||||
m_dump.Finalize();
|
||||
|
|
|
@ -62,7 +62,7 @@ bool ElementaryStream::is_full()
|
|||
{
|
||||
if (released < put_count)
|
||||
{
|
||||
u32 first = entries.Peek();
|
||||
u32 first = entries.Peek(&dmux->is_closed);
|
||||
if (first >= put)
|
||||
{
|
||||
return (first - put) < GetMaxAU();
|
||||
|
@ -136,9 +136,10 @@ void ElementaryStream::finish(DemuxerStream& stream) // not multithread-safe (or
|
|||
put_count++;
|
||||
//if (fidMajor != 0xbd) LOG_NOTICE(HLE, "<<< es::finish(): peek=0x%x, first=0x%x, put=0x%x, size=0x%x", peek, first, put, size);
|
||||
}
|
||||
if (!entries.Push(addr))
|
||||
if (!entries.Push(addr, &sq_no_wait))
|
||||
{
|
||||
cellDmux->Error("es::finish() aborted (no space)");
|
||||
Emu.Pause();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -196,10 +197,11 @@ bool ElementaryStream::release()
|
|||
if (released >= put_count)
|
||||
{
|
||||
cellDmux->Error("es::release(): buffer is empty");
|
||||
Emu.Pause();
|
||||
return false;
|
||||
}
|
||||
|
||||
u32 addr = entries.Peek();
|
||||
u32 addr = entries.Peek(&dmux->is_closed);
|
||||
|
||||
auto info = vm::ptr<CellDmuxAuInfo>::make(addr);
|
||||
//if (fidMajor != 0xbd) LOG_WARNING(HLE, "es::release(): (%s) size = 0x%x, info = 0x%x, pts = 0x%x",
|
||||
|
@ -208,13 +210,15 @@ bool ElementaryStream::release()
|
|||
if (released >= peek_count)
|
||||
{
|
||||
cellDmux->Error("es::release(): buffer has not been seen yet");
|
||||
Emu.Pause();
|
||||
return false;
|
||||
}
|
||||
|
||||
released++;
|
||||
if (!entries.Pop(addr))
|
||||
if (!entries.Pop(addr, &sq_no_wait))
|
||||
{
|
||||
cellDmux->Error("es::release(): entries.Pop() aborted (no entries found)");
|
||||
Emu.Pause();
|
||||
return false;
|
||||
}
|
||||
//if (fidMajor != 0xbd) LOG_NOTICE(HLE, "<<< es::release(): peek=0x%x, first=0x%x, put=0x%x, size=0x%x", peek, first, put, size);
|
||||
|
@ -235,7 +239,7 @@ bool ElementaryStream::peek(u32& out_data, bool no_ex, u32& out_spec, bool updat
|
|||
return false;
|
||||
}
|
||||
|
||||
u32 addr = entries.Peek(peek_count - released);
|
||||
u32 addr = entries.Peek(&dmux->is_closed, peek_count - released);
|
||||
auto info = vm::ptr<CellDmuxAuInfo>::make(addr);
|
||||
//if (fidMajor != 0xbd) LOG_WARNING(HLE, "es::peek(%sAu(Ex)): (%s) size = 0x%x, info = 0x%x, pts = 0x%x",
|
||||
//wxString(update_index ? "Get" : "Peek").wx_str(),
|
||||
|
@ -325,7 +329,7 @@ u32 dmuxOpen(Demuxer* data)
|
|||
|
||||
while (true)
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
if (Emu.IsStopped() || dmux.is_closed)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
@ -522,6 +526,7 @@ u32 dmuxOpen(Demuxer* data)
|
|||
case USER_DATA_START_CODE:
|
||||
{
|
||||
cellDmux->Error("USER_DATA_START_CODE found");
|
||||
Emu.Pause();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -530,14 +535,12 @@ u32 dmuxOpen(Demuxer* data)
|
|||
// search
|
||||
stream.skip(1);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// wait for task with yielding (if no default work)
|
||||
if (!dmux.job.Pop(task))
|
||||
if (!dmux.job.Pop(task, &dmux.is_closed))
|
||||
{
|
||||
break; // Emu is stopped
|
||||
}
|
||||
|
@ -563,6 +566,7 @@ u32 dmuxOpen(Demuxer* data)
|
|||
if (updates_count != updates_signaled)
|
||||
{
|
||||
cellDmux->Error("dmuxSetStream: stream update inconsistency (input=%d, signaled=%d)", updates_count, updates_signaled);
|
||||
Emu.Pause();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -572,7 +576,7 @@ u32 dmuxOpen(Demuxer* data)
|
|||
//stream.addr, stream.size, stream.discontinuity, stream.userdata);
|
||||
|
||||
dmux.is_running = true;
|
||||
dmux.fbSetStream.Push(task.stream.addr); // feedback
|
||||
dmux.fbSetStream.Push(task.stream.addr, &dmux.is_closed); // feedback
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -588,18 +592,11 @@ u32 dmuxOpen(Demuxer* data)
|
|||
dmux.is_running = false;
|
||||
if (task.type == dmuxResetStreamAndWaitDone)
|
||||
{
|
||||
dmux.fbSetStream.Push(0);
|
||||
dmux.fbSetStream.Push(0, &dmux.is_closed);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case dmuxClose:
|
||||
{
|
||||
dmux.is_finished = true;
|
||||
cellDmux->Notice("Demuxer thread ended");
|
||||
return;
|
||||
}
|
||||
|
||||
case dmuxEnableEs:
|
||||
{
|
||||
ElementaryStream& es = *task.es.es_ptr;
|
||||
|
@ -646,12 +643,6 @@ u32 dmuxOpen(Demuxer* data)
|
|||
}
|
||||
break;
|
||||
|
||||
/*case dmuxReleaseAu:
|
||||
{
|
||||
task.es.es_ptr->release();
|
||||
}
|
||||
break;*/
|
||||
|
||||
case dmuxFlushEs:
|
||||
{
|
||||
ElementaryStream& es = *task.es.es_ptr;
|
||||
|
@ -680,12 +671,20 @@ u32 dmuxOpen(Demuxer* data)
|
|||
}
|
||||
break;
|
||||
|
||||
case dmuxClose: break;
|
||||
|
||||
default:
|
||||
{
|
||||
cellDmux->Error("Demuxer thread error: unknown task(%d)", task.type);
|
||||
Emu.Pause();
|
||||
return;
|
||||
}
|
||||
}
|
||||
cellDmux->Warning("Demuxer thread aborted");
|
||||
}
|
||||
|
||||
dmux.is_finished = true;
|
||||
if (Emu.IsStopped()) cellDmux->Warning("Demuxer thread aborted");
|
||||
if (dmux.is_closed) cellDmux->Notice("Demuxer thread ended");
|
||||
});
|
||||
|
||||
t.detach();
|
||||
|
@ -783,7 +782,8 @@ int cellDmuxClose(u32 demuxerHandle)
|
|||
return CELL_DMUX_ERROR_ARG;
|
||||
}
|
||||
|
||||
dmux->job.Push(DemuxerTask(dmuxClose));
|
||||
dmux->is_closed = true;
|
||||
dmux->job.Push(DemuxerTask(dmuxClose), &sq_no_wait);
|
||||
|
||||
while (!dmux->is_finished)
|
||||
{
|
||||
|
@ -830,10 +830,10 @@ int cellDmuxSetStream(u32 demuxerHandle, const u32 streamAddress, u32 streamSize
|
|||
info.discontinuity = discontinuity;
|
||||
info.userdata = userData;
|
||||
|
||||
dmux->job.Push(task);
|
||||
dmux->job.Push(task, &dmux->is_closed);
|
||||
|
||||
u32 addr;
|
||||
if (!dmux->fbSetStream.Pop(addr))
|
||||
if (!dmux->fbSetStream.Pop(addr, &dmux->is_closed))
|
||||
{
|
||||
cellDmux->Warning("cellDmuxSetStream(%d) aborted (fbSetStream.Pop())", demuxerHandle);
|
||||
return CELL_OK;
|
||||
|
@ -856,7 +856,7 @@ int cellDmuxResetStream(u32 demuxerHandle)
|
|||
return CELL_DMUX_ERROR_ARG;
|
||||
}
|
||||
|
||||
dmux->job.Push(DemuxerTask(dmuxResetStream));
|
||||
dmux->job.Push(DemuxerTask(dmuxResetStream), &dmux->is_closed);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
@ -871,10 +871,10 @@ int cellDmuxResetStreamAndWaitDone(u32 demuxerHandle)
|
|||
return CELL_DMUX_ERROR_ARG;
|
||||
}
|
||||
|
||||
dmux->job.Push(DemuxerTask(dmuxResetStreamAndWaitDone));
|
||||
dmux->job.Push(DemuxerTask(dmuxResetStreamAndWaitDone), &dmux->is_closed);
|
||||
|
||||
u32 addr;
|
||||
if (!dmux->fbSetStream.Pop(addr))
|
||||
if (!dmux->fbSetStream.Pop(addr, &dmux->is_closed))
|
||||
{
|
||||
cellDmux->Warning("cellDmuxResetStreamAndWaitDone(%d) aborted (fbSetStream.Pop())", demuxerHandle);
|
||||
return CELL_OK;
|
||||
|
@ -952,7 +952,7 @@ int cellDmuxEnableEs(u32 demuxerHandle, vm::ptr<const CellCodecEsFilterId> esFil
|
|||
task.es.es = id;
|
||||
task.es.es_ptr = es;
|
||||
|
||||
dmux->job.Push(task);
|
||||
dmux->job.Push(task, &dmux->is_closed);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -970,7 +970,7 @@ int cellDmuxDisableEs(u32 esHandle)
|
|||
task.es.es = esHandle;
|
||||
task.es.es_ptr = es;
|
||||
|
||||
es->dmux->job.Push(task);
|
||||
es->dmux->job.Push(task, &es->dmux->is_closed);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -988,7 +988,7 @@ int cellDmuxResetEs(u32 esHandle)
|
|||
task.es.es = esHandle;
|
||||
task.es.es_ptr = es;
|
||||
|
||||
es->dmux->job.Push(task);
|
||||
es->dmux->job.Push(task, &es->dmux->is_closed);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -1115,7 +1115,7 @@ int cellDmuxFlushEs(u32 esHandle)
|
|||
task.es.es = esHandle;
|
||||
task.es.es_ptr = es;
|
||||
|
||||
es->dmux->job.Push(task);
|
||||
es->dmux->job.Push(task, &es->dmux->is_closed);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -415,12 +415,14 @@ public:
|
|||
const u32 cbArg;
|
||||
u32 id;
|
||||
volatile bool is_finished;
|
||||
volatile bool is_closed;
|
||||
volatile bool is_running;
|
||||
|
||||
PPUThread* dmuxCb;
|
||||
|
||||
Demuxer(u32 addr, u32 size, vm::ptr<CellDmuxCbMsg> func, u32 arg)
|
||||
: is_finished(false)
|
||||
, is_closed(false)
|
||||
, is_running(false)
|
||||
, memAddr(addr)
|
||||
, memSize(size)
|
||||
|
|
|
@ -28,6 +28,7 @@ VideoDecoder::VideoDecoder(CellVdecCodecType type, u32 profile, u32 addr, u32 si
|
|||
, cbFunc(func)
|
||||
, cbArg(arg)
|
||||
, is_finished(false)
|
||||
, is_closed(false)
|
||||
, is_running(false)
|
||||
, just_started(false)
|
||||
, just_finished(false)
|
||||
|
@ -64,14 +65,14 @@ VideoDecoder::VideoDecoder(CellVdecCodecType type, u32 profile, u32 addr, u32 si
|
|||
VideoDecoder::~VideoDecoder()
|
||||
{
|
||||
// TODO: check finalization
|
||||
if (ctx)
|
||||
{
|
||||
for (u32 i = frames.GetCount() - 1; ~i; i--)
|
||||
{
|
||||
VdecFrame& vf = frames.Peek(i);
|
||||
VdecFrame& vf = frames.Peek(nullptr, i);
|
||||
av_frame_unref(vf.data);
|
||||
av_frame_free(&vf.data);
|
||||
}
|
||||
if (ctx)
|
||||
{
|
||||
avcodec_close(ctx);
|
||||
avformat_close_input(&fmt);
|
||||
}
|
||||
|
@ -97,15 +98,15 @@ next:
|
|||
{
|
||||
while (!vdec.job.GetCountUnsafe())
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
if (Emu.IsStopped() || vdec.is_closed)
|
||||
{
|
||||
cellVdec->Warning("vdecRead(): aborted");
|
||||
if (Emu.IsStopped()) cellVdec->Warning("vdecRead(): aborted");
|
||||
return 0;
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
|
||||
switch (vdec.job.Peek().type)
|
||||
switch (auto jtype = vdec.job.Peek(nullptr).type)
|
||||
{
|
||||
case vdecEndSeq:
|
||||
case vdecClose:
|
||||
|
@ -113,6 +114,7 @@ next:
|
|||
buf_size = vdec.reader.size;
|
||||
}
|
||||
break;
|
||||
|
||||
case vdecDecodeAu:
|
||||
{
|
||||
memcpy(buf, vm::get_ptr<void>(vdec.reader.addr), vdec.reader.size);
|
||||
|
@ -123,16 +125,20 @@ next:
|
|||
|
||||
vdec.cbFunc.call(*vdec.vdecCb, vdec.id, CELL_VDEC_MSG_TYPE_AUDONE, CELL_OK, vdec.cbArg);
|
||||
|
||||
vdec.job.Pop(vdec.task);
|
||||
vdec.job.Pop(vdec.task, nullptr);
|
||||
|
||||
vdec.reader.addr = vdec.task.addr;
|
||||
vdec.reader.size = vdec.task.size;
|
||||
//LOG_NOTICE(HLE, "Video AU: size = 0x%x, pts = 0x%llx, dts = 0x%llx", vdec.task.size, vdec.task.pts, vdec.task.dts);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
cellVdec->Error("vdecRead(): sequence error (task %d)", vdec.job.Peek().type);
|
||||
return 0;
|
||||
{
|
||||
cellVdec->Error("vdecRead(): unknown task (%d)", jtype);
|
||||
Emu.Pause();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
goto next;
|
||||
|
@ -199,7 +205,7 @@ u32 vdecOpen(VideoDecoder* data)
|
|||
|
||||
while (true)
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
if (Emu.IsStopped() || vdec.is_closed)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
@ -216,7 +222,7 @@ u32 vdecOpen(VideoDecoder* data)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!vdec.job.Pop(task))
|
||||
if (!vdec.job.Pop(task, &vdec.is_closed))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
@ -358,11 +364,10 @@ u32 vdecOpen(VideoDecoder* data)
|
|||
|
||||
while (true)
|
||||
{
|
||||
if (Emu.IsStopped() || vdec.job.PeekIfExist().type == vdecClose)
|
||||
if (Emu.IsStopped() || vdec.is_closed)
|
||||
{
|
||||
vdec.is_finished = true;
|
||||
cellVdec->Warning("vdecDecodeAu: aborted");
|
||||
return;
|
||||
if (Emu.IsStopped()) cellVdec->Warning("vdecDecodeAu: aborted");
|
||||
break;
|
||||
}
|
||||
|
||||
last_frame = av_read_frame(vdec.fmt, &au) < 0;
|
||||
|
@ -432,37 +437,39 @@ u32 vdecOpen(VideoDecoder* data)
|
|||
|
||||
//LOG_NOTICE(HLE, "got picture (pts=0x%llx, dts=0x%llx)", frame.pts, frame.dts);
|
||||
|
||||
vdec.frames.Push(frame); // !!!!!!!!
|
||||
if (vdec.frames.Push(frame, &vdec.is_closed))
|
||||
{
|
||||
frame.data = nullptr; // to prevent destruction
|
||||
|
||||
vdec.cbFunc.call(*vdec.vdecCb, vdec.id, CELL_VDEC_MSG_TYPE_PICOUT, CELL_OK, vdec.cbArg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vdec.cbFunc.call(*vdec.vdecCb, vdec.id, CELL_VDEC_MSG_TYPE_AUDONE, CELL_OK, vdec.cbArg);
|
||||
}
|
||||
break;
|
||||
|
||||
case vdecClose:
|
||||
{
|
||||
vdec.is_finished = true;
|
||||
cellVdec->Notice("Video Decoder thread ended");
|
||||
return;
|
||||
}
|
||||
|
||||
case vdecSetFrameRate:
|
||||
{
|
||||
cellVdec->Error("TODO: vdecSetFrameRate(%d)", task.frc);
|
||||
Emu.Pause();
|
||||
}
|
||||
break;
|
||||
|
||||
case vdecClose: break;
|
||||
|
||||
default:
|
||||
{
|
||||
cellVdec->Error("Video Decoder thread error: unknown task(%d)", task.type);
|
||||
Emu.Pause();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vdec.is_finished = true;
|
||||
cellVdec->Warning("Video Decoder thread aborted");
|
||||
if (Emu.IsStopped()) cellVdec->Warning("Video Decoder thread aborted");
|
||||
if (vdec.is_closed) cellVdec->Notice("Video Decoder thread ended");
|
||||
});
|
||||
|
||||
t.detach();
|
||||
|
@ -514,7 +521,8 @@ int cellVdecClose(u32 handle)
|
|||
return CELL_VDEC_ERROR_ARG;
|
||||
}
|
||||
|
||||
vdec->job.Push(VdecTask(vdecClose));
|
||||
vdec->is_closed = true;
|
||||
vdec->job.Push(VdecTask(vdecClose), &sq_no_wait);
|
||||
|
||||
while (!vdec->is_finished)
|
||||
{
|
||||
|
@ -541,7 +549,7 @@ int cellVdecStartSeq(u32 handle)
|
|||
return CELL_VDEC_ERROR_ARG;
|
||||
}
|
||||
|
||||
vdec->job.Push(VdecTask(vdecStartSeq));
|
||||
vdec->job.Push(VdecTask(vdecStartSeq), &vdec->is_closed);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -577,7 +585,7 @@ int cellVdecEndSeq(u32 handle)
|
|||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
|
||||
vdec->job.Push(VdecTask(vdecEndSeq));
|
||||
vdec->job.Push(VdecTask(vdecEndSeq), &vdec->is_closed);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -601,7 +609,7 @@ int cellVdecDecodeAu(u32 handle, CellVdecDecodeMode mode, vm::ptr<const CellVdec
|
|||
task.userData = auInfo->userData;
|
||||
task.specData = auInfo->codecSpecificData;
|
||||
|
||||
vdec->job.Push(task);
|
||||
vdec->job.Push(task, &vdec->is_closed);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -638,7 +646,10 @@ int cellVdecGetPicture(u32 handle, vm::ptr<const CellVdecPicFormat> format, vm::
|
|||
|
||||
VdecFrame vf;
|
||||
|
||||
vdec->frames.Pop(vf);
|
||||
if (!vdec->frames.Pop(vf, &vdec->is_closed))
|
||||
{
|
||||
return CELL_VDEC_ERROR_EMPTY;
|
||||
}
|
||||
|
||||
AVFrame& frame = *vf.data;
|
||||
|
||||
|
@ -674,7 +685,7 @@ int cellVdecGetPicItem(u32 handle, vm::ptr<u32> picItem_ptr)
|
|||
return CELL_VDEC_ERROR_EMPTY;
|
||||
}
|
||||
|
||||
VdecFrame& vf = vdec->frames.Peek();
|
||||
VdecFrame& vf = vdec->frames.Peek(nullptr);
|
||||
|
||||
AVFrame& frame = *vf.data;
|
||||
|
||||
|
@ -782,7 +793,7 @@ int cellVdecSetFrameRate(u32 handle, CellVdecFrameRate frc)
|
|||
VdecTask task(vdecSetFrameRate);
|
||||
task.frc = frc;
|
||||
|
||||
vdec->job.Push(task);
|
||||
vdec->job.Push(task, &vdec->is_closed);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -647,7 +647,6 @@ struct CellVdecMpeg2Info
|
|||
|
||||
enum VdecJobType : u32
|
||||
{
|
||||
vdecInvalid,
|
||||
vdecStartSeq,
|
||||
vdecEndSeq,
|
||||
vdecDecodeAu,
|
||||
|
@ -676,7 +675,6 @@ struct VdecTask
|
|||
}
|
||||
|
||||
VdecTask()
|
||||
: type(vdecInvalid)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@ -697,6 +695,7 @@ public:
|
|||
SQueue<VdecTask> job;
|
||||
u32 id;
|
||||
volatile bool is_running;
|
||||
volatile bool is_closed;
|
||||
volatile bool is_finished;
|
||||
bool just_started;
|
||||
bool just_finished;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue