AVIDump: Add a struct for the state.

So AddFrame use no global state and can be threaded well.
This commit is contained in:
degasus 2016-11-04 18:19:35 +01:00
parent dad5041737
commit be29090aae
9 changed files with 44 additions and 18 deletions

View File

@ -824,8 +824,9 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight,
D3D11_MAPPED_SUBRESOURCE map; D3D11_MAPPED_SUBRESOURCE map;
D3D::context->Map(s_screenshot_texture, 0, D3D11_MAP_READ, 0, &map); D3D::context->Map(s_screenshot_texture, 0, D3D11_MAP_READ, 0, &map);
AVIDump::Frame state = AVIDump::FetchState(ticks);
DumpFrameData(reinterpret_cast<const u8*>(map.pData), source_width, source_height, map.RowPitch, DumpFrameData(reinterpret_cast<const u8*>(map.pData), source_width, source_height, map.RowPitch,
ticks); state);
FinishFrameData(); FinishFrameData();
D3D::context->Unmap(s_screenshot_texture, 0); D3D::context->Unmap(s_screenshot_texture, 0);

View File

@ -777,8 +777,9 @@ void Renderer::SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height
D3D12_RANGE read_range = {0, dst_location.PlacedFootprint.Footprint.RowPitch * source_height}; D3D12_RANGE read_range = {0, dst_location.PlacedFootprint.Footprint.RowPitch * source_height};
CheckHR(s_screenshot_texture->Map(0, &read_range, &screenshot_texture_map)); CheckHR(s_screenshot_texture->Map(0, &read_range, &screenshot_texture_map));
AVIDump::Frame state = AVIDump::FetchState(ticks);
DumpFrameData(reinterpret_cast<const u8*>(screenshot_texture_map), source_width, source_height, DumpFrameData(reinterpret_cast<const u8*>(screenshot_texture_map), source_width, source_height,
dst_location.PlacedFootprint.Footprint.RowPitch, ticks); dst_location.PlacedFootprint.Footprint.RowPitch, state);
FinishFrameData(); FinishFrameData();
D3D12_RANGE write_range = {}; D3D12_RANGE write_range = {};

View File

@ -1455,8 +1455,9 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight,
glReadPixels(flipped_trc.left, flipped_trc.bottom, flipped_trc.GetWidth(), glReadPixels(flipped_trc.left, flipped_trc.bottom, flipped_trc.GetWidth(),
flipped_trc.GetHeight(), GL_RGBA, GL_UNSIGNED_BYTE, image.data()); flipped_trc.GetHeight(), GL_RGBA, GL_UNSIGNED_BYTE, image.data());
AVIDump::Frame state = AVIDump::FetchState(ticks);
DumpFrameData(image.data(), flipped_trc.GetWidth(), flipped_trc.GetHeight(), DumpFrameData(image.data(), flipped_trc.GetWidth(), flipped_trc.GetHeight(),
flipped_trc.GetWidth() * 4, ticks, true); flipped_trc.GetWidth() * 4, state, true);
FinishFrameData(); FinishFrameData();
} }
// Finish up the current frame, print some stats // Finish up the current frame, print some stats

View File

@ -125,7 +125,8 @@ void SWRenderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight,
// Save screenshot // Save screenshot
if (IsFrameDumping()) if (IsFrameDumping())
{ {
DumpFrameData(GetCurrentColorTexture(), fbWidth, fbHeight, fbWidth * 4, ticks); AVIDump::Frame state = AVIDump::FetchState(ticks);
DumpFrameData(GetCurrentColorTexture(), fbWidth, fbHeight, fbWidth * 4, state);
FinishFrameData(); FinishFrameData();
} }

View File

