Revive: dumping/ffmpeg_backend: Various fixes (#6528)

* dumping/ffmpeg_backend: Add FPS filter

So that the recorded video can be at 60FPS (which is supported by most encoders) while still maintaining correct speed.

* dumping/ffmpeg_backend: Add HW context support

Required for some HW acceled encoders. Not tested as my devices don't seem to require this.

* CMake: Copy avfilter dll for MSVC

* CMakeLists: Require FFmpeg 4.0

* ffmpeg: Fix dumper compile error on MSVC.

* ffmpeg: Address review comments.

---------

Co-authored-by: zhupengfei <zhupf321@gmail.com>
This commit is contained in:
Steveice10
2023-05-16 02:28:21 -07:00
committed by GitHub
parent 0768bd8ce0
commit b89f5278ac
5 changed files with 289 additions and 49 deletions

View File

@@ -19,10 +19,10 @@
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavfilter/avfilter.h>
#include <libavformat/avformat.h>
#include <libavutil/opt.h>
#include <libswresample/swresample.h>
#include <libswscale/swscale.h>
}
namespace VideoDumper {
@@ -69,7 +69,7 @@ protected:
/**
* A FFmpegStream used for video data.
* Rescales, encodes and writes a frame.
* Filters (scales), encodes and writes a frame.
*/
class FFmpegVideoStream : public FFmpegStream {
public:
@@ -80,21 +80,39 @@ public:
void ProcessFrame(VideoFrame& frame);
private:
struct SwsContextDeleter {
void operator()(SwsContext* sws_context) const {
sws_freeContext(sws_context);
}
};
bool InitHWContext(const AVCodec* codec);
bool InitFilters();
u64 frame_count{};
std::unique_ptr<AVFrame, AVFrameDeleter> current_frame{};
std::unique_ptr<AVFrame, AVFrameDeleter> scaled_frame{};
std::unique_ptr<SwsContext, SwsContextDeleter> sws_context{};
std::unique_ptr<AVFrame, AVFrameDeleter> filtered_frame{};
std::unique_ptr<AVFrame, AVFrameDeleter> hw_frame{};
Layout::FramebufferLayout layout;
/// The pixel format the frames are stored in
/// The pixel format the input frames are stored in
static constexpr AVPixelFormat pixel_format = AVPixelFormat::AV_PIX_FMT_BGRA;
// Software pixel format. For normal encoders, this is the format they accept. For HW-acceled
// encoders, this is the format the HW frames context accepts.
AVPixelFormat sw_pixel_format = AV_PIX_FMT_NONE;
/// Whether the encoder we are using requires HW frames to be supplied.
bool requires_hw_frames = false;
// Filter related
struct AVFilterGraphDeleter {
void operator()(AVFilterGraph* filter_graph) const {
avfilter_graph_free(&filter_graph);
}
};
std::unique_ptr<AVFilterGraph, AVFilterGraphDeleter> filter_graph{};
// These don't need to be freed apparently
AVFilterContext* source_context;
AVFilterContext* sink_context;
/// The filter graph to use. This graph means 'change FPS to 60, convert format if needed'
static constexpr std::string_view filter_graph_desc = "fps=60";
};
/**