From 3f64aaabbd2a07aa2855cd6100974b588ff9b1d6 Mon Sep 17 00:00:00 2001 From: zhupengfei Date: Sat, 26 Jan 2019 22:19:36 +0800 Subject: [PATCH] core: Add video dumper interface The VideoFrame is rotated while copying, to put the pixels in their correct positions (OpenGL seems to return the image in reverted order by default) --- src/core/CMakeLists.txt | 2 ++ src/core/dumping/backend.cpp | 26 ++++++++++++++++ src/core/dumping/backend.h | 59 ++++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 src/core/dumping/backend.cpp create mode 100644 src/core/dumping/backend.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 633c9296b..20172ea64 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -36,6 +36,8 @@ add_library(core STATIC core.h core_timing.cpp core_timing.h + dumping/backend.cpp + dumping/backend.h file_sys/archive_backend.cpp file_sys/archive_backend.h file_sys/archive_extsavedata.cpp diff --git a/src/core/dumping/backend.cpp b/src/core/dumping/backend.cpp new file mode 100644 index 000000000..daf43c744 --- /dev/null +++ b/src/core/dumping/backend.cpp @@ -0,0 +1,26 @@ +// Copyright 2018 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include +#include "core/dumping/backend.h" + +namespace VideoDumper { + +VideoFrame::VideoFrame(std::size_t width_, std::size_t height_, u8* data_) + : width(width_), height(height_), stride(width * 4), data(width * height * 4) { + // While copying, rotate the image to put the pixels in correct order + // (As OpenGL returns pixel data starting from the lowest position) + for (std::size_t i = 0; i < height; i++) { + for (std::size_t j = 0; j < width; j++) { + for (std::size_t k = 0; k < 4; k++) { + data[i * stride + j * 4 + k] = data_[(height - i - 1) * stride + j * 4 + k]; + } + } + } +} + +Backend::~Backend() = default; +NullBackend::~NullBackend() = default; + +} // namespace VideoDumper \ No newline at end of file diff --git a/src/core/dumping/backend.h b/src/core/dumping/backend.h new file mode 100644 index 000000000..c2a4d532a --- /dev/null +++ b/src/core/dumping/backend.h @@ -0,0 +1,59 @@ +// Copyright 2018 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include +#include "audio_core/audio_types.h" +#include "common/common_types.h" +#include "core/frontend/framebuffer_layout.h" + +namespace VideoDumper { +/** + * Frame dump data for a single screen + * data is in RGB888 format, left to right then top to bottom + */ +class VideoFrame { +public: + std::size_t width; + std::size_t height; + u32 stride; + std::vector data; + + VideoFrame(std::size_t width_ = 0, std::size_t height_ = 0, u8* data_ = nullptr); +}; + +class Backend { +public: + virtual ~Backend(); + virtual bool StartDumping(const std::string& path, const std::string& format, + const Layout::FramebufferLayout& layout) = 0; + virtual void AddVideoFrame(const VideoFrame& frame) = 0; + virtual void AddAudioFrame(const AudioCore::StereoFrame16& frame) = 0; + virtual void AddAudioSample(const std::array& sample) = 0; + virtual void StopDumping() = 0; + virtual bool IsDumping() const = 0; + virtual Layout::FramebufferLayout GetLayout() const = 0; +}; + +class NullBackend : public Backend { +public: + ~NullBackend() override; + bool StartDumping(const std::string& /*path*/, const std::string& /*format*/, + const Layout::FramebufferLayout& /*layout*/) override { + return false; + } + void AddVideoFrame(const VideoFrame& /*frame*/) override {} + void AddAudioFrame(const AudioCore::StereoFrame16& /*frame*/) override {} + void AddAudioSample(const std::array& /*sample*/) override {} + void StopDumping() override {} + bool IsDumping() const override { + return false; + } + Layout::FramebufferLayout GetLayout() const override { + return Layout::FramebufferLayout{}; + } +}; +} // namespace VideoDumper