|
Wavelength
Privacy-focused, cross-platform, and open-source communication application
|
Decodes video data frame by frame using FFmpeg libraries in a separate thread. More...
#include <video_decoder.h>
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 | |
| AudioDecoder * | audio_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. | |
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.
|
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.
| video_data | The raw video data to be decoded. |
| parent | Optional parent QObject. |
|
override |
Destructor. Stops the decoding thread, waits for it to finish, and releases all allocated resources.
|
private |
Releases all FFmpeg resources (contexts, frames, scaler) and deletes the internal AudioDecoder. Resets internal state variables related to FFmpeg and audio.
|
signal |
Emitted when an error occurs during initialization or decoding.
| message | A description of the error. |
| 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.
|
signal |
Emitted for each decoded video frame.
| frame | The decoded frame as a QImage (Format_RGB888). A copy is emitted. |
| 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.
|
inlineprivateslot |
Slot connected to the internal AudioDecoder's error signal. Relays the audio error message via the main error() signal.
| message | The error message from the AudioDecoder. |
|
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.
|
inline |
Checks if the video file contains an audio stream.
| 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.
|
inline |
Checks if the playback is currently paused. This operation is thread-safe.
| 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.
|
signal |
Emitted when both video and audio (if present) streams reach the end.
|
signal |
Emitted periodically during playback to indicate the current position (based on audio if available, otherwise estimated).
| position | The current playback position in seconds. |
|
staticprivate |
Custom read function for FFmpeg's AVIOContext. Reads data from the internal QBuffer (buffer_).
| opaque | Pointer to the QBuffer instance. |
| buf | Buffer to read data into. |
| buf_size | Size of the buffer. |
|
inline |
Releases all FFmpeg and internal AudioDecoder resources. Calls CleanupFFmpegResources(). This operation is thread-safe.
| 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.
|
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.
| 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.
| position | The target position in seconds from the beginning of the video. |
|
staticprivate |
Custom seek function for FFmpeg's AVIOContext. Adjusts the position within the internal QBuffer (buffer_). Supports SEEK_SET and AVSEEK_SIZE.
| opaque | Pointer to the QBuffer instance. |
| offset | The offset to seek to/by. |
| whence | The seeking mode (SEEK_SET, AVSEEK_SIZE). |
| 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.
| volume | The desired volume level (0.0 to 1.0). |
| 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.
|
privateslot |
Slot connected to the internal AudioDecoder's positionChanged signal. Updates the internal current_audio_position_ and emits the main positionChanged() signal.
| position | The current audio playback position in seconds. |
|
signal |
Emitted after successful initialization, providing video stream details.
| width | The width of the video in pixels. |
| height | The height of the video in pixels. |
| fps | The calculated average frame rate in frames per second. |
| duration | The total duration of the video in seconds. |
| has_audio | True if an audio stream was detected, false otherwise. |
|
private |
Pointer to the internal AudioDecoder instance (if audio stream exists).
|
private |
Flag indicating if the internal AudioDecoder has finished playback. Access protected by mutex_.
|
private |
Flag indicating if the internal AudioDecoder has been successfully initialized.
|
private |
Index of the audio stream within the format context.
|
private |
QBuffer used by FFmpeg's custom I/O context to read video_data_.
|
private |
FFmpeg context for the video codec.
|
private |
Current playback position reported by the internal AudioDecoder. Access protected by mutex_.
|
private |
Current estimated playback position in seconds (used if no audio).
|
private |
Total duration of the video in seconds.
|
private |
Flag indicating if the current frame is the first one after start/seek.
|
private |
FFmpeg context for handling the container format (e.g., MP4, WebM).
|
private |
FFmpeg frame structure to hold decoded video data.
|
private |
Calculated average frame rate of the video in frames per second.
|
private |
Timer used for frame timing synchronization when no audio is present.
|
private |
FFmpeg context for custom I/O operations (reading from memory).
|
private |
Presentation timestamp (PTS) of the previously decoded frame (used for frame timing).
|
mutableprivate |
Mutex protecting access to shared state variables (paused_, stopped_, seeking_, etc.).
|
private |
Flag indicating if playback is currently paused. Access protected by mutex_.
|
private |
Target timestamp (in video stream timebase) for the pending seek operation. Access protected by mutex_.
|
private |
Flag indicating if a seek operation is pending. Access protected by mutex_.
|
private |
Flag indicating if the thread should stop execution. Access protected by mutex_.
|
private |
FFmpeg context for image scaling and pixel format conversion (to RGB24).
|
private |
The raw video data provided in the constructor.
|
private |
Flag indicating if the video stream has reached the end. Access protected by mutex_.
|
private |
Index of the video stream within the format context.
|
private |
Condition variable used to pause/resume the decoding thread.