Wavelength
Privacy-focused, cross-platform, and open-source communication application
Loading...
Searching...
No Matches
VideoDecoder Class Referencefinal

Decodes video data frame by frame using FFmpeg libraries in a separate thread. More...

#include <video_decoder.h>

Inheritance diagram for VideoDecoder:
Collaboration diagram for VideoDecoder:

Signals

void error (const QString &message)
 Emitted when an error occurs during initialization or decoding.
 
void frameReady (const QImage &frame)
 Emitted for each decoded video frame.
 
void playbackFinished ()
 Emitted when both video and audio (if present) streams reach the end.
 
void positionChanged (double position)
 Emitted periodically during playback to indicate the current position (based on audio if available, otherwise estimated).
 
void videoInfo (int width, int height, double fps, double duration, bool has_audio)
 Emitted after successful initialization, providing video stream details.
 

Public Member Functions

void ExtractFirstFrame ()
 Synchronously extracts the first video frame from the data. Performs a separate, simplified FFmpeg initialization and decoding process to get the first frame quickly, typically for generating a thumbnail. Emits frameReady() with the first frame upon success. This method runs in the calling thread.
 
float GetVolume () const
 Gets the current playback volume (from the internal AudioDecoder). Returns 0.0 if there is no audio stream. This operation is thread-safe.
 
bool HasAudio () const
 Checks if the video file contains an audio stream.
 
bool Initialize ()
 Initializes the FFmpeg components for decoding the video and potentially audio. Opens the input stream using the custom I/O context, finds video and audio streams, opens codecs, sets up the video scaler (to convert to RGB24), allocates frames/buffers. If audio is found, creates and connects to an internal AudioDecoder instance. Emits videoInfo upon success. This operation is thread-safe and should be called before starting the thread.
 
bool IsPaused () const
 Checks if the playback is currently paused. This operation is thread-safe.
 
void Pause ()
 Toggles the paused state of the playback. If paused, playback stops; if unpaused, playback resumes. Also pauses/resumes the internal audio decoder (if present). Wakes the thread if it was waiting due to being paused. This operation is thread-safe.
 
void ReleaseResources ()
 Releases all FFmpeg and internal AudioDecoder resources. Calls CleanupFFmpegResources(). This operation is thread-safe.
 
void Reset ()
 Resets the playback position to the beginning of the video. Pauses playback, seeks both video and internal audio decoder (if present) to 0, resets internal state flags (finished, first frame), and wakes the thread. This operation is thread-safe.
 
void Seek (double position)
 Seeks to a specific position in the video stream. Seeks the internal audio decoder (if present) and sets the seeking flag and target timestamp for the video stream. The actual video seek operation happens within the run() loop. This operation is thread-safe.
 
void SetVolume (float volume) const
 Sets the playback volume (delegated to the internal AudioDecoder). Has no effect if there is no audio stream. This operation is thread-safe.
 
void Stop ()
 Stops the decoding thread and playback gracefully. Sets the stopped_ flag, stops the internal audio decoder (if present), and wakes the thread if it's waiting. The thread will then exit its run loop. This operation is thread-safe.
 
 VideoDecoder (const QByteArray &video_data, QObject *parent=nullptr)
 Constructs a VideoDecoder object. Initializes internal state, allocates memory for FFmpeg's custom I/O context, sets up the QBuffer for reading from the provided video data.
 
 ~VideoDecoder () override
 Destructor. Stops the decoding thread, waits for it to finish, and releases all allocated resources.
 

Protected Member Functions

void run () override
 The main function executed by the QThread. Contains the loop that reads packets, decodes video frames, handles seeking/pausing, synchronizes with the internal audio decoder (if present) or uses frame timing, and emits decoded frames via the frameReady signal.
 

Private Slots

void HandleAudioError (const QString &message)
 Slot connected to the internal AudioDecoder's error signal. Relays the audio error message via the main error() signal.
 
