Difference between revisions of "Hacker Guide/Audio Output"

From VideoLAN Wiki
Jump to navigation Jump to search
Line 22: Line 22:
 
The audio output will be probed and initialized with the typical Open() callback.
 
The audio output will be probed and initialized with the typical Open() callback.
 
The audio output should check the input audio format in audio_output_t.format:
 
The audio output should check the input audio format in audio_output_t.format:
 +
 +
struct aout_sys_t
 +
{
 +
    /* ... */
 +
};
  
 
  static int Open (vlc_object_t *obj)
 
  static int Open (vlc_object_t *obj)
 
  {
 
  {
 
     audio_output_t *aout = (audio_output_t *)obj;
 
     audio_output_t *aout = (audio_output_t *)obj;
 
+
    aout_sys_t *sys;
 +
   
 +
    /* Check input format */
 
     vlc_fourcc_t format = aout->format.i_format;
 
     vlc_fourcc_t format = aout->format.i_format;
 
     unsigned samplerate = aout->format.i_rate;
 
     unsigned samplerate = aout->format.i_rate;
 
     unsigned channels = aout_FormatNbChannels(&aout->format);
 
     unsigned channels = aout_FormatNbChannels(&aout->format);
 +
   
 +
    /* Initialize audio subsystem */
 +
    sys = malloc (sizeof (*sys));
 +
    if (unlikely(sys == NULL))
 +
        return VLC_ENOMEM;
 +
    /* ... */
 +
    if (failure)
 +
    {
 +
        free (sys);
 +
        return VLC_EGENERIC;
 +
    }
 +
   
 +
    /* Adjust format to stereo */
 +
    aout->format.i_original_channels =
 +
    aout->format.i_physical_channels = AOUT_CHAN_LEFT|AOUT_CHAN_RIGHT;
 +
    /* aout->format.i_format = VLC_CODEC_S16N; */
 +
    /* aout->format.i_rate = 48000; */
 +
   
 +
    /* Setup callbacks */
 +
    aout->sys = sys;
 +
    aout->pf_play = Play;
 +
    aout->pf_pause = Pause;
 +
    aout->pf_flush = Flush;
 +
    aout_VolumeSoftInit (aout);
 +
    return VLC_SUCCESS;
 +
}
 +
 +
When done, the audio output module will be deinitialized:
 +
 +
static void Close (vlc_object_t *obj)
 +
{
 +
    audio_output_t *aout = (audio_output_t)obj;
 +
    aout_sys_t *sys = aout->sys;
 +
 +
    /* Deinitialize */
 
     /* ... */
 
     /* ... */
 +
 +
    free (sys);
 
  }
 
  }
  

Revision as of 09:35, 16 October 2011

Description

An audio output module is used to pass decoded audio frames to the audio output hardware. Normally, the audio frames contain an integral number of audio samples coded linearly, i.e. PCM. However, to address the need for digital audio pass-through, the audio output may also receive coded audio frames encapsulated as S/PDIF packets.

This describes the fourth version of the audio output layer, found in VLC version 1.2.0. Versions 0.5.0 to 1.1.x were based on a partly similar but nevertheless incompatible interface known as aout3.

Writing an audio output module

An audio output module should be declared with the correct capability and category as follows:

set_capability("audio output", 60)
set_category(CAT_AUDIO)
set_subcategory(SUBCAT_AUDIO_AOUT)

For more details on writing modules in general, see Documentation:Hacker's Guide/Module Writers Guide.

Priority

Unless a specific module has been provisioned in the VLC preferences, or specified through the --aout command line parameter, LibVLC will try to each audio output module in order of decreasing priority until one succeeds. As usual modules with a priority of zero will never be probed unless configured explicitly.

Thus, on Linux for instance, the PulseAudio module has a higher priority than the ALSA one, and the OSS module has the smallest (non-zero) priority. The file audio output has zero priority and will not be used normally. This is so that VLC uses PulseAudio if available, otherwise ALSA, otherwise OSS.

Initialization

The audio output will be probed and initialized with the typical Open() callback. The audio output should check the input audio format in audio_output_t.format:

