MXVK Vulkan Framework 0.35.0
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_Capture & operator= (const VK_FF_Capture &)=delete
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 readRgba16 (std::vector< uint16_t > &rgba, int &width, int &height, int &pitch, bool flipY=false)
 Decode the next frame as native-endian RGBA16.
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 or RGBA16 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 126 of file mxvk_ff_capture.cpp.

126{ close(); }
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 233 of file mxvk_ff_capture.cpp.

233 {
234#ifdef MXVK_CUDA
235 if (decoder_surface_copy_event != nullptr) {
236 cudaEventDestroy(decoder_surface_copy_event);
237 decoder_surface_copy_event = nullptr;
238 }
239 decoder_surface_barrier_logged = false;
240#endif
241 if (swsCtx != nullptr) {
242 sws_freeContext(swsCtx);
243 swsCtx = nullptr;
244 }
245 rgba16_conversion_logged = false;
246 if (hwDeviceCtx != nullptr) {
247 av_buffer_unref(&hwDeviceCtx);
248 }
249 if (swFrame != nullptr) {
250 av_frame_free(&swFrame);
251 }
252 if (frame != nullptr) {
253 av_frame_free(&frame);
254 }
255 if (packet != nullptr) {
256 av_packet_free(&packet);
257 }
258 if (codecCtx != nullptr) {
259 avcodec_free_context(&codecCtx);
260 }
261 if (formatCtx != nullptr) {
262 avformat_close_input(&formatCtx);
263 }
264 videoStream = -1;
265 frameWidth = 0;
266 frameHeight = 0;
267 frameFps = 30.0;
268 hwPixFmt = AV_PIX_FMT_NONE;
269 hardwareDecode = false;
270 hardwareDecodeDevice = -1;
271 }

◆ fps()

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

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

Definition at line 118 of file mxvk_ff_capture.hpp.