void HandleAudioFinished ()
 Slot connected to the internal AudioDecoder's playbackFinished signal. Sets the audio_finished_ flag and emits the main playbackFinished() signal if the video stream has also finished.
 
void UpdateAudioPosition (double position)
 Slot connected to the internal AudioDecoder's positionChanged signal. Updates the internal current_audio_position_ and emits the main positionChanged() signal.
 

Private Member Functions

void CleanupFFmpegResources ()
 Releases all FFmpeg resources (contexts, frames, scaler) and deletes the internal AudioDecoder. Resets internal state variables related to FFmpeg and audio.
 

Static Private Member Functions

static int ReadPacket (void *opaque, uint8_t *buf, int buf_size)
 Custom read function for FFmpeg's AVIOContext. Reads data from the internal QBuffer (buffer_).
 
static int64_t SeekPacket (void *opaque, int64_t offset, int whence)
 Custom seek function for FFmpeg's AVIOContext. Adjusts the position within the internal QBuffer (buffer_). Supports SEEK_SET and AVSEEK_SIZE.
 

Private Attributes

AudioDecoderaudio_decoder_ = nullptr
 Pointer to the internal AudioDecoder instance (if audio stream exists).
 
bool audio_finished_ = false
 Flag indicating if the internal AudioDecoder has finished playback. Access protected by mutex_.
 
bool audio_initialized_ = false
 Flag indicating if the internal AudioDecoder has been successfully initialized.
 
int audio_stream_index_ = -1
 Index of the audio stream within the format context.
 
QBuffer buffer_
 QBuffer used by FFmpeg's custom I/O context to read video_data_.
 
AVCodecContext * codec_context_ = nullptr
 FFmpeg context for the video codec.
 
double current_audio_position_ = 0.0
 Current playback position reported by the internal AudioDecoder. Access protected by mutex_.
 
double current_position_ = 0.0
 Current estimated playback position in seconds (used if no audio).
 
double duration_ = 0.0
 Total duration of the video in seconds.
 
bool first_frame_ = true
 Flag indicating if the current frame is the first one after start/seek.
 
AVFormatContext * format_context_ = nullptr
 FFmpeg context for handling the container format (e.g., MP4, WebM).
 
AVFrame * frame_ = nullptr
 FFmpeg frame structure to hold decoded video data.
 
double frame_rate_ = 0.0
 Calculated average frame rate of the video in frames per second.
 
QElapsedTimer frame_timer_
 Timer used for frame timing synchronization when no audio is present.
 
AVIOContext * io_context_ = nullptr
 FFmpeg context for custom I/O operations (reading from memory).
 
int64_t last_frame_pts_ = AV_NOPTS_VALUE
 Presentation timestamp (PTS) of the previously decoded frame (used for frame timing).
 
QMutex mutex_
 Mutex protecting access to shared state variables (paused_, stopped_, seeking_, etc.).
 
bool paused_ = false
 Flag indicating if playback is currently paused. Access protected by mutex_.
 
int64_t seek_position_ = -1
 Target timestamp (in video stream timebase) for the pending seek operation. Access protected by mutex_.
 
bool seeking_ = false
 Flag indicating if a seek operation is pending. Access protected by mutex_.
 
bool stopped_ = false
 Flag indicating if the thread should stop execution. Access protected by mutex_.
 
SwsContext * sws_context_ = nullptr
 FFmpeg context for image scaling and pixel format conversion (to RGB24).
 
QByteArray video_data_
 The raw video data provided in the constructor.
 
bool video_finished_ = false
 Flag indicating if the video stream has reached the end. Access protected by mutex_.
 
int video_stream_ = -1
 Index of the video stream within the format context.
 
QWaitCondition wait_condition_
 Condition variable used to pause/resume the decoding thread.
 

Detailed Description

Decodes video data frame by frame using FFmpeg libraries in a separate thread.

This class takes raw video data (e.g., MP4, WebM) as a QByteArray, uses FFmpeg (libavformat, libavcodec, libswscale) to decode the video stream, and emits each decoded frame as a QImage (Format_RGB888). If an audio stream is present, it uses an internal AudioDecoder instance to handle audio decoding and playback synchronization.

The decoding loop runs in a separate QThread to avoid blocking the main UI thread. It supports pausing, resuming, seeking, volume control (via the internal AudioDecoder), and provides signals for status updates (errors, info, position, frames, finish). It uses a custom AVIOContext to read data directly from the QByteArray in memory.

Constructor & Destructor Documentation

◆ VideoDecoder()

VideoDecoder::VideoDecoder ( const QByteArray & video_data,
QObject * parent = nullptr )
explicit

Constructs a VideoDecoder object. Initializes internal state, allocates memory for FFmpeg's custom I/O context, sets up the QBuffer for reading from the provided video data.

Parameters
video_dataThe raw video data to be decoded.
parentOptional parent QObject.
Here is the call graph for this function:

◆ ~VideoDecoder()

VideoDecoder::~VideoDecoder ( )
override

Destructor. Stops the decoding thread, waits for it to finish, and releases all allocated resources.

Here is the call graph for this function:

Member Function Documentation

◆ CleanupFFmpegResources()

void VideoDecoder::CleanupFFmpegResources ( )
private

Releases all FFmpeg resources (contexts, frames, scaler) and deletes the internal AudioDecoder. Resets internal state variables related to FFmpeg and audio.

Here is the caller graph for this function:

◆ error

void VideoDecoder::error ( const QString & message)
signal

Emitted when an error occurs during initialization or decoding.

Parameters
messageA description of the error.
Here is the caller graph for this function:

◆ ExtractFirstFrame()

void VideoDecoder::ExtractFirstFrame ( )

Synchronously extracts the first video frame from the data. Performs a separate, simplified FFmpeg initialization and decoding process to get the first frame quickly, typically for generating a thumbnail. Emits frameReady() with the first frame upon success. This method runs in the calling thread.

Here is the call graph for this function:

◆ frameReady

void VideoDecoder::frameReady ( const QImage & frame)
signal

Emitted for each decoded video frame.

Parameters
frameThe decoded frame as a QImage (Format_RGB888). A copy is emitted.
Here is the caller graph for this function:

◆ GetVolume()

float VideoDecoder::GetVolume ( ) const

Gets the current playback volume (from the internal AudioDecoder). Returns 0.0 if there is no audio stream. This operation is thread-safe.

Returns
The current volume level (0.0 to 1.0).

◆ HandleAudioError

void VideoDecoder::HandleAudioError ( const QString & message)
inlineprivateslot

Slot connected to the internal AudioDecoder's error signal. Relays the audio error message via the main error() signal.

Parameters
messageThe error message from the AudioDecoder.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ HandleAudioFinished

void VideoDecoder::HandleAudioFinished ( )
privateslot

Slot connected to the internal AudioDecoder's playbackFinished signal. Sets the audio_finished_ flag and emits the main playbackFinished() signal if the video stream has also finished.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ HasAudio()

bool VideoDecoder::HasAudio ( ) const
inline

Checks if the video file contains an audio stream.

Returns
True if an audio stream was detected during initialization, false otherwise.
Here is the caller graph for this function:

◆ Initialize()

bool VideoDecoder::Initialize ( )

Initializes the FFmpeg components for decoding the video and potentially audio. Opens the input stream using the custom I/O context, finds video and audio streams, opens codecs, sets up the video scaler (to convert to RGB24), allocates frames/buffers. If audio is found, creates and connects to an internal AudioDecoder instance. Emits videoInfo upon success. This operation is thread-safe and should be called before starting the thread.

Returns
True if initialization was successful, false otherwise.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ IsPaused()

bool VideoDecoder::IsPaused ( ) const
inline

Checks if the playback is currently paused. This operation is thread-safe.

Returns
True if paused, false otherwise.

◆ Pause()

void VideoDecoder::Pause ( )

