diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index 9aecea08ec..7ee261d912 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -870,7 +870,7 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, D3D11_MAPPED_SUBRESOURCE map; D3D::context->Map(s_screenshot_texture, 0, D3D11_MAP_READ, 0, &map); - DumpFrameData(reinterpret_cast(map.pData), source_width, source_height, + DumpFrameData(reinterpret_cast(map.pData), source_width, source_height, map.RowPitch, AVIDump::DumpFormat::FORMAT_RGBA); FinishFrameData(); diff --git a/Source/Core/VideoBackends/D3D12/Render.cpp b/Source/Core/VideoBackends/D3D12/Render.cpp index cd402d0ecc..53d6eb3d7f 100644 --- a/Source/Core/VideoBackends/D3D12/Render.cpp +++ b/Source/Core/VideoBackends/D3D12/Render.cpp @@ -848,6 +848,7 @@ void Renderer::SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height CheckHR(s_screenshot_texture->Map(0, &read_range, &screenshot_texture_map)); DumpFrameData(reinterpret_cast(screenshot_texture_map), source_width, source_height, + dst_location.PlacedFootprint.Footprint.RowPitch, AVIDump::DumpFormat::FORMAT_RGBA); FinishFrameData(); diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp index 27aff46e61..4b8b638212 100644 --- a/Source/Core/VideoBackends/OGL/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Render.cpp @@ -1469,7 +1469,7 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, flipped_trc.GetHeight(), GL_RGBA, GL_UNSIGNED_BYTE, image.data()); DumpFrameData(image.data(), flipped_trc.GetWidth(), flipped_trc.GetHeight(), - AVIDump::DumpFormat::FORMAT_RGBA, true); + flipped_trc.GetWidth() * 4, AVIDump::DumpFormat::FORMAT_RGBA, true); FinishFrameData(); } // Finish up the current frame, print some stats diff --git a/Source/Core/VideoBackends/Vulkan/Renderer.cpp b/Source/Core/VideoBackends/Vulkan/Renderer.cpp index c9721927de..f164f132a7 100644 --- a/Source/Core/VideoBackends/Vulkan/Renderer.cpp +++ b/Source/Core/VideoBackends/Vulkan/Renderer.cpp @@ -496,6 +496,7 @@ void Renderer::SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height DumpFrameData(reinterpret_cast(m_screenshot_readback_texture->GetMapPointer()), static_cast(m_screenshot_render_texture->GetWidth()), static_cast(m_screenshot_render_texture->GetHeight()), + static_cast(m_screenshot_readback_texture->GetRowStride()), AVIDump::DumpFormat::FORMAT_RGBA); FinishFrameData(); } diff --git a/Source/Core/VideoCommon/AVIDump.cpp b/Source/Core/VideoCommon/AVIDump.cpp index d31601d545..ab5b99c993 100644 --- a/Source/Core/VideoCommon/AVIDump.cpp +++ b/Source/Core/VideoCommon/AVIDump.cpp @@ -37,7 +37,6 @@ static AVStream* s_stream = nullptr; static AVFrame* s_src_frame = nullptr; static AVFrame* s_scaled_frame = nullptr; static AVPixelFormat s_pix_fmt = AV_PIX_FMT_BGR24; -static int s_bytes_per_pixel; static SwsContext* s_sws_context = nullptr; static int s_width; static int s_height; @@ -52,6 +51,7 @@ static AVIDump::DumpFormat s_current_format; static const u8* s_stored_frame_data; static int s_stored_frame_width; static int s_stored_frame_height; +static int s_stored_frame_stride; static void InitAVCodec() { @@ -68,12 +68,10 @@ bool AVIDump::Start(int w, int h, DumpFormat format) if (format == DumpFormat::FORMAT_BGR) { s_pix_fmt = AV_PIX_FMT_BGR24; - s_bytes_per_pixel = 3; } else { s_pix_fmt = AV_PIX_FMT_RGBA; - s_bytes_per_pixel = 4; } s_current_format = format; @@ -181,18 +179,18 @@ static void PreparePacket(AVPacket* pkt) pkt->size = 0; } -void AVIDump::AddFrame(const u8* data, int width, int height) +void AVIDump::AddFrame(const u8* data, int width, int height, int stride) { // Store current frame data in case frame dumping stops before next frame update, // but make sure that you don't store the last stored frame and check the resolution upon // closing the file or else you store recursion, and dolphins don't like recursion. if (!s_stop_dumping) { - StoreFrameData(data, width, height); + StoreFrameData(data, width, height, stride); CheckResolution(width, height); } s_src_frame->data[0] = const_cast(data); - s_src_frame->linesize[0] = width * s_bytes_per_pixel; + s_src_frame->linesize[0] = stride; s_src_frame->format = s_pix_fmt; s_src_frame->width = s_width; s_src_frame->height = s_height; @@ -267,7 +265,7 @@ void AVIDump::Stop() { s_stop_dumping = true; // Write the last stored frame just in case frame dumping stops before the next frame update - AddFrame(s_stored_frame_data, s_stored_frame_width, s_stored_frame_height); + AddFrame(s_stored_frame_data, s_stored_frame_width, s_stored_frame_height, s_stored_frame_stride); av_write_trailer(s_format_context); CloseFile(); s_file_index = 0; @@ -328,9 +326,10 @@ void AVIDump::CheckResolution(int width, int height) } } -void AVIDump::StoreFrameData(const u8* data, int width, int height) +void AVIDump::StoreFrameData(const u8* data, int width, int height, int stride) { s_stored_frame_data = data; s_stored_frame_width = width; s_stored_frame_height = height; + s_stored_frame_stride = stride; } diff --git a/Source/Core/VideoCommon/AVIDump.h b/Source/Core/VideoCommon/AVIDump.h index 6b0837f789..a3b2ef4bd5 100644 --- a/Source/Core/VideoCommon/AVIDump.h +++ b/Source/Core/VideoCommon/AVIDump.h @@ -12,7 +12,7 @@ private: static bool CreateFile(); static void CloseFile(); static void CheckResolution(int width, int height); - static void StoreFrameData(const u8* data, int width, int height); + static void StoreFrameData(const u8* data, int width, int height, int stride); public: enum class DumpFormat @@ -22,7 +22,7 @@ public: }; static bool Start(int w, int h, DumpFormat format); - static void AddFrame(const u8* data, int width, int height); + static void AddFrame(const u8* data, int width, int height, int stride); static void Stop(); static void DoState(); }; diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp index 6f1a581b6e..e523fd8a67 100644 --- a/Source/Core/VideoCommon/RenderBase.cpp +++ b/Source/Core/VideoCommon/RenderBase.cpp @@ -555,30 +555,20 @@ bool Renderer::IsFrameDumping() return false; } -void Renderer::DumpFrameData(const u8* data, int w, int h, AVIDump::DumpFormat format, +void Renderer::DumpFrameData(const u8* data, int w, int h, int stride, AVIDump::DumpFormat format, bool swap_upside_down) { #if defined(HAVE_LIBAV) || defined(_WIN32) if (w == 0 || h == 0) return; - size_t image_size; - switch (format) - { - case AVIDump::DumpFormat::FORMAT_BGR: - image_size = 3 * w * h; - break; - case AVIDump::DumpFormat::FORMAT_RGBA: - image_size = 4 * w * h; - break; - } - m_last_framedump_width = w; m_last_framedump_height = h; m_last_framedump_format = format; + m_last_framedump_stride = stride; // TODO: Refactor this. Right now it's needed for the implace flipping of the image. - m_frame_data.assign(data, data + image_size); + m_frame_data.assign(data, data + stride * h); if (!m_last_frame_dumped) { @@ -598,7 +588,7 @@ void Renderer::DumpFrameData(const u8* data, int w, int h, AVIDump::DumpFormat f { if (swap_upside_down) FlipImageData(m_frame_data.data(), w, h, 4); - AVIDump::AddFrame(m_frame_data.data(), w, h); + AVIDump::AddFrame(m_frame_data.data(), w, h, stride); } m_last_frame_dumped = true; diff --git a/Source/Core/VideoCommon/RenderBase.h b/Source/Core/VideoCommon/RenderBase.h index 9cb957c986..9a78ce4a4b 100644 --- a/Source/Core/VideoCommon/RenderBase.h +++ b/Source/Core/VideoCommon/RenderBase.h @@ -148,7 +148,7 @@ protected: static void RecordVideoMemory(); bool IsFrameDumping(); - void DumpFrameData(const u8* data, int w, int h, AVIDump::DumpFormat format, + void DumpFrameData(const u8* data, int w, int h, int stride, AVIDump::DumpFormat format, bool swap_upside_down = false); void FinishFrameData(); @@ -194,6 +194,7 @@ private: bool m_last_frame_dumped = false; int m_last_framedump_width = 0; int m_last_framedump_height = 0; + int m_last_framedump_stride = 0; AVIDump::DumpFormat m_last_framedump_format; };