MXVK Vulkan Framework 0.33.1
C++20 Vulkan rendering framework for practical 2D and 3D application development with SDL3.
Loading...
Searching...
No Matches
mxvk::VK_FF_Capture Class Reference

FFmpeg-backed video-file capture source. More...

#include <mxvk/include/mxvk/mxvk_ff_capture.hpp>

Public Member Functions

void close ()
 Close the active file and release decoder resources.
double fps () const
 Source frame rate, falling back to 30 fps when unknown.
int hardware_decode_device () const
 Selected CUDA hardware-decode device, or -1 for FFmpeg's default.
int height () const
 Source height in pixels.
bool is_open () const
 Check whether a decoder is open.
bool open (const std::string &filename)
 Open a video file.
bool open (const std::string &filename, int cuda_device)
 Open a video file on a selected CUDA decode device.
VK_FF_Captureoperator= (const VK_FF_Capture &)=delete
VK_FF_Captureoperator= (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 seek_start ()
 Seek the active video stream back to its beginning.
bool skip ()
 Decode and discard the next video frame.
bool using_hardware_decode () const
 True when CUDA hardware decode is active.
 VK_FF_Capture ()=default
 Construct a closed capture source.
 VK_FF_Capture (const VK_FF_Capture &)=delete
 VK_FF_Capture (VK_FF_Capture &&)=delete
int width () const
 Source width in pixels.
 ~VK_FF_Capture ()
 Close and release FFmpeg resources.

Detailed Description

FFmpeg-backed video-file capture source.

VK_FF_Capture opens video files directly through FFmpeg, prefers CUDA hardware decoding when available, and returns tightly packed RGBA8 frames suitable for Vulkan staging uploads or encoder input.

Definition at line 33 of file mxvk_ff_capture.hpp.

Constructor & Destructor Documentation

◆ VK_FF_Capture() [1/3]

mxvk::VK_FF_Capture::VK_FF_Capture ( )
default

Construct a closed capture source.

◆ ~VK_FF_Capture()

mxvk::VK_FF_Capture::~VK_FF_Capture ( )

Close and release FFmpeg resources.

Definition at line 58 of file mxvk_ff_capture.cpp.

58 {
59 close();
60 }
void close()
Close the active file and release decoder resources.

◆ VK_FF_Capture() [2/3]

mxvk::VK_FF_Capture::VK_FF_Capture ( const VK_FF_Capture & )
delete

◆ VK_FF_Capture() [3/3]

mxvk::VK_FF_Capture::VK_FF_Capture ( VK_FF_Capture && )
delete

Member Function Documentation

◆ close()

void mxvk::VK_FF_Capture::close ( )

Close the active file and release decoder resources.

Definition at line 182 of file mxvk_ff_capture.cpp.

182 {
183#ifdef MXVK_CUDA
184 if (decoder_surface_copy_event != nullptr) {
185 cudaEventDestroy(decoder_surface_copy_event);
186 decoder_surface_copy_event = nullptr;
187 }
188 decoder_surface_barrier_logged = false;
189#endif
190 if (swsCtx != nullptr) {
191 sws_freeContext(swsCtx);
192 swsCtx = nullptr;
193 }
194 if (hwDeviceCtx != nullptr) {
195 av_buffer_unref(&hwDeviceCtx);
196 }
197 if (swFrame != nullptr) {
198 av_frame_free(&swFrame);
199 }
200 if (frame != nullptr) {
201 av_frame_free(&frame);
202 }
203 if (packet != nullptr) {
204 av_packet_free(&packet);
205 }
206 if (codecCtx != nullptr) {
207 avcodec_free_context(&codecCtx);
208 }
209 if (formatCtx != nullptr) {
210 avformat_close_input(&formatCtx);
211 }
212 videoStream = -1;
213 frameWidth = 0;
214 frameHeight = 0;
215 frameFps = 30.0;
216 hwPixFmt = AV_PIX_FMT_NONE;
217 hardwareDecode = false;
218 hardwareDecodeDevice = -1;
219 }

◆ fps()

double mxvk::VK_FF_Capture::fps ( ) const
inlinenodiscard

Source frame rate, falling back to 30 fps when unknown.

Definition at line 105 of file mxvk_ff_capture.hpp.

105{ return frameFps; }

◆ hardware_decode_device()

int mxvk::VK_FF_Capture::hardware_decode_device ( ) const
inlinenodiscard

Selected CUDA hardware-decode device, or -1 for FFmpeg's default.

Definition at line 109 of file mxvk_ff_capture.hpp.

109{ return hardwareDecodeDevice; }

◆ height()

int mxvk::VK_FF_Capture::height ( ) const
inlinenodiscard

Source height in pixels.

Definition at line 103 of file mxvk_ff_capture.hpp.

103{ return frameHeight; }

◆ is_open()

bool mxvk::VK_FF_Capture::is_open ( ) const
inlinenodiscard

Check whether a decoder is open.

Definition at line 77 of file mxvk_ff_capture.hpp.

77{ return formatCtx != nullptr && codecCtx != nullptr; }

◆ open() [1/2]

bool mxvk::VK_FF_Capture::open ( const std::string & filename)

Open a video file.

Parameters
filenamePath to the input video file.
Returns
true on success.

Definition at line 62 of file mxvk_ff_capture.cpp.

62 {
63 return open(filename, -1);
64 }
bool open(const std::string &filename)
Open a video file.

◆ open() [2/2]

bool mxvk::VK_FF_Capture::open ( const std::string & filename,
int cuda_device )

Open a video file on a selected CUDA decode device.

Parameters
filenamePath to the input video file.
cuda_deviceCUDA device index used for hardware decode; a negative value lets FFmpeg select its default device.
Returns
true on success.

Definition at line 66 of file mxvk_ff_capture.cpp.

66 {
67 close();
68
69 if (avformat_open_input(&formatCtx, filename.c_str(), nullptr, nullptr) < 0) {
70 std::cout << std::format("mxvk_ff_capture: failed to open file: {}\n", filename);
71 close();
72 return false;
73 }
74
75 if (avformat_find_stream_info(formatCtx, nullptr) < 0) {
76 std::cout << std::format("mxvk_ff_capture: failed to read stream info: {}\n", filename);
77 close();
78 return false;
79 }
80
81 const int streamIndex = av_find_best_stream(formatCtx, AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, 0);
82 if (streamIndex < 0) {
83 std::cout << std::format("mxvk_ff_capture: no video stream found: {}\n", filename);
84 close();
85 return false;
86 }
87 videoStream = streamIndex;
88
89 AVStream *stream = formatCtx->streams[videoStream];
90 const AVCodecParameters *codecParams = stream->codecpar;
91 const AVCodec *decoder = avcodec_find_decoder(codecParams->codec_id);
92 if (decoder == nullptr) {
93 std::cout << "mxvk_ff_capture: no decoder found for video stream\n";
94 close();
95 return false;
96 }
97
98 codecCtx = avcodec_alloc_context3(decoder);
99 if (codecCtx == nullptr || avcodec_parameters_to_context(codecCtx, codecParams) < 0) {
100 std::cout << "mxvk_ff_capture: failed to create decoder context\n";
101 close();
102 return false;
103 }
104
105 codecCtx->opaque = this;
106 if (initHardwareDevice(decoder, cuda_device)) {
107 codecCtx->get_format = &VK_FF_Capture::chooseHwFormat;
108 codecCtx->hw_device_ctx = av_buffer_ref(hwDeviceCtx);
109 hardwareDecode = codecCtx->hw_device_ctx != nullptr;
110 }
111
112 if (avcodec_open2(codecCtx, decoder, nullptr) < 0) {
113 std::cout << "mxvk_ff_capture: failed to open decoder\n";
114 close();
115 return false;
116 }
117
118 packet = av_packet_alloc();
119 frame = av_frame_alloc();
120 swFrame = av_frame_alloc();
121 if (packet == nullptr || frame == nullptr || swFrame == nullptr) {
122 std::cout << "mxvk_ff_capture: failed to allocate decoder frames\n";
123 close();
124 return false;
125 }
126
127 frameWidth = codecCtx->width;
128 frameHeight = codecCtx->height;
129 frameFps = rationalToDouble(stream->avg_frame_rate);
130 if (frameFps <= 0.0) {
131 frameFps = rationalToDouble(stream->r_frame_rate);
132 }
133 if (frameFps <= 0.0) {
134 frameFps = 30.0;
135 }
136
137 const std::string decodeMode =
138 hardwareDecode && hardwareDecodeDevice >= 0
139 ? std::format("cuda:{}", hardwareDecodeDevice)
140 : hardwareDecode ? "cuda"
141 : "software";
142 std::cout << std::format(
143 "mxvk_ff_capture: opened {} ({}x{}, {:.3f} fps, decode={})\n",
144 filename,
145 frameWidth,
146 frameHeight,
147 frameFps,
148 decodeMode);
149 return true;
150 }

◆ operator=() [1/2]

VK_FF_Capture & mxvk::VK_FF_Capture::operator= ( const VK_FF_Capture & )
delete

◆ operator=() [2/2]

VK_FF_Capture & mxvk::VK_FF_Capture::operator= ( VK_FF_Capture && )
delete

◆ readRgba()

bool mxvk::VK_FF_Capture::readRgba ( std::vector< uint8_t > & rgba,
int & width,
int & height,
int & pitch,
bool flipY = false )

Decode the next frame as tightly packed RGBA8.

Parameters
rgbaOutput byte buffer, resized to pitch * height.
widthOutput frame width in pixels.
heightOutput frame height in pixels.
pitchOutput row pitch in bytes.
flipYFlip rows vertically after conversion when true.
Returns
true when a frame was decoded, false on EOF or failure.

Definition at line 221 of file mxvk_ff_capture.cpp.

221 {
222 if (!is_open()) {
223 return false;
224 }
225
226 if (!decodeNextFrame()) {
227 return false;
228 }
229 const bool converted = convertFrameToRgba(frame, rgba, width, height, pitch, flipY);
230 av_frame_unref(frame);
231 return converted;
232 }
bool is_open() const
Check whether a decoder is open.
int width() const
Source width in pixels.
int height() const
Source height in pixels.

◆ seek_start()

bool mxvk::VK_FF_Capture::seek_start ( )

Seek the active video stream back to its beginning.

The decoder and optional hardware-device context remain active.

Returns
true when the input was sought and the decoder was flushed.

Definition at line 152 of file mxvk_ff_capture.cpp.

152 {
153 if (!is_open() || videoStream < 0) {
154 return false;
155 }
156
157 AVStream *stream = formatCtx->streams[videoStream];
158 const int64_t timestamp = stream->start_time == AV_NOPTS_VALUE
159 ? 0
160 : stream->start_time;
161 if (av_seek_frame(formatCtx, videoStream, timestamp,
162 AVSEEK_FLAG_BACKWARD) < 0) {
163 std::cout << "mxvk_ff_capture: failed to seek to start\n";
164 return false;
165 }
166
167 avcodec_flush_buffers(codecCtx);
168 av_packet_unref(packet);
169 av_frame_unref(frame);
170 av_frame_unref(swFrame);
171 return true;
172 }

◆ skip()

bool mxvk::VK_FF_Capture::skip ( )

Decode and discard the next video frame.

Hardware frames remain on the decoder device and no RGBA conversion or host transfer is performed. This is intended for media-clock catch-up when a late source frame must not be rendered.

Returns
true when a frame was decoded and discarded.

Definition at line 174 of file mxvk_ff_capture.cpp.

174 {
175 if (!is_open() || !decodeNextFrame()) {
176 return false;
177 }
178 av_frame_unref(frame);
179 return true;
180 }

◆ using_hardware_decode()

bool mxvk::VK_FF_Capture::using_hardware_decode ( ) const
inlinenodiscard

True when CUDA hardware decode is active.

Definition at line 107 of file mxvk_ff_capture.hpp.

107{ return hardwareDecode; }

◆ width()

int mxvk::VK_FF_Capture::width ( ) const
inlinenodiscard

Source width in pixels.

Definition at line 101 of file mxvk_ff_capture.hpp.

101{ return frameWidth; }

The documentation for this class was generated from the following files: