mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-21 03:55:32 +00:00
Refactor audio/camera/mic threads
This commit is contained in:
parent
19a64e0e94
commit
1456678316
6 changed files with 88 additions and 126 deletions
|
@ -8,8 +8,6 @@
|
|||
#include "Emu/Audio/AudioThread.h"
|
||||
#include "cellAudio.h"
|
||||
|
||||
#include <thread>
|
||||
|
||||
LOG_CHANNEL(cellAudio);
|
||||
|
||||
template <>
|
||||
|
@ -40,22 +38,7 @@ void fmt_class_string<CellAudioError>::format(std::string& out, u64 arg)
|
|||
});
|
||||
}
|
||||
|
||||
void audio_config::on_init(const std::shared_ptr<void>& _this)
|
||||
{
|
||||
m_buffer.set(vm::alloc(AUDIO_PORT_OFFSET * AUDIO_PORT_COUNT, vm::main));
|
||||
m_indexes.set(vm::alloc(sizeof(u64) * AUDIO_PORT_COUNT, vm::main));
|
||||
|
||||
for (u32 i = 0; i < AUDIO_PORT_COUNT; i++)
|
||||
{
|
||||
ports[i].number = i;
|
||||
ports[i].addr = m_buffer + AUDIO_PORT_OFFSET * i;
|
||||
ports[i].index = m_indexes + i;
|
||||
}
|
||||
|
||||
old_thread::on_init(_this);
|
||||
}
|
||||
|
||||
void audio_config::on_task()
|
||||
std::pair<u32, u32> audio_thread::operator()()
|
||||
{
|
||||
thread_ctrl::set_native_priority(1);
|
||||
|
||||
|
@ -76,11 +59,11 @@ void audio_config::on_task()
|
|||
const auto audio = Emu.GetCallbacks().get_audio();
|
||||
audio->Open(buf8ch, buf_sz);
|
||||
|
||||
while (fxm::check<audio_config>() && !Emu.IsStopped())
|
||||
while (fxm::check<audio_config>() == this && !Emu.IsStopped())
|
||||
{
|
||||
if (Emu.IsPaused())
|
||||
{
|
||||
std::this_thread::sleep_for(1ms); // hack
|
||||
thread_ctrl::wait_for(1000); // hack
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -94,7 +77,7 @@ void audio_config::on_task()
|
|||
const u64 expected_time = m_counter * AUDIO_SAMPLES * 1000000 / 48000;
|
||||
if (expected_time >= time_pos)
|
||||
{
|
||||
std::this_thread::sleep_for(1ms); // hack
|
||||
thread_ctrl::wait_for(1000); // hack
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -342,17 +325,24 @@ void audio_config::on_task()
|
|||
cellAudio.trace("Audio perf: (access=%d, AddData=%d, events=%d, dump=%d)",
|
||||
stamp1 - stamp0, stamp2 - stamp1, stamp3 - stamp2, get_system_time() - stamp3);
|
||||
}
|
||||
|
||||
return {m_buffer.addr(), m_indexes.addr()};
|
||||
}
|
||||
|
||||
error_code cellAudioInit()
|
||||
{
|
||||
cellAudio.warning("cellAudioInit()");
|
||||
|
||||
const auto buf = vm::cast(vm::alloc(AUDIO_PORT_OFFSET * AUDIO_PORT_COUNT, vm::main));
|
||||
const auto ind = vm::cast(vm::alloc(sizeof(u64) * AUDIO_PORT_COUNT, vm::main));
|
||||
|
||||
// Start audio thread
|
||||
const auto g_audio = fxm::make<audio_config>();
|
||||
const auto g_audio = fxm::make<audio_config>("Audio Thread", buf, ind);
|
||||
|
||||
if (!g_audio)
|
||||
{
|
||||
vm::dealloc(buf);
|
||||
vm::dealloc(ind);
|
||||
return CELL_AUDIO_ERROR_ALREADY_INIT;
|
||||
}
|
||||
|
||||
|
@ -371,6 +361,10 @@ error_code cellAudioQuit()
|
|||
return CELL_AUDIO_ERROR_NOT_INIT;
|
||||
}
|
||||
|
||||
// Join and dealloc
|
||||
auto [buf, ind] = g_audio->operator()();
|
||||
vm::dealloc(buf);
|
||||
vm::dealloc(ind);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
#include "Utilities/Thread.h"
|
||||
|
||||
|
||||
|
||||
// Error codes
|
||||
enum CellAudioError : u32
|
||||
{
|
||||
|
@ -85,8 +83,6 @@ enum : u32
|
|||
AUDIO_SAMPLES = CELL_AUDIO_BLOCK_SAMPLES,
|
||||
};
|
||||
|
||||
extern u64 get_system_time();
|
||||
|
||||
enum class audio_port_state : u32
|
||||
{
|
||||
closed,
|
||||
|
@ -96,7 +92,7 @@ enum class audio_port_state : u32
|
|||
|
||||
struct audio_port
|
||||
{
|
||||
atomic_t<audio_port_state> state{ audio_port_state::closed };
|
||||
atomic_t<audio_port_state> state = audio_port_state::closed;
|
||||
|
||||
u32 number;
|
||||
vm::ptr<char> addr{};
|
||||
|
@ -119,36 +115,36 @@ struct audio_port
|
|||
atomic_t<level_set_t> level_set;
|
||||
};
|
||||
|
||||
class audio_config final : public old_thread
|
||||
class audio_thread
|
||||
{
|
||||
void on_task() override;
|
||||
|
||||
std::string get_name() const override { return "Audio Thread"; }
|
||||
|
||||
vm::ptr<char> m_buffer = vm::null;
|
||||
vm::ptr<u64> m_indexes = vm::null;
|
||||
vm::ptr<char> m_buffer;
|
||||
vm::ptr<u64> m_indexes;
|
||||
|
||||
u64 m_counter{};
|
||||
|
||||
public:
|
||||
void on_init(const std::shared_ptr<void>&) override;
|
||||
|
||||
const u64 start_time = get_system_time();
|
||||
|
||||
std::array<audio_port, AUDIO_PORT_COUNT> ports;
|
||||
|
||||
std::vector<u64> keys;
|
||||
|
||||
semaphore<> mutex;
|
||||
shared_mutex mutex;
|
||||
|
||||
audio_config() = default;
|
||||
|
||||
~audio_config()
|
||||
audio_thread(vm::ptr<char> buf, vm::ptr<u64> ind)
|
||||
: m_buffer(buf)
|
||||
, m_indexes(ind)
|
||||
{
|
||||
vm::dealloc_verbose_nothrow(m_buffer.addr());
|
||||
vm::dealloc_verbose_nothrow(m_indexes.addr());
|
||||
for (u32 i = 0; i < AUDIO_PORT_COUNT; i++)
|
||||
{
|
||||
ports[i].number = i;
|
||||
ports[i].addr = m_buffer + AUDIO_PORT_OFFSET * i;
|
||||
ports[i].index = m_indexes + i;
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<u32, u32> operator()();
|
||||
|
||||
audio_port* open_port()
|
||||
{
|
||||
for (u32 i = 0; i < AUDIO_PORT_COUNT; i++)
|
||||
|
@ -162,3 +158,5 @@ public:
|
|||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
using audio_config = named_thread<audio_thread>;
|
||||
|
|
|
@ -7,8 +7,6 @@
|
|||
#include "Emu/Io/PadHandler.h"
|
||||
#include "Emu/System.h"
|
||||
|
||||
#include <thread>
|
||||
|
||||
LOG_CHANNEL(cellCamera);
|
||||
|
||||
// **************
|
||||
|
@ -284,7 +282,7 @@ s32 cellCameraInit()
|
|||
}
|
||||
|
||||
// Start camera thread
|
||||
const auto g_camera = fxm::make<camera_thread>();
|
||||
const auto g_camera = fxm::make<camera_thread>("Camera Thread");
|
||||
|
||||
if (!g_camera)
|
||||
{
|
||||
|
@ -356,6 +354,13 @@ s32 cellCameraEnd()
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
const auto g_camera = fxm::withdraw<camera_thread>();
|
||||
|
||||
if (!g_camera)
|
||||
{
|
||||
return CELL_CAMERA_ERROR_NOT_INIT;
|
||||
}
|
||||
|
||||
// TODO: My tests hinted to this behavior, but I'm not sure, so I'll leave this commented
|
||||
//s32 res = cellCameraClose(0);
|
||||
//if (res != CELL_OK)
|
||||
|
@ -363,11 +368,8 @@ s32 cellCameraEnd()
|
|||
// return res;
|
||||
//}
|
||||
|
||||
if (!fxm::remove<camera_thread>())
|
||||
{
|
||||
return CELL_CAMERA_ERROR_NOT_INIT;
|
||||
}
|
||||
|
||||
// Join thread
|
||||
g_camera->operator()();
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -1154,19 +1156,19 @@ DECLARE(ppu_module_manager::cellCamera)("cellCamera", []()
|
|||
|
||||
// camera_thread members
|
||||
|
||||
void camera_thread::on_task()
|
||||
void camera_context::operator()()
|
||||
{
|
||||
while (fxm::check<camera_thread>() && !Emu.IsStopped())
|
||||
while (fxm::check<camera_thread>() == this && !Emu.IsStopped())
|
||||
{
|
||||
std::chrono::steady_clock::time_point frame_start = std::chrono::steady_clock::now();
|
||||
const u64 frame_start = get_system_time();
|
||||
|
||||
if (Emu.IsPaused())
|
||||
{
|
||||
std::this_thread::sleep_for(1ms); // hack
|
||||
thread_ctrl::wait_for(1000); // hack
|
||||
continue;
|
||||
}
|
||||
|
||||
std::lock_guard lock(mutex_notify_data_map);
|
||||
std::unique_lock lock(mutex_notify_data_map);
|
||||
|
||||
for (auto const& notify_data_entry : notify_data_map)
|
||||
{
|
||||
|
@ -1180,8 +1182,8 @@ void camera_thread::on_task()
|
|||
{
|
||||
if (auto queue = lv2_event_queue::find(key))
|
||||
{
|
||||
u64 data2{ 0 };
|
||||
u64 data3{ 0 };
|
||||
u64 data2 = 0;
|
||||
u64 data3 = 0;
|
||||
|
||||
if (read_mode.load() == CELL_CAMERA_READ_DIRECT)
|
||||
{
|
||||
|
@ -1205,29 +1207,22 @@ void camera_thread::on_task()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const std::chrono::microseconds frame_target_time{ static_cast<u32>(1000000.0 / info.framerate) };
|
||||
lock.unlock();
|
||||
|
||||
std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
|
||||
|
||||
std::chrono::microseconds frame_processing_time = std::chrono::duration_cast<std::chrono::microseconds>(now - frame_start);
|
||||
|
||||
if (frame_processing_time < frame_target_time)
|
||||
for (const u64 frame_target_time = 1000000u / info.framerate;;)
|
||||
{
|
||||
std::chrono::microseconds frame_idle_time = frame_target_time - frame_processing_time;
|
||||
std::this_thread::sleep_for(frame_idle_time);
|
||||
const u64 time_passed = get_system_time() - frame_start;
|
||||
if (time_passed >= frame_target_time)
|
||||
break;
|
||||
|
||||
thread_ctrl::wait_for(frame_target_time - time_passed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void camera_thread::on_init(const std::shared_ptr<void>& _this)
|
||||
{
|
||||
old_thread::on_init(_this);
|
||||
}
|
||||
|
||||
void camera_thread::send_attach_state(bool attached)
|
||||
void camera_context::send_attach_state(bool attached)
|
||||
{
|
||||
std::lock_guard lock(mutex_notify_data_map);
|
||||
|
||||
|
@ -1255,7 +1250,7 @@ void camera_thread::send_attach_state(bool attached)
|
|||
}
|
||||
}
|
||||
|
||||
void camera_thread::set_attr(s32 attrib, u32 arg1, u32 arg2)
|
||||
void camera_context::set_attr(s32 attrib, u32 arg1, u32 arg2)
|
||||
{
|
||||
if (attrib == CELL_CAMERA_READMODE)
|
||||
{
|
||||
|
@ -1271,7 +1266,7 @@ void camera_thread::set_attr(s32 attrib, u32 arg1, u32 arg2)
|
|||
attr[attrib] = {arg1, arg2};
|
||||
}
|
||||
|
||||
void camera_thread::add_queue(u64 key, u64 source, u64 flag)
|
||||
void camera_context::add_queue(u64 key, u64 source, u64 flag)
|
||||
{
|
||||
std::lock_guard lock(mutex);
|
||||
{
|
||||
|
@ -1284,7 +1279,7 @@ void camera_thread::add_queue(u64 key, u64 source, u64 flag)
|
|||
send_attach_state(true);
|
||||
}
|
||||
|
||||
void camera_thread::remove_queue(u64 key)
|
||||
void camera_context::remove_queue(u64 key)
|
||||
{
|
||||
std::lock_guard lock(mutex);
|
||||
{
|
||||
|
|
|
@ -351,21 +351,16 @@ struct CellCameraReadEx
|
|||
vm::bptr<u8> pbuf;
|
||||
};
|
||||
|
||||
class camera_thread final : public old_thread
|
||||
class camera_context
|
||||
{
|
||||
private:
|
||||
struct notify_event_data
|
||||
{
|
||||
u64 source;
|
||||
u64 flag;
|
||||
};
|
||||
|
||||
void on_task() override;
|
||||
|
||||
std::string get_name() const override { return "Camera Thread"; }
|
||||
|
||||
public:
|
||||
void on_init(const std::shared_ptr<void>&) override;
|
||||
void operator()();
|
||||
void send_attach_state(bool attached);
|
||||
void set_attr(s32 attrib, u32 arg1, u32 arg2);
|
||||
|
||||
|
@ -385,11 +380,11 @@ public:
|
|||
|
||||
std::map<u64, notify_event_data> notify_data_map;
|
||||
|
||||
semaphore<> mutex;
|
||||
semaphore<> mutex_notify_data_map;
|
||||
shared_mutex mutex;
|
||||
shared_mutex mutex_notify_data_map;
|
||||
Timer timer;
|
||||
|
||||
atomic_t<u8> read_mode{0};
|
||||
atomic_t<u8> read_mode{CELL_CAMERA_READ_FUNCCALL};
|
||||
atomic_t<bool> is_streaming{false};
|
||||
atomic_t<bool> is_attached{false};
|
||||
atomic_t<bool> is_open{false};
|
||||
|
@ -404,11 +399,10 @@ public:
|
|||
|
||||
lv2_memory_container container;
|
||||
atomic_t<u32> frame_num;
|
||||
|
||||
camera_thread() : read_mode(CELL_CAMERA_READ_FUNCCALL) {}
|
||||
~camera_thread() = default;
|
||||
};
|
||||
|
||||
using camera_thread = named_thread<camera_context>;
|
||||
|
||||
/// Shared data between cellGem and cellCamera
|
||||
struct gem_camera_shared
|
||||
{
|
||||
|
|
|
@ -5,38 +5,24 @@
|
|||
#include "cellMic.h"
|
||||
#include <Emu/IdManager.h>
|
||||
#include <Emu/Cell/lv2/sys_event.h>
|
||||
#include <thread>
|
||||
|
||||
LOG_CHANNEL(cellMic);
|
||||
|
||||
void mic_thread::on_init(const std::shared_ptr<void>& _this)
|
||||
void mic_context::operator()()
|
||||
{
|
||||
old_thread::on_init(_this);
|
||||
}
|
||||
|
||||
void mic_thread::on_task()
|
||||
{
|
||||
while (micInited && !Emu.IsStopped())
|
||||
while (fxm::check<mic_thread>() == this && !Emu.IsStopped())
|
||||
{
|
||||
thread_ctrl::wait_for(1000);
|
||||
|
||||
if (Emu.IsPaused())
|
||||
{
|
||||
std::this_thread::sleep_for(1ms); // hack from cellAudio
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!micOpened || !micStarted)
|
||||
continue;
|
||||
|
||||
// If event queue is not set, then we can't send any events
|
||||
if (eventQueueKey == 0)
|
||||
continue;
|
||||
|
||||
std::this_thread::sleep_for(1s);
|
||||
|
||||
// Make sure the mic thread wasn't stopped while we were sleeping
|
||||
if (!micInited)
|
||||
break;
|
||||
|
||||
auto micQueue = lv2_event_queue::find(eventQueueKey);
|
||||
if (!micQueue)
|
||||
continue;
|
||||
|
||||
micQueue->send(0, CELL_MIC_DATA, 0, 0);
|
||||
}
|
||||
|
@ -47,8 +33,8 @@ void mic_thread::on_task()
|
|||
s32 cellMicInit()
|
||||
{
|
||||
cellMic.notice("cellMicInit()");
|
||||
const auto micThread = fxm::make<mic_thread>();
|
||||
micInited = true;
|
||||
|
||||
const auto micThread = fxm::make<mic_thread>("Mic Thread");
|
||||
if (!micThread)
|
||||
return CELL_MIC_ERROR_ALREADY_INIT;
|
||||
|
||||
|
@ -58,11 +44,13 @@ s32 cellMicInit()
|
|||
s32 cellMicEnd()
|
||||
{
|
||||
cellMic.notice("cellMicEnd()");
|
||||
micInited = false;
|
||||
|
||||
const auto micThread = fxm::withdraw<mic_thread>();
|
||||
if (!micThread)
|
||||
return CELL_MIC_ERROR_NOT_INIT;
|
||||
|
||||
// Join
|
||||
micThread->operator()();
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -479,8 +467,8 @@ s32 cellMicGetDeviceIdentifier()
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
DECLARE(ppu_module_manager::cellMic)
|
||||
("cellMic", []() {
|
||||
DECLARE(ppu_module_manager::cellMic)("cellMic", []()
|
||||
{
|
||||
REG_FUNC(cellMic, cellMicInit);
|
||||
REG_FUNC(cellMic, cellMicEnd);
|
||||
REG_FUNC(cellMic, cellMicOpen);
|
||||
|
|
|
@ -52,15 +52,11 @@ enum CellMicCommand
|
|||
// TODO: generate this from input from an actual microphone
|
||||
const u32 bufferSize = 1;
|
||||
|
||||
bool micInited = false;
|
||||
|
||||
class mic_thread final : public old_thread
|
||||
class mic_context
|
||||
{
|
||||
private:
|
||||
void on_task() override;
|
||||
std::string get_name() const override { return "Mic Thread"; }
|
||||
public:
|
||||
void on_init(const std::shared_ptr<void>&) override;
|
||||
void operator()();
|
||||
|
||||
// Default value of 48000 for no particular reason
|
||||
u32 DspFrequency = 48000; // DSP is the default type
|
||||
u32 rawFrequency = 48000;
|
||||
|
@ -76,9 +72,6 @@ public:
|
|||
f32 signalStateGainControl;
|
||||
f32 signalStateMicSignalLevel; // value is in decibels
|
||||
f32 signalStateSpeakerSignalLevel; // value is in decibels
|
||||
mic_thread() = default;
|
||||
~mic_thread()
|
||||
{
|
||||
micInited = false;
|
||||
}
|
||||
};
|
||||
|
||||
using mic_thread = named_thread<mic_context>;
|
||||
|
|
Loading…
Add table
Reference in a new issue