118{ 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 122 of file mxvk_ff_capture.hpp.

122{ return hardwareDecodeDevice; }

◆ height()

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

Source height in pixels.

Definition at line 116 of file mxvk_ff_capture.hpp.

116{ 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 128 of file mxvk_ff_capture.cpp.

128{ return open(filename, -1); }
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 130 of file mxvk_ff_capture.cpp.

130 {
131 close();
132
133 if (avformat_open_input(&formatCtx, filename.c_str(), nullptr, nullptr) < 0) {
134 std::cout << std::format("mxvk_ff_capture: failed to open file: {}\n", filename);
135 close();
136 return false;
137 }
138
139 if (avformat_find_stream_info(formatCtx, nullptr) < 0) {
140 std::cout << std::format("mxvk_ff_capture: failed to read stream info: {}\n", filename);
141 close();
142 return false;
143 }
144
145 const int streamIndex = av_find_best_stream(formatCtx, AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, 0);
146 if (streamIndex < 0) {
147 std::cout << std::format("mxvk_ff_capture: no video stream found: {}\n", filename);
148 close();
149 return false;
150 }
151 videoStream = streamIndex;
152
153 AVStream *stream = formatCtx->streams[videoStream];
154 const AVCodecParameters *codecParams = stream->codecpar;
155 const AVCodec *decoder = avcodec_find_decoder(codecParams->codec_id);
156 if (decoder == nullptr) {
157 std::cout << "mxvk_ff_capture: no decoder found for video stream\n";
158 close();
159 return false;
160 }
161
162 codecCtx = avcodec_alloc_context3(decoder);
163 if (codecCtx == nullptr || avcodec_parameters_to_context(codecCtx, codecParams) < 0) {
164 std::cout << "mxvk_ff_capture: failed to create decoder context\n";
165 close();
166 return false;
167 }
168
169 codecCtx->opaque = this;
170 if (initHardwareDevice(decoder, cuda_device)) {
171 codecCtx->get_format = &VK_FF_Capture::chooseHwFormat;
172 codecCtx->hw_device_ctx = av_buffer_ref(hwDeviceCtx);
173 hardwareDecode = codecCtx->hw_device_ctx != nullptr;
174 }
175
176 if (avcodec_open2(codecCtx, decoder, nullptr) < 0) {
177 std::cout << "mxvk_ff_capture: failed to open decoder\n";
178 close();
179 return false;
180 }
181
182 packet = av_packet_alloc();
183 frame = av_frame_alloc();
184 swFrame = av_frame_alloc();
185 if (packet == nullptr || frame == nullptr || swFrame == nullptr) {
186 std::cout << "mxvk_ff_capture: failed to allocate decoder frames\n";
187 close();
188 return false;
189 }
190
191 frameWidth = codecCtx->width;
192 frameHeight = codecCtx->height;
193 frameFps = rationalToDouble(stream->avg_frame_rate);
194 if (frameFps <= 0.0) {
195 frameFps = rationalToDouble(stream->r_frame_rate);
196 }
197 if (frameFps <= 0.0) {
198 frameFps = 30.0;
199 }
200
201 const std::string decodeMode = hardwareDecode && hardwareDecodeDevice >= 0 ? std::format("cuda:{}", hardwareDecodeDevice) : hardwareDecode ? "cuda" : "software";
202 std::cout << std::format("mxvk_ff_capture: opened {} ({}x{}, {:.3f} fps, decode={})\n", filename, frameWidth, frameHeight, frameFps, decodeMode);
203 return true;
204 }

◆ 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 273 of file mxvk_ff_capture.cpp.

273 {
274 if (!is_open()) {
275 return false;
276 }
277
278 if (!decodeNextFrame()) {
279 return false;
280 }
281 const bool converted = convertFrameToRgba(frame, rgba, width, height, pitch, flipY);
282 av_frame_unref(frame);
283 return converted;
284 }
bool is_open() const
Check whether a decoder is open.
int width() const
Source width in pixels.
int height() const
Source height in pixels.

◆ readRgba16()

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

Decode the next frame as native-endian RGBA16.

Parameters
rgbaOutput 16-bit component 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.

Ten-bit YUV/P010 sources retain their component precision. Values remain transfer-encoded; this method does not linearize PQ or HLG.

Definition at line 286 of file mxvk_ff_capture.cpp.

286 {
287 if (!is_open()) {
288 return false;
289 }
290
291 if (!decodeNextFrame()) {
292 return false;
293 }
294 const bool converted = convertFrameToRgba16(frame, rgba, width, height, pitch, flipY);
295 av_frame_unref(frame);
296 return converted;
297 }

◆ 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 206 of file mxvk_ff_capture.cpp.

206 {
207 if (!is_open() || videoStream < 0) {
208 return false;
209 }
210
211 AVStream *stream = formatCtx->streams[videoStream];
212 const int64_t timestamp = stream->start_time == AV_NOPTS_VALUE ? 0 : stream->start_time;
213 if (av_seek_frame(formatCtx, videoStream, timestamp, AVSEEK_FLAG_BACKWARD) < 0) {
214 std::cout << "mxvk_ff_capture: failed to seek to start\n";
215 return false;
216 }
217
218 avcodec_flush_buffers(codecCtx);
219 av_packet_unref(packet);
220 av_frame_unref(frame);
221 av_frame_unref(swFrame);
222 return true;
223 }

◆ 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 225 of file mxvk_ff_capture.cpp.

225 {
226 if (!is_open() || !decodeNextFrame()) {
227 return false;
228 }
229 av_frame_unref(frame);
230 return true;
231 }

◆ using_hardware_decode()

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

True when CUDA hardware decode is active.

Definition at line 120 of file mxvk_ff_capture.hpp.

120{ return hardwareDecode; }

◆ width()

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

Source width in pixels.

Definition at line 114 of file mxvk_ff_capture.hpp.

114{ return frameWidth; }

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