Libopus Decoder State Internal Data Structure

This article provides a technical overview of the internal data structure used to maintain decoder state in the libopus reference implementation of the Opus audio codec. We will identify the primary state structure, examine its layout, and explain how it manages the dual-engine nature of the hybrid SILK and CELT codecs.

The primary internal data structure that holds the decoder state in libopus is struct OpusDecoder (commonly referred to by its typedef OpusDecoder).

Because libopus is designed with a highly encapsulated API, the definition of struct OpusDecoder is kept private and resides within the library’s source code (specifically in src/opus_decoder.c). This encapsulation ensures binary compatibility (ABI stability), preventing user applications from directly accessing or modifying the structure’s fields. Instead, applications interact with the state using a pointer to this opaque structure.

Layout of the OpusDecoder Structure

The OpusDecoder structure acts as a master controller that orchestrates the two underlying decoding technologies used by Opus: SILK (optimized for speech) and CELT (optimized for music and general audio).

Internally, struct OpusDecoder contains the following key components:

Memory Allocation and Initialization

Because the structure is opaque, client applications cannot instantiate it directly on the stack using standard C declarations. Libopus provides specific functions to handle its lifecycle:

  1. opus_decoder_get_size: This function returns the exact size in bytes required for the OpusDecoder structure based on the requested number of channels.
  2. opus_decoder_create: Dynamically allocates memory for the OpusDecoder structure on the heap and initializes it.
  3. opus_decoder_init: Initialises a pre-allocated memory block (which can reside on the stack or a custom memory pool) to act as the OpusDecoder state.