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

Decodes and plays audio data using FFmpeg libraries in a separate thread. More...

#include <audio_decoder.h>

Inheritance diagram for AudioDecoder:
Collaboration diagram for AudioDecoder:

Signals

void audioInfo (int sample_rate, int channels, double duration)
 Emitted after successful initialization, providing audio stream details.
 
void error (const QString &message)
 Emitted when an error occurs during initialization or decoding.
 
void playbackFinished ()
 Emitted when the decoder reaches the end of the audio stream.
 
void positionChanged (double position)
 Emitted periodically during playback to indicate the current position.
 

Public Member Functions

 AudioDecoder (const QByteArray &audio_data, QObject *parent=nullptr)
 Constructs an AudioDecoder object. Initializes internal state, allocates memory for FFmpeg's custom I/O context, and copies the provided audio data into an internal buffer.
 
float GetVolume () const
 Gets the current playback volume. This operation is thread-safe.
 
bool Initialize ()
 Initializes the FFmpeg components and QAudioOutput for playback. Opens the input stream using the custom I/O context, finds the audio stream and codec, opens the codec, sets up the resampler (to convert to PCM S16LE stereo 44.1 kHz), configures and starts QAudioOutput. Emits audioInfo upon success. This operation is thread-safe and should be called before starting the thread.
 
bool IsDecoderRunning () const
 Checks if the decoding thread is currently running.
 
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. Wakes the thread if it was waiting due to being paused. This operation is thread-safe.
 
bool Reinitialize ()
 Reinitializes the decoder after it has been stopped or encountered an error. Releases existing resources, resets state flags (paused, stopped, seeking, position), reallocates I/O buffer and context if necessary. Does not automatically start playback. This operation is thread-safe.
 
void ReleaseResources ()
 Releases all FFmpeg and Qt Multimedia resources. Stops audio output, frees contexts (format, codec, resampler, I/O), frames, and buffers. Resets the initialization flag. This operation is thread-safe.
 
void Reset ()
 Resets the playback position to the beginning (0 seconds). Seeks the FFmpeg format context, flushes codec buffers, resets the internal position counter, resets the audio output device, and emits positionChanged(0). This operation is thread-safe.
 
void Seek (double position)
 Seeks to a specific position in the audio stream. The position is specified in seconds. Sets the seeking_ flag and wakes the thread. The actual seek operation happens within the run() loop. This operation is thread-safe.
 
void SetVolume (float volume) const
 Sets the playback volume. The volume is a linear factor between 0.0 (silent) and 1.0 (full volume). This operation is thread-safe.
 
void Stop ()
 Stops the decoding thread and playback gracefully. Sets the stopped_ flag and wakes the thread if it's waiting. The thread will then exit its run loop. This operation is thread-safe.
 
 ~AudioDecoder () override
 Destructor. Stops the decoding thread, waits for it to finish, and releases all allocated resources.
 

Protected Member Functions

void DecodeAudioFrame (const AVFrame *audio_frame) const
 Decodes a single audio frame using the FFmpeg resampler and writes the result to the audio device.
 
void run () override
 The main function executed by the QThread. Contains the loop that reads packets, decodes frames, handles seeking/pausing, updates playback position, and sends decoded audio data to the output device.
 

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 audio_data_ QByteArray buffer.
 
static int64_t SeekPacket (void *opaque, int64_t offset, int whence)
 Custom seek function for FFmpeg's AVIOContext. Adjusts the internal read_position_ based on the offset and whence parameters. Supports SEEK_SET, SEEK_CUR, SEEK_END, and AVSEEK_SIZE.
 

Private Attributes

AVCodecContext * audio_codec_context_ = nullptr
 FFmpeg context for the audio codec.
 
QByteArray audio_data_
 The raw audio data provided in the constructor.
 
QIODevice * audio_device_ = nullptr
 Qt I/O device associated with audio_output_, used for writing PCM data.
 
QAudioFormat audio_format_
 Qt audio format description (PCM S16LE stereo 44.1kHz).
 
AVFrame * audio_frame_ = nullptr
 FFmpeg frame structure to hold decoded audio data.
 
QAudioOutput * audio_output_ = nullptr
 Qt Multimedia object for audio output.
 
int audio_stream_ = -1
 Index of the audio stream within the format context.
 
double current_position_ = 0
 Current playback position in seconds.
 
AVFormatContext * format_context_ = nullptr
 FFmpeg context for handling the container format.
 
bool initialized_ = false
 Flag indicating if the Initialize() method has completed successfully.
 
unsigned char * io_buffer_ = nullptr
 Buffer used by the custom I/O context to hold audio_data_.
 