struct aout_sys_t
{
    /* ... */
};
static int Open (vlc_object_t *obj)
{
    audio_output_t *aout = (audio_output_t *)obj;
    aout_sys_t *sys;
    
    /* Check input format */
    vlc_fourcc_t format = aout->format.i_format;
    unsigned samplerate = aout->format.i_rate;
    unsigned channels = aout_FormatNbChannels(&aout->format);
    
    /* Initialize audio subsystem */ 
    sys = malloc (sizeof (*sys));
    if (unlikely(sys == NULL))
        return VLC_ENOMEM;
    /* ... */
    if (failure)
    {
        free (sys);
        return VLC_EGENERIC;
    }
    
    /* Adjust format to stereo */
    aout->format.i_original_channels =
    aout->format.i_physical_channels = AOUT_CHAN_LEFT|AOUT_CHAN_RIGHT;
    /* aout->format.i_format = VLC_CODEC_S16N; */
    /* aout->format.i_rate = 48000; */
    
    /* Setup callbacks */
    aout->sys = sys;
    aout->pf_play = Play;
    aout->pf_pause = Pause;
    aout->pf_flush = Flush;
    aout_VolumeSoftInit (aout);
    return VLC_SUCCESS;
}

When done, the audio output module will be deinitialized:

static void Close (vlc_object_t *obj)
{
    audio_output_t *aout = (audio_output_t)obj;
    aout_sys_t *sys = aout->sys;
    /* Deinitialize */
    /* ... */
    free (sys);
}

Format

The format is usually VLC_CODEC_FL32 (float) on desktop systems. The possible format values follow:

FOURCC Description C type Endianess On entry On return
VLC_CODEC_FL32 Single precision float Native With FPU Allowed
VLC_CODEC_FI32 Fixed-point int32_t Native Without FPU Forbidden
VLC_CODEC_S16N Signed 16-bits int16_t Native Without FPU Allowed
VLC_CODEC_F32L Single precision float Little With little endian FPU Allowed
VLC_CODEC_F32B Single precision float Big With big endian FPU Allowed
VLC_CODEC_F64L Double precision double Little Never Allowed
VLC_CODEC_F64B Double precision double Big Never Allowed
VLC_CODEC_S16L Signed 16-bits int16_t Little Without FPU Allowed
VLC_CODEC_S16B Signed 16-bits int16_t Big Without FPU Allowed
VLC_CODEC_S24L Signed 24-bits N/A Little Never Allowed
VLC_CODEC_S24B Signed 24-bits N/A Big Never Allowed
VLC_CODEC_S32L Signed 32-bits int32_t Little Never Allowed
VLC_CODEC_S32B Signed 32-bits int32_t Big Never Allowed
VLC_CODEC_A52 AC-3 / Dolby Non-linear N/A A52 input Forbidden
VLC_CODEC_DTS DTS Coherent Acoustics Non-linear N/A DTS input Forbidden
VLC_CODEC_MPGA MPEG 2 Audio Non-linear N/A MPEG input Forbidden
VLC_CODEC_SPDIFL S/PDIF uint16_t Little Never Allowed (S/PDIF)
VLC_CODEC_SPDIFB S/PDIF uint16_t Big Never Allowed (S/PDIF)

The "on entry" column indicates in which situation (if any), the format may be presented by the LibVLC core to the audio output Open() callback. The "on return" column determines if the format is supported for actual output.

S/PDIF

If and only if the format on entry is non-linear, the audio output module can enable digital pass-through mode. To do so, it must set the audio output format to VLC_CODEC_SPDIFL (or VLC_CODEC_SPDIFB). If on the contrary pass-through is not to be used, then the format must be set to a linear FOURCC, usually VLC_CODEC_FL32 or VLC_CODEC_S16N.

Convenience aliases

VLC_CODEC_FL32 is an alias for VLC_CODEC_F32L or VLC_CODEC_F32B depending on architecture endianess. The full list of convenience native endianess FOURCC is

  • VLC_CODEC_FL32 (float)
  • VLC_CODEC_FL64 (double)
  • VLC_CODEC_S32N (int32_t)
  • VLC_CODEC_S24N (N/A)
  • VLC_CODEC_S16N (int16_t)
  • VLC_CODEC_U16N (uint16_t)

Sample rate and channels

The sample rate is the sample rate that comes from the decoder or the audio filters, so is the channel mapping.

If possible, it is recommended that the audio output uses a format as close to the input as possible. This is to conversion and loss of quality. Nevertheless, it is often necessary to use different a output format due to hardware limitation: - resample if the aout->format.i_rate is modified, - remix the channels if aout->format.i_physical_channels and/or aout->format.i_original_channels are modified, - convert the sample format is aout->format.i_format is modified.

Warning

Beware that the Open() callback must not change aout->format until it is absolutely certain to return VLC_SUCCESS (0). If it were to change the format and then return an initialization failure, subsequent modules would get corrupt informations about the input format!