mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-02-06 09:39:55 +00:00
recording: optimize access to video recorder
Use separate locks for audio and video Fix audio mutex usage in cellRec. Removes can_consume_sample, since we don't do any processing between can_consume_sample and present_samples. Use get_system_time for consistency. Move pts reset to set_video_sink. Make start time atomic. Remove frame and sample counts. Use m_active to early out to reduce mutex locks. Do not try to present samples if the recording mode is stopped anyway.
This commit is contained in:
parent
826cdbb507
commit
9e76e14a79
@ -11,6 +11,8 @@
|
||||
|
||||
LOG_CHANNEL(cellAudio);
|
||||
|
||||
extern atomic_t<recording_mode> g_recording_mode;
|
||||
|
||||
extern void lv2_sleep(u64 timeout, ppu_thread* ppu = nullptr);
|
||||
|
||||
vm::gvar<char, AUDIO_PORT_OFFSET * AUDIO_PORT_COUNT> g_audio_buffer;
|
||||
@ -290,8 +292,9 @@ void audio_ringbuffer::commit_data(f32* buf, u32 sample_cnt)
|
||||
m_dump.WriteData(buf, sample_cnt_in * static_cast<u32>(AudioSampleSize::FLOAT));
|
||||
|
||||
// Record audio if enabled
|
||||
if (utils::video_provider& provider = g_fxo->get<utils::video_provider>(); provider.can_consume_sample())
|
||||
if (g_recording_mode != recording_mode::stopped)
|
||||
{
|
||||
utils::video_provider& provider = g_fxo->get<utils::video_provider>();
|
||||
provider.present_samples(reinterpret_cast<u8*>(buf), sample_cnt, static_cast<u32>(cfg.audio_channels));
|
||||
}
|
||||
|
||||
|
@ -176,7 +176,8 @@ public:
|
||||
{
|
||||
cellRec.notice("Stopping video sink. flush=%d", flush);
|
||||
|
||||
std::lock_guard lock(m_mtx);
|
||||
std::lock_guard lock_video(m_video_mtx);
|
||||
std::lock_guard lock_audio(m_audio_mtx);
|
||||
m_flush = flush;
|
||||
m_paused = false;
|
||||
m_frames_to_encode.clear();
|
||||
@ -188,7 +189,8 @@ public:
|
||||
{
|
||||
cellRec.notice("Pausing video sink. flush=%d", flush);
|
||||
|
||||
std::lock_guard lock(m_mtx);
|
||||
std::lock_guard lock_video(m_video_mtx);
|
||||
std::lock_guard lock_audio(m_audio_mtx);
|
||||
m_flush = flush;
|
||||
m_paused = true;
|
||||
}
|
||||
@ -197,14 +199,15 @@ public:
|
||||
{
|
||||
cellRec.notice("Resuming video sink");
|
||||
|
||||
std::lock_guard lock(m_mtx);
|
||||
std::lock_guard lock_video(m_video_mtx);
|
||||
std::lock_guard lock_audio(m_audio_mtx);
|
||||
m_flush = false;
|
||||
m_paused = false;
|
||||
}
|
||||
|
||||
encoder_frame get_frame()
|
||||
{
|
||||
std::lock_guard lock(m_mtx);
|
||||
std::lock_guard lock_video(m_video_mtx);
|
||||
|
||||
if (!m_frames_to_encode.empty())
|
||||
{
|
||||
@ -218,7 +221,7 @@ public:
|
||||
|
||||
encoder_sample get_sample()
|
||||
{
|
||||
std::lock_guard lock(m_mtx);
|
||||
std::lock_guard lock(m_audio_mtx);
|
||||
|
||||
if (!m_samples_to_encode.empty())
|
||||
{
|
||||
|
@ -781,7 +781,8 @@ namespace utils
|
||||
m_thread.reset();
|
||||
}
|
||||
|
||||
std::lock_guard lock(m_mtx);
|
||||
std::lock_guard lock_video(m_video_mtx);
|
||||
std::lock_guard lock_audio(m_audio_mtx);
|
||||
m_frames_to_encode.clear();
|
||||
m_samples_to_encode.clear();
|
||||
has_error = false;
|
||||
@ -1288,17 +1289,17 @@ namespace utils
|
||||
encoder_frame frame_data;
|
||||
bool got_frame = false;
|
||||
{
|
||||
m_mtx.lock();
|
||||
m_video_mtx.lock();
|
||||
|
||||
if (m_frames_to_encode.empty())
|
||||
{
|
||||
m_mtx.unlock();
|
||||
m_video_mtx.unlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
frame_data = std::move(m_frames_to_encode.front());
|
||||
m_frames_to_encode.pop_front();
|
||||
m_mtx.unlock();
|
||||
m_video_mtx.unlock();
|
||||
|
||||
got_frame = true;
|
||||
|
||||
|
@ -45,7 +45,8 @@ namespace utils
|
||||
return false;
|
||||
}
|
||||
|
||||
std::lock_guard lock(m_mutex);
|
||||
std::lock_guard lock_video(m_video_mutex);
|
||||
std::lock_guard lock_audio(m_audio_mutex);
|
||||
|
||||
if (m_video_sink)
|
||||
{
|
||||
@ -65,10 +66,13 @@ namespace utils
|
||||
|
||||
m_type = sink ? type : recording_mode::stopped;
|
||||
m_video_sink = sink;
|
||||
m_active = (m_type != recording_mode::stopped);
|
||||
|
||||
if (m_type == recording_mode::stopped)
|
||||
if (!m_active)
|
||||
{
|
||||
m_active = false;
|
||||
m_last_video_pts_incoming = -1;
|
||||
m_last_audio_pts_incoming = -1;
|
||||
m_start_time_us.store(umax);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -76,7 +80,9 @@ namespace utils
|
||||
|
||||
void video_provider::set_pause_time_us(usz pause_time_us)
|
||||
{
|
||||
std::lock_guard lock(m_mutex);
|
||||
std::lock_guard lock_video(m_video_mutex);
|
||||
std::lock_guard lock_audio(m_audio_mutex);
|
||||
|
||||
m_pause_time_us = pause_time_us;
|
||||
}
|
||||
|
||||
@ -91,20 +97,6 @@ namespace utils
|
||||
if (g_recording_mode == recording_mode::stopped)
|
||||
{
|
||||
m_active = false;
|
||||
return g_recording_mode;
|
||||
}
|
||||
|
||||
if (!m_active.exchange(true))
|
||||
{
|
||||
m_current_encoder_frame = 0;
|
||||
m_current_encoder_sample = 0;
|
||||
m_last_video_pts_incoming = -1;
|
||||
m_last_audio_pts_incoming = -1;
|
||||
}
|
||||
|
||||
if (m_current_encoder_frame == 0 && m_current_encoder_sample == 0)
|
||||
{
|
||||
m_encoder_start = steady_clock::now();
|
||||
}
|
||||
|
||||
return g_recording_mode;
|
||||
@ -112,12 +104,19 @@ namespace utils
|
||||
|
||||
bool video_provider::can_consume_frame()
|
||||
{
|
||||
std::lock_guard lock(m_mutex);
|
||||
if (!m_active)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::lock_guard lock_video(m_video_mutex);
|
||||
|
||||
if (!m_video_sink || !m_video_sink->use_internal_video)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const usz elapsed_us = std::chrono::duration_cast<std::chrono::microseconds>(steady_clock::now() - m_encoder_start).count();
|
||||
const usz elapsed_us = get_system_time() - m_start_time_us;
|
||||
ensure(elapsed_us >= m_pause_time_us);
|
||||
|
||||
const usz timestamp_ms = (elapsed_us - m_pause_time_us) / 1000;
|
||||
@ -127,15 +126,27 @@ namespace utils
|
||||
|
||||
void video_provider::present_frame(std::vector<u8>& data, u32 pitch, u32 width, u32 height, bool is_bgra)
|
||||
{
|
||||
std::lock_guard lock(m_mutex);
|
||||
if (!m_active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard lock_video(m_video_mutex);
|
||||
|
||||
if (check_mode() == recording_mode::stopped)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const u64 current_time_us = get_system_time();
|
||||
|
||||
if (m_start_time_us.compare_and_swap_test(umax, current_time_us))
|
||||
{
|
||||
media_log.notice("video_provider: start time = %d", current_time_us);
|
||||
}
|
||||
|
||||
// Calculate presentation timestamp.
|
||||
const usz elapsed_us = std::chrono::duration_cast<std::chrono::microseconds>(steady_clock::now() - m_encoder_start).count();
|
||||
const usz elapsed_us = current_time_us - m_start_time_us;
|
||||
ensure(elapsed_us >= m_pause_time_us);
|
||||
|
||||
const usz timestamp_ms = (elapsed_us - m_pause_time_us) / 1000;
|
||||
@ -150,41 +161,37 @@ namespace utils
|
||||
if (m_video_sink->add_frame(data, pitch, width, height, is_bgra ? AVPixelFormat::AV_PIX_FMT_BGRA : AVPixelFormat::AV_PIX_FMT_RGBA, timestamp_ms))
|
||||
{
|
||||
m_last_video_pts_incoming = pts;
|
||||
m_current_encoder_frame++;
|
||||
}
|
||||
}
|
||||
|
||||
bool video_provider::can_consume_sample()
|
||||
{
|
||||
std::lock_guard lock(m_mutex);
|
||||
|
||||
if (!m_video_sink || !m_video_sink->use_internal_audio)
|
||||
return false;
|
||||
|
||||
const usz elapsed_us = std::chrono::duration_cast<std::chrono::microseconds>(steady_clock::now() - m_encoder_start).count();
|
||||
ensure(elapsed_us >= m_pause_time_us);
|
||||
|
||||
const usz timestamp_us = elapsed_us - m_pause_time_us;
|
||||
const s64 pts = m_video_sink->get_audio_pts(timestamp_us);
|
||||
return pts > m_last_audio_pts_incoming;
|
||||
}
|
||||
|
||||
void video_provider::present_samples(u8* buf, u32 sample_count, u16 channels)
|
||||
{
|
||||
if (!buf || !sample_count || !channels)
|
||||
if (!buf || !sample_count || !channels || !m_active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard lock(m_mutex);
|
||||
std::lock_guard lock_audio(m_audio_mutex);
|
||||
|
||||
if (!m_video_sink || !m_video_sink->use_internal_audio)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (check_mode() == recording_mode::stopped)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const u64 current_time_us = get_system_time();
|
||||
|
||||
if (m_start_time_us.compare_and_swap_test(umax, current_time_us))
|
||||
{
|
||||
media_log.notice("video_provider: start time = %d", current_time_us);
|
||||
}
|
||||
|
||||
// Calculate presentation timestamp.
|
||||
const usz elapsed_us = std::chrono::duration_cast<std::chrono::microseconds>(steady_clock::now() - m_encoder_start).count();
|
||||
const usz elapsed_us = current_time_us - m_start_time_us;
|
||||
ensure(elapsed_us >= m_pause_time_us);
|
||||
|
||||
const usz timestamp_us = elapsed_us - m_pause_time_us;
|
||||
@ -199,7 +206,6 @@ namespace utils
|
||||
if (m_video_sink->add_audio_samples(buf, sample_count, channels, timestamp_us))
|
||||
{
|
||||
m_last_audio_pts_incoming = pts;
|
||||
m_current_encoder_sample += sample_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,6 @@ namespace utils
|
||||
bool can_consume_frame();
|
||||
void present_frame(std::vector<u8>& data, u32 pitch, u32 width, u32 height, bool is_bgra);
|
||||
|
||||
bool can_consume_sample();
|
||||
void present_samples(u8* buf, u32 sample_count, u16 channels);
|
||||
|
||||
private:
|
||||
@ -31,11 +30,10 @@ namespace utils
|
||||
|
||||
recording_mode m_type = recording_mode::stopped;
|
||||
std::shared_ptr<video_sink> m_video_sink;
|
||||
shared_mutex m_mutex{};
|
||||
shared_mutex m_video_mutex{};
|
||||
shared_mutex m_audio_mutex{};
|
||||
atomic_t<bool> m_active{false};
|
||||
atomic_t<usz> m_current_encoder_frame{0};
|
||||
atomic_t<usz> m_current_encoder_sample{0};
|
||||
steady_clock::time_point m_encoder_start{};
|
||||
atomic_t<usz> m_start_time_us{umax};
|
||||
s64 m_last_video_pts_incoming = -1;
|
||||
s64 m_last_audio_pts_incoming = -1;
|
||||
usz m_pause_time_us = 0;
|
||||
|
@ -24,7 +24,7 @@ namespace utils
|
||||
if (m_flush || m_paused)
|
||||
return false;
|
||||
|
||||
std::lock_guard lock(m_mtx);
|
||||
std::lock_guard lock(m_video_mtx);
|
||||
m_frames_to_encode.emplace_back(timestamp_ms, pitch, width, height, pixel_format, std::move(frame));
|
||||
return true;
|
||||
}
|
||||
@ -102,7 +102,7 @@ namespace utils
|
||||
bool use_internal_video = false; // True if we want to fetch frames from rsx
|
||||
|
||||
protected:
|
||||
shared_mutex m_mtx;
|
||||
shared_mutex m_video_mtx;
|
||||
std::deque<encoder_frame> m_frames_to_encode;
|
||||
shared_mutex m_audio_mtx;
|
||||
std::deque<encoder_sample> m_samples_to_encode;
|
||||
|
Loading…
x
Reference in New Issue
Block a user