Toggles the paused state of the playback. If paused, playback stops; if unpaused, playback resumes. Also pauses/resumes the internal audio decoder (if present). Wakes the thread if it was waiting due to being paused. This operation is thread-safe.

◆ playbackFinished

void VideoDecoder::playbackFinished ( )
signal

Emitted when both video and audio (if present) streams reach the end.

Here is the caller graph for this function:

◆ positionChanged

void VideoDecoder::positionChanged ( double position)
signal

Emitted periodically during playback to indicate the current position (based on audio if available, otherwise estimated).

Parameters
positionThe current playback position in seconds.
Here is the caller graph for this function:

◆ ReadPacket()

int VideoDecoder::ReadPacket ( void * opaque,
uint8_t * buf,
int buf_size )
staticprivate

Custom read function for FFmpeg's AVIOContext. Reads data from the internal QBuffer (buffer_).

Parameters
opaquePointer to the QBuffer instance.
bufBuffer to read data into.
buf_sizeSize of the buffer.
Returns
Number of bytes read, or 0 if the end of buffer is reached.
Here is the caller graph for this function:

◆ ReleaseResources()

void VideoDecoder::ReleaseResources ( )
inline

Releases all FFmpeg and internal AudioDecoder resources. Calls CleanupFFmpegResources(). This operation is thread-safe.

Here is the call graph for this function:

◆ Reset()

void VideoDecoder::Reset ( )

Resets the playback position to the beginning of the video. Pauses playback, seeks both video and internal audio decoder (if present) to 0, resets internal state flags (finished, first frame), and wakes the thread. This operation is thread-safe.

Here is the call graph for this function:

◆ run()

void VideoDecoder::run ( )
overrideprotected

The main function executed by the QThread. Contains the loop that reads packets, decodes video frames, handles seeking/pausing, synchronizes with the internal audio decoder (if present) or uses frame timing, and emits decoded frames via the frameReady signal.

Here is the call graph for this function:

◆ Seek()

void VideoDecoder::Seek ( double position)

Seeks to a specific position in the video stream. Seeks the internal audio decoder (if present) and sets the seeking flag and target timestamp for the video stream. The actual video seek operation happens within the run() loop. This operation is thread-safe.

Parameters
positionThe target position in seconds from the beginning of the video.
Here is the call graph for this function:

◆ SeekPacket()

int64_t VideoDecoder::SeekPacket ( void * opaque,
int64_t offset,
int whence )
staticprivate

Custom seek function for FFmpeg's AVIOContext. Adjusts the position within the internal QBuffer (buffer_). Supports SEEK_SET and AVSEEK_SIZE.

Parameters
opaquePointer to the QBuffer instance.
offsetThe offset to seek to/by.
whenceThe seeking mode (SEEK_SET, AVSEEK_SIZE).
Returns
The new buffer position, or the total size if whence is AVSEEK_SIZE, or -1 on error.
Here is the caller graph for this function:

◆ SetVolume()

void VideoDecoder::SetVolume ( float volume) const

Sets the playback volume (delegated to the internal AudioDecoder). Has no effect if there is no audio stream. This operation is thread-safe.

Parameters
volumeThe desired volume level (0.0 to 1.0).

◆ Stop()

void VideoDecoder::Stop ( )

Stops the decoding thread and playback gracefully. Sets the stopped_ flag, stops the internal audio decoder (if present), and wakes the thread if it's waiting. The thread will then exit its run loop. This operation is thread-safe.

Here is the caller graph for this function:

◆ UpdateAudioPosition

void VideoDecoder::UpdateAudioPosition ( double position)
privateslot

Slot connected to the internal AudioDecoder's positionChanged signal. Updates the internal current_audio_position_ and emits the main positionChanged() signal.

Parameters
positionThe current audio playback position in seconds.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ videoInfo

void VideoDecoder::videoInfo ( int width,
int height,
double fps,
double duration,
bool has_audio )
signal

Emitted after successful initialization, providing video stream details.

