Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions Source/Core/VideoCommon/FrameDumpFFMpeg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ extern "C" {
#include "Core/HW/SystemTimers.h"
#include "Core/HW/VideoInterface.h"
#include "Core/System.h"
#include "Core/CoreTiming.h"

#include "VideoCommon/OnScreenDisplay.h"

Expand Down Expand Up @@ -356,6 +357,10 @@ bool FFMpegFrameDump::IsFirstFrameInCurrentFile() const

void FFMpegFrameDump::AddFrame(const FrameData& frame)
{

auto& system = Core::System::GetInstance();
SystemTimers::SystemTimersManager& systemTimers = system.GetSystemTimers();
CoreTiming::CoreTimingManager& coreTiming = system.GetCoreTiming();
// Are we even dumping?
if (!IsStarted())
return;
Expand All @@ -370,9 +375,12 @@ void FFMpegFrameDump::AddFrame(const FrameData& frame)
const s64 pts = av_rescale_q(
frame.state.ticks - m_context->start_ticks,
// TODO: GetTicksPerSecond is not safe from GPU thread.
AVRational{1, int(Core::System::GetInstance().GetSystemTimers().GetTicksPerSecond())},
AVRational{1, int(systemTimers.GetTicksPerSecond())},
m_context->codec->time_base);

INFO_LOG_FMT(FRAMEDUMP, "Last PTS: {} | PTS: {} | Stream PTS: {}", m_context->last_pts, pts, m_context->scaled_frame->pts);
INFO_LOG_FMT(FRAMEDUMP, "Ticks: {} | Ticks per Second: {}", coreTiming.GetTicks(), systemTimers.GetTicksPerSecond());

if (!IsFirstFrameInCurrentFile())
{
if (pts <= m_context->last_pts)
Expand All @@ -384,7 +392,7 @@ void FFMpegFrameDump::AddFrame(const FrameData& frame)
{
WARN_LOG_FMT(FRAMEDUMP, "PTS delta > 1. Resulting file will have variable frame rate. "
"Subsequent occurrences will not be reported.");
m_context->gave_vfr_warning = true;
// m_context->gave_vfr_warning = true;
}
}

Expand Down
62 changes: 42 additions & 20 deletions Source/Core/VideoCommon/FrameDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,16 @@ static bool DumpFrameToPNG(const FrameData& frame, const std::string& file_name)
Config::Get(Config::GFX_PNG_COMPRESSION_LEVEL));
}

FrameDumper::FrameDumper()
{
m_frame_end_handle =
GetVideoEvents().after_frame_event.Register([this](Core::System&) { FlushFrameDump(); });
}

FrameDumper::~FrameDumper()
{
ShutdownFrameDumping();
}
// FrameDumper::FrameDumper()
// {
// m_frame_end_handle =
// GetVideoEvents().after_frame_event.Register([this](Core::System&) { FlushFrameDump(); });
// }
//
// FrameDumper::~FrameDumper()
// {
// ShutdownFrameDumping();
// }

void FrameDumper::DumpCurrentFrame(const AbstractTexture* src_texture,
const MathUtil::Rectangle<int>& src_rect,
Expand Down Expand Up @@ -68,6 +68,16 @@ void FrameDumper::DumpCurrentFrame(const AbstractTexture* src_texture,
m_frame_dump_readback_texture->GetRect());
m_last_frame_state = m_ffmpeg_dump.FetchState(ticks, frame_number);
m_frame_dump_needs_flush = true;

std::swap(m_frame_dump_readback_texture, m_frame_dump_output_texture);

auto& output = m_frame_dump_output_texture;
output->Flush();

if (output->Map())
{
DumpFrameData(reinterpret_cast<u8*>(output->GetMappedPointer()), output->GetConfig().width, output->GetConfig().height, static_cast<int>(output->GetMappedStride()));
}
}

bool FrameDumper::CheckFrameDumpRenderTexture(u32 target_width, u32 target_height)
Expand Down Expand Up @@ -172,17 +182,20 @@ void FrameDumper::DumpFrameData(const u8* data, int w, int h, int stride)
{
m_frame_dump_data = FrameData{data, w, h, stride, m_last_frame_state};

if (!m_frame_dump_thread_running.IsSet())
if (Config::Get(Config::MAIN_MOVIE_DUMP_FRAMES))
{
if (m_frame_dump_thread.joinable())
m_frame_dump_thread.join();
m_frame_dump_thread_running.Set();
m_frame_dump_thread = std::thread(&FrameDumper::FrameDumpThreadFunc, this);
}
if (!mLastFrameDumped)
{
mIsAVIDumping = m_ffmpeg_dump.Start(w, h, m_last_frame_state.ticks);
}

// Wake worker thread up.
m_frame_dump_start.Set();
m_frame_dump_frame_running = true;
if (mIsAVIDumping)
{
m_ffmpeg_dump.AddFrame(m_frame_dump_data);
}

mLastFrameDumped = true;
}
}

void FrameDumper::FinishFrameData()
Expand Down Expand Up @@ -345,14 +358,23 @@ void FrameDumper::SaveScreenshot(std::string filename)
m_screenshot_request.Set();
}

bool FrameDumper::IsFrameDumping() const
bool FrameDumper::IsFrameDumping()
{
if (m_screenshot_request.IsSet())
return true;

if (Config::Get(Config::MAIN_MOVIE_DUMP_FRAMES))
return true;

if (mIsAVIDumping && mLastFrameDumped)
{
m_ffmpeg_dump.Stop();
mIsAVIDumping = false;
OSD::AddMessage("Stopped dumping frames");
}

mLastFrameDumped = false;

return false;
}

Expand Down
9 changes: 6 additions & 3 deletions Source/Core/VideoCommon/FrameDumper.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ class AbstractFramebuffer;
class FrameDumper
{
public:
FrameDumper();
~FrameDumper();
// FrameDumper();
// ~FrameDumper();

// Ensures all rendered frames are queued for encoding.
void FlushFrameDump();
Expand All @@ -32,11 +32,14 @@ class FrameDumper

void SaveScreenshot(std::string filename);

bool IsFrameDumping() const;
bool IsFrameDumping();
int GetRequiredResolutionLeastCommonMultiple() const;

void DoState(PointerWrap& p);

bool mLastFrameDumped = false;
bool mIsAVIDumping = false;

private:
// NOTE: The methods below are called on the framedumping thread.
void FrameDumpThreadFunc();
Expand Down