AVIOContext * io_context_ = nullptr
 FFmpeg context for custom I/O operations (reading from memory).
 
QMutex mutex_
 Mutex protecting access to shared state variables from different threads.
 
bool paused_ = true
 Flag indicating if playback is currently paused.
 
bool reached_end_of_stream_ = false
 Flag indicating if the end of the audio stream has been reached.
 
int read_position_ = 0
 Current read position within audio_data_ for the custom I/O context.
 
int64_t seek_position_ = 0
 Target timestamp for the pending seek operation (in stream timebase).
 
bool seeking_ = false
 Flag indicating if a seek operation is pending.
 
bool stopped_ = false
 Flag indicating if the thread should stop execution.
 
SwrContext * swr_context_ = nullptr
 FFmpeg context for audio resampling (format/rate/channel conversion).
 
QWaitCondition wait_condition_
 Condition variable used to pause/resume the decoding thread.
 

Detailed Description

Decodes and plays audio data using FFmpeg libraries in a separate thread.

This class takes raw audio data (e.g., from a file) as a QByteArray, uses FFmpeg (libavformat, libavcodec, libswresample) to decode it, and plays the resulting PCM audio using Qt Multimedia (QAudioOutput). It runs the decoding and playback loop in a separate QThread to avoid blocking the main UI thread. It supports pausing, seeking, volume control, and provides signals for status updates (errors, position, finish).

Constructor & Destructor Documentation

◆ AudioDecoder()

AudioDecoder::AudioDecoder ( const QByteArray & audio_data,
QObject * parent = nullptr )
explicit

Constructs an AudioDecoder object. Initializes internal state, allocates memory for FFmpeg's custom I/O context, and copies the provided audio data into an internal buffer.

Parameters
audio_dataThe raw audio data to be decoded.
parentOptional parent QObject.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ~AudioDecoder()

AudioDecoder::~AudioDecoder ( )
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

◆ audioInfo

void AudioDecoder::audioInfo ( int sample_rate,
int channels,
double duration )
signal

Emitted after successful initialization, providing audio stream details.

Parameters
sample_rateThe sample rate of the audio in Hz.
channelsThe number of audio channels.
durationThe total duration of the audio in seconds.
Here is the caller graph for this function:

◆ DecodeAudioFrame()

void AudioDecoder::DecodeAudioFrame ( const AVFrame * audio_frame) const
protected

Decodes a single audio frame using the FFmpeg resampler and writes the result to the audio device.

Converts the input frame (audio_frame) to the target format (PCM S16LE stereo 44.1 kHz), allocates a buffer for the converted data, performs the conversion using swr_convert, and writes the resulting data to the QAudioOutput device (audio_device_). Includes logic to wait if the audio device buffer is nearly full. This method is thread-safe regarding access to shared decoder state via mutex_.

Parameters
audio_frameThe raw audio frame received from the FFmpeg decoder.
Here is the caller graph for this function:

◆ error

void AudioDecoder::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:

◆ GetVolume()

float AudioDecoder::GetVolume ( ) const

Gets the current playback volume. This operation is thread-safe.

Returns
The current volume level (0.0 to 1.0).

◆ Initialize()

bool AudioDecoder::Initialize ( )

Initializes the FFmpeg components and QAudioOutput for playback. Opens the input stream using the custom I/O context, finds the audio stream and codec, opens the codec, sets up the resampler (to convert to PCM S16LE stereo 44.1 kHz), configures and starts QAudioOutput. Emits audioInfo 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:

◆ IsDecoderRunning()

bool AudioDecoder::IsDecoderRunning ( ) const
inline

Checks if the decoding thread is currently running.

Returns
True if the thread is running, false otherwise.

◆ IsPaused()

bool AudioDecoder::IsPaused ( ) const

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

Returns
True if paused, false otherwise.

◆ Pause()

void AudioDecoder::Pause ( )

Toggles the paused state of the playback. If paused, playback stops; if unpaused, playback resumes. Wakes the thread if it was waiting due to being paused. This operation is thread-safe.

◆ playbackFinished

void AudioDecoder::playbackFinished ( )
signal

Emitted when the decoder reaches the end of the audio stream.

Here is the caller graph for this function:

◆ positionChanged

void AudioDecoder::positionChanged ( double position)
signal

Emitted periodically during playback to indicate the current position.

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

◆ ReadPacket()

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

Custom read function for FFmpeg's AVIOContext. Reads data from the internal audio_data_ QByteArray buffer.

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

◆ Reinitialize()

bool AudioDecoder::Reinitialize ( )

Reinitializes the decoder after it has been stopped or encountered an error. Releases existing resources, resets state flags (paused, stopped, seeking, position), reallocates I/O buffer and context if necessary. Does not automatically start playback. This operation is thread-safe.

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