Parameters
widthThe width of the video in pixels.
heightThe height of the video in pixels.
fpsThe calculated average frame rate in frames per second.
durationThe total duration of the video in seconds.
has_audioTrue if an audio stream was detected, false otherwise.
Here is the caller graph for this function:

Member Data Documentation

◆ audio_decoder_

AudioDecoder* VideoDecoder::audio_decoder_ = nullptr
private

Pointer to the internal AudioDecoder instance (if audio stream exists).

◆ audio_finished_

bool VideoDecoder::audio_finished_ = false
private

Flag indicating if the internal AudioDecoder has finished playback. Access protected by mutex_.

◆ audio_initialized_

bool VideoDecoder::audio_initialized_ = false
private

Flag indicating if the internal AudioDecoder has been successfully initialized.

◆ audio_stream_index_

int VideoDecoder::audio_stream_index_ = -1
private

Index of the audio stream within the format context.

◆ buffer_

QBuffer VideoDecoder::buffer_
private

QBuffer used by FFmpeg's custom I/O context to read video_data_.

◆ codec_context_

AVCodecContext* VideoDecoder::codec_context_ = nullptr
private

FFmpeg context for the video codec.

◆ current_audio_position_

double VideoDecoder::current_audio_position_ = 0.0
private

Current playback position reported by the internal AudioDecoder. Access protected by mutex_.

◆ current_position_

double VideoDecoder::current_position_ = 0.0
private

Current estimated playback position in seconds (used if no audio).

◆ duration_

double VideoDecoder::duration_ = 0.0
private

Total duration of the video in seconds.

◆ first_frame_

bool VideoDecoder::first_frame_ = true
private

Flag indicating if the current frame is the first one after start/seek.

◆ format_context_

AVFormatContext* VideoDecoder::format_context_ = nullptr
private

FFmpeg context for handling the container format (e.g., MP4, WebM).

◆ frame_

AVFrame* VideoDecoder::frame_ = nullptr
private

FFmpeg frame structure to hold decoded video data.

◆ frame_rate_

double VideoDecoder::frame_rate_ = 0.0
private

Calculated average frame rate of the video in frames per second.

◆ frame_timer_

QElapsedTimer VideoDecoder::frame_timer_
private

Timer used for frame timing synchronization when no audio is present.

◆ io_context_

AVIOContext* VideoDecoder::io_context_ = nullptr
private

FFmpeg context for custom I/O operations (reading from memory).

◆ last_frame_pts_

int64_t VideoDecoder::last_frame_pts_ = AV_NOPTS_VALUE
private

Presentation timestamp (PTS) of the previously decoded frame (used for frame timing).

◆ mutex_

QMutex VideoDecoder::mutex_
mutableprivate

Mutex protecting access to shared state variables (paused_, stopped_, seeking_, etc.).

◆ paused_

bool VideoDecoder::paused_ = false
private

Flag indicating if playback is currently paused. Access protected by mutex_.

◆ seek_position_

int64_t VideoDecoder::seek_position_ = -1
private

Target timestamp (in video stream timebase) for the pending seek operation. Access protected by mutex_.

◆ seeking_

bool VideoDecoder::seeking_ = false
private

Flag indicating if a seek operation is pending. Access protected by mutex_.

◆ stopped_

bool VideoDecoder::stopped_ = false
private

Flag indicating if the thread should stop execution. Access protected by mutex_.

◆ sws_context_

SwsContext* VideoDecoder::sws_context_ = nullptr
private

FFmpeg context for image scaling and pixel format conversion (to RGB24).

◆ video_data_

QByteArray VideoDecoder::video_data_
private

The raw video data provided in the constructor.

◆ video_finished_

bool VideoDecoder::video_finished_ = false
private

Flag indicating if the video stream has reached the end. Access protected by mutex_.

◆ video_stream_

int VideoDecoder::video_stream_ = -1
private

Index of the video stream within the format context.

◆ wait_condition_

QWaitCondition VideoDecoder::wait_condition_
private

Condition variable used to pause/resume the decoding thread.


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