@ -747,10 +747,11 @@ bool Renderer::DrawFrameDump(const EFBRectangle& rc, u32 xfb_addr,
void Renderer::DumpFrame(u64 ticks) void Renderer::DumpFrame(u64 ticks)
{ {
AVIDump::Frame state = AVIDump::FetchState(ticks);
DumpFrameData(reinterpret_cast<const u8*>(m_frame_dump_readback_texture->GetMapPointer()), DumpFrameData(reinterpret_cast<const u8*>(m_frame_dump_readback_texture->GetMapPointer()),
static_cast<int>(m_frame_dump_render_texture->GetWidth()), static_cast<int>(m_frame_dump_render_texture->GetWidth()),
static_cast<int>(m_frame_dump_render_texture->GetHeight()), static_cast<int>(m_frame_dump_render_texture->GetHeight()),
static_cast<int>(m_frame_dump_readback_texture->GetRowStride()), ticks); static_cast<int>(m_frame_dump_readback_texture->GetRowStride()), state);
FinishFrameData(); FinishFrameData();
} }

View File

@ -166,7 +166,7 @@ static void PreparePacket(AVPacket* pkt)
pkt->size = 0; pkt->size = 0;
} }
void AVIDump::AddFrame(const u8* data, int width, int height, int stride, u64 ticks) void AVIDump::AddFrame(const u8* data, int width, int height, int stride, const Frame& state)
{ {
CheckResolution(width, height); CheckResolution(width, height);
s_src_frame->data[0] = const_cast<u8*>(data); s_src_frame->data[0] = const_cast<u8*>(data);
@ -196,26 +196,25 @@ void AVIDump::AddFrame(const u8* data, int width, int height, int stride, u64 ti
// incorrectly. // incorrectly.
if (!s_last_frame_is_valid) if (!s_last_frame_is_valid)
{ {
s_last_frame = ticks; s_last_frame = state.ticks;
s_last_frame_is_valid = true; s_last_frame_is_valid = true;
} }
if (!s_start_dumping && Movie::GetCurrentFrame() < 1) if (!s_start_dumping && state.first_frame)
{ {
delta = ticks; delta = state.ticks;
last_pts = AV_NOPTS_VALUE; last_pts = AV_NOPTS_VALUE;
s_start_dumping = true; s_start_dumping = true;
} }
else else
{ {
delta = ticks - s_last_frame; delta = state.ticks - s_last_frame;
last_pts = (s_last_pts * s_stream->codec->time_base.den) / SystemTimers::GetTicksPerSecond(); last_pts = (s_last_pts * s_stream->codec->time_base.den) / state.ticks_per_second;
} }
u64 pts_in_ticks = s_last_pts + delta; u64 pts_in_ticks = s_last_pts + delta;
s_scaled_frame->pts = s_scaled_frame->pts = (pts_in_ticks * s_stream->codec->time_base.den) / state.ticks_per_second;
(pts_in_ticks * s_stream->codec->time_base.den) / SystemTimers::GetTicksPerSecond();
if (s_scaled_frame->pts != last_pts) if (s_scaled_frame->pts != last_pts)
{ {
s_last_frame = ticks; s_last_frame = state.ticks;
s_last_pts = pts_in_ticks; s_last_pts = pts_in_ticks;
error = avcodec_encode_video2(s_stream->codec, &pkt, s_scaled_frame, &got_packet); error = avcodec_encode_video2(s_stream->codec, &pkt, s_scaled_frame, &got_packet);
} }
@ -304,3 +303,12 @@ void AVIDump::CheckResolution(int width, int height)
Start(width, height); Start(width, height);
} }
} }
AVIDump::Frame AVIDump::FetchState(u64 ticks)
{
Frame state;
state.ticks = ticks;
state.first_frame = Movie::GetCurrentFrame() < 1;
state.ticks_per_second = SystemTimers::GetTicksPerSecond();
return state;
}

View File

@ -14,8 +14,21 @@ private:
static void CheckResolution(int width, int height); static void CheckResolution(int width, int height);
public: public:
struct Frame
{
u64 ticks = 0;
u32 ticks_per_second = 0;
bool first_frame = false;
};
static bool Start(int w, int h); static bool Start(int w, int h);
static void AddFrame(const u8* data, int width, int height, int stride, u64 ticks); static void AddFrame(const u8* data, int width, int height, int stride, const Frame& state);
static void Stop(); static void Stop();
static void DoState(); static void DoState();
#if defined(HAVE_LIBAV) || defined(_WIN32)
static Frame FetchState(u64 ticks);
#else
static Frame FetchState(u64 ticks) { return {}; }
#endif
}; };

View File

@ -667,7 +667,7 @@ bool Renderer::IsFrameDumping()
return false; return false;
} }
void Renderer::DumpFrameData(const u8* data, int w, int h, int stride, u64 ticks, void Renderer::DumpFrameData(const u8* data, int w, int h, int stride, const AVIDump::Frame& state,
bool swap_upside_down) bool swap_upside_down)
{ {
if (w == 0 || h == 0) if (w == 0 || h == 0)
@ -701,7 +701,7 @@ void Renderer::DumpFrameData(const u8* data, int w, int h, int stride, u64 ticks
} }
if (m_AVI_dumping) if (m_AVI_dumping)
{ {
AVIDump::AddFrame(m_frame_data.data(), w, h, stride, ticks); AVIDump::AddFrame(m_frame_data.data(), w, h, stride, state);
} }
m_last_frame_dumped = true; m_last_frame_dumped = true;

View File

@ -147,7 +147,7 @@ protected:
static void RecordVideoMemory(); static void RecordVideoMemory();
bool IsFrameDumping(); bool IsFrameDumping();
void DumpFrameData(const u8* data, int w, int h, int stride, u64 ticks, void DumpFrameData(const u8* data, int w, int h, int stride, const AVIDump::Frame& state,
bool swap_upside_down = false); bool swap_upside_down = false);
void FinishFrameData(); void FinishFrameData();