MXVK Vulkan Framework 0.24.0
C++20 Vulkan rendering framework for practical 2D and 3D application development with SDL3.
Loading...
Searching...
No Matches
mxvk_ff_capture.hpp
Go to the documentation of this file.
1/**
2 * @file mxvk_ff_capture.hpp
3 * @brief FFmpeg video-file capture with optional CUDA hardware decoding.
4 */
5#pragma once
6
7#include <cstdint>
8#include <string>
9#include <vector>
10
11extern "C" {
12#include <libavcodec/avcodec.h>
13#include <libavformat/avformat.h>
14#include <libavutil/hwcontext.h>
15#include <libavutil/pixfmt.h>
16#include <libswscale/swscale.h>
17}
18#ifdef MXVK_CUDA
19#include <opencv2/core/cuda.hpp>
20#include <opencv2/cudaimgproc.hpp>
21#endif
22
23namespace mxvk {
24
25 /**
26 * @brief FFmpeg-backed video-file capture source.
27 *
28 * VK_FF_Capture opens video files directly through FFmpeg, prefers CUDA
29 * hardware decoding when available, and returns tightly packed RGBA8 frames
30 * suitable for Vulkan staging uploads or encoder input.
31 */
33 public:
34 /** @brief Construct a closed capture source. */
35 VK_FF_Capture() = default;
36 /** @brief Close and release FFmpeg resources. */
38 VK_FF_Capture(const VK_FF_Capture &) = delete;
42
43 /**
44 * @brief Open a video file.
45 * @param filename Path to the input video file.
46 * @return true on success.
47 */
48 bool open(const std::string &filename);
49 /** @brief Close the active file and release decoder resources. */
50 void close();
51 /** @brief Check whether a decoder is open. */
52 [[nodiscard]] bool is_open() const { return formatCtx != nullptr && codecCtx != nullptr; }
53
54 /**
55 * @brief Decode the next frame as tightly packed RGBA8.
56 * @param rgba Output byte buffer, resized to pitch * height.
57 * @param width Output frame width in pixels.
58 * @param height Output frame height in pixels.
59 * @param pitch Output row pitch in bytes.
60 * @param flipY Flip rows vertically after conversion when true.
61 * @return true when a frame was decoded, false on EOF or failure.
62 */
63 bool readRgba(std::vector<uint8_t> &rgba, int &width, int &height, int &pitch, bool flipY = false);
64#ifdef MXVK_CUDA
65 /**
66 * @brief Decode the next frame as a CUDA-resident RGBA8 image.
67 * @param rgba Output CUDA GpuMat containing RGBA8 pixels.
68 * @param stream CUDA stream used for device copies and color conversion.
69 * @param flipY Flip rows vertically after conversion when true.
70 * @return true when a frame was decoded and converted.
71 */
72 bool readGpuRgba(cv::cuda::GpuMat &rgba, cv::cuda::Stream &stream, bool flipY = false);
73#endif
74
75 /** @brief Source width in pixels. */
76 [[nodiscard]] int width() const { return frameWidth; }
77 /** @brief Source height in pixels. */
78 [[nodiscard]] int height() const { return frameHeight; }
79 /** @brief Source frame rate, falling back to 30 fps when unknown. */
80 [[nodiscard]] double fps() const { return frameFps; }
81 /** @brief True when CUDA hardware decode is active. */
82 [[nodiscard]] bool using_hardware_decode() const { return hardwareDecode; }
83
84 private:
85 static AVPixelFormat chooseHwFormat(AVCodecContext *ctx, const AVPixelFormat *formats);
86 [[nodiscard]] AVPixelFormat selectHwFormat(const AVPixelFormat *formats) const;
87 bool initHardwareDevice(const AVCodec *decoder);
88 bool decodeNextFrame();
89 bool convertFrameToRgba(const AVFrame *decodedFrame, std::vector<uint8_t> &rgba, int &width, int &height, int &pitch, bool flipY);
90#ifdef MXVK_CUDA
91 bool convertFrameToGpuRgba(const AVFrame *decodedFrame, cv::cuda::GpuMat &rgba, cv::cuda::Stream &stream, bool flipY);
92#endif
93 void flipRows(std::vector<uint8_t> &rgba, int pitch) const;
94
95 AVFormatContext *formatCtx = nullptr;
96 AVCodecContext *codecCtx = nullptr;
97 AVPacket *packet = nullptr;
98 AVFrame *frame = nullptr;
99 AVFrame *swFrame = nullptr;
100 AVBufferRef *hwDeviceCtx = nullptr;
101 SwsContext *swsCtx = nullptr;
102 int videoStream = -1;
103 int frameWidth = 0;
104 int frameHeight = 0;
105 double frameFps = 30.0;
106 AVPixelFormat hwPixFmt = AV_PIX_FMT_NONE;
107 bool hardwareDecode = false;
108#ifdef MXVK_CUDA
109 cv::cuda::GpuMat gpuNv12{};
110 cv::cuda::GpuMat gpuRgb{};
111 cv::cuda::GpuMat gpuRgba{};
112 cv::cuda::GpuMat gpuFlippedRgba{};
113#endif
114 };
115
116} // namespace mxvk
void close()
Close the active file and release decoder resources.
bool is_open() const
Check whether a decoder is open.
VK_FF_Capture & operator=(const VK_FF_Capture &)=delete
double fps() const
Source frame rate, falling back to 30 fps when unknown.
int width() const
Source width in pixels.
int height() const
Source height in pixels.
VK_FF_Capture(VK_FF_Capture &&)=delete
bool open(const std::string &filename)
Open a video file.
VK_FF_Capture(const VK_FF_Capture &)=delete
VK_FF_Capture()=default
Construct a closed capture source.
VK_FF_Capture & operator=(VK_FF_Capture &&)=delete
bool readRgba(std::vector< uint8_t > &rgba, int &width, int &height, int &pitch, bool flipY=false)
Decode the next frame as tightly packed RGBA8.
bool using_hardware_decode() const
True when CUDA hardware decode is active.
~VK_FF_Capture()
Close and release FFmpeg resources.
Utilities for loading and saving PNG images.
Definition mxvk.hpp:30