◆ ReleaseResources()

void AudioDecoder::ReleaseResources ( )

Releases all FFmpeg and Qt Multimedia resources. Stops audio output, frees contexts (format, codec, resampler, I/O), frames, and buffers. Resets the initialization flag. This operation is thread-safe.

Here is the caller graph for this function:

◆ Reset()

void AudioDecoder::Reset ( )

Resets the playback position to the beginning (0 seconds). Seeks the FFmpeg format context, flushes codec buffers, resets the internal position counter, resets the audio output device, and emits positionChanged(0). This operation is thread-safe.

Here is the call graph for this function:

◆ run()

void AudioDecoder::run ( )
overrideprotected

The main function executed by the QThread. Contains the loop that reads packets, decodes frames, handles seeking/pausing, updates playback position, and sends decoded audio data to the output device.

Here is the call graph for this function:

◆ Seek()

void AudioDecoder::Seek ( double position)

Seeks to a specific position in the audio stream. The position is specified in seconds. Sets the seeking_ flag and wakes the thread. The actual seek operation happens within the run() loop. This operation is thread-safe.

Parameters
positionThe target position in seconds from the beginning of the audio.

◆ SeekPacket()

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

Custom seek function for FFmpeg's AVIOContext. Adjusts the internal read_position_ based on the offset and whence parameters. Supports SEEK_SET, SEEK_CUR, SEEK_END, and AVSEEK_SIZE.

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

◆ SetVolume()

void AudioDecoder::SetVolume ( float volume) const

Sets the playback volume. The volume is a linear factor between 0.0 (silent) and 1.0 (full volume). This operation is thread-safe.

Parameters
volumeThe desired volume level (0.0 to 1.0).

◆ Stop()

void AudioDecoder::Stop ( )

Stops the decoding thread and playback gracefully. Sets the stopped_ flag 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:

Member Data Documentation

◆ audio_codec_context_

AVCodecContext* AudioDecoder::audio_codec_context_ = nullptr
private

FFmpeg context for the audio codec.

◆ audio_data_

QByteArray AudioDecoder::audio_data_
private

The raw audio data provided in the constructor.

◆ audio_device_

QIODevice* AudioDecoder::audio_device_ = nullptr
private

Qt I/O device associated with audio_output_, used for writing PCM data.

◆ audio_format_

QAudioFormat AudioDecoder::audio_format_
private

Qt audio format description (PCM S16LE stereo 44.1kHz).

◆ audio_frame_

AVFrame* AudioDecoder::audio_frame_ = nullptr
private

FFmpeg frame structure to hold decoded audio data.

◆ audio_output_

QAudioOutput* AudioDecoder::audio_output_ = nullptr
private

Qt Multimedia object for audio output.

◆ audio_stream_

int AudioDecoder::audio_stream_ = -1
private

Index of the audio stream within the format context.

◆ current_position_

double AudioDecoder::current_position_ = 0
private

Current playback position in seconds.

◆ format_context_

AVFormatContext* AudioDecoder::format_context_ = nullptr
private

FFmpeg context for handling the container format.

◆ initialized_

bool AudioDecoder::initialized_ = false
private

Flag indicating if the Initialize() method has completed successfully.

◆ io_buffer_

unsigned char* AudioDecoder::io_buffer_ = nullptr
private

Buffer used by the custom I/O context to hold audio_data_.

◆ io_context_

AVIOContext* AudioDecoder::io_context_ = nullptr
private

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

◆ mutex_

QMutex AudioDecoder::mutex_
mutableprivate

Mutex protecting access to shared state variables from different threads.

◆ paused_

bool AudioDecoder::paused_ = true
private

Flag indicating if playback is currently paused.

◆ reached_end_of_stream_

bool AudioDecoder::reached_end_of_stream_ = false
private

Flag indicating if the end of the audio stream has been reached.

◆ read_position_

int AudioDecoder::read_position_ = 0
private

Current read position within audio_data_ for the custom I/O context.

◆ seek_position_

int64_t AudioDecoder::seek_position_ = 0
private

Target timestamp for the pending seek operation (in stream timebase).

◆ seeking_

bool AudioDecoder::seeking_ = false
private

Flag indicating if a seek operation is pending.

◆ stopped_

bool AudioDecoder::stopped_ = false
private

Flag indicating if the thread should stop execution.

◆ swr_context_

SwrContext* AudioDecoder::swr_context_ = nullptr
private

FFmpeg context for audio resampling (format/rate/channel conversion).

◆ wait_condition_

QWaitCondition AudioDecoder::wait_condition_
private

Condition variable used to pause/resume the decoding thread.


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