Difference between revisions of "Hacker Guide/Audio Output"
Line 6: | Line 6: | ||
== Writing an audio output module == | == Writing an audio output module == | ||
+ | For more details on writing modules in general, see [[Documentation:Hacker's Guide/Module Writers Guide]]. | ||
An audio output module should be declared with the correct capability and category as follows: | An audio output module should be declared with the correct capability and category as follows: | ||
Line 11: | Line 12: | ||
set_category(CAT_AUDIO) | set_category(CAT_AUDIO) | ||
set_subcategory(SUBCAT_AUDIO_AOUT) | set_subcategory(SUBCAT_AUDIO_AOUT) | ||
+ | set_callbacks(Open, Close) | ||
+ | |||
+ | (Note: The callbacks name can be different. We use Open() and Close() in this example.) | ||
+ | |||
+ | Instances of an audio output module should store their private internal state (if any) as an aout_sys_t structure: | ||
− | + | struct aout_sys_t | |
+ | { | ||
+ | /* ... */ | ||
+ | }; | ||
=== Priority === | === Priority === | ||
Line 22: | Line 31: | ||
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: | ||
− | |||
− | |||
− | |||
− | |||
− | |||
static int Open (vlc_object_t *obj) | static int Open (vlc_object_t *obj) | ||
Line 78: | Line 82: | ||
=== Format === | === Format === | ||
− | The format is usually VLC_CODEC_FL32 (float) on desktop systems. | + | The initial format when Open() starts, is usually VLC_CODEC_FL32 (float) on desktop systems, but not always. |
+ | All formats are implicitly channel-interleaved. Uninterleaved audio is never used. For instance, stereo audio is ordered as: | ||
+ | * first left channel value, | ||
+ | * first right channel value, | ||
+ | * second left channel value, | ||
+ | * second right channel value, | ||
+ | * etc. | ||
+ | |||
+ | Currently, the following formats are supported: | ||
{| | {| | ||
!FOURCC | !FOURCC | ||
Line 215: | Line 227: | ||
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. | 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. | ||
+ | |||
+ | If the returned format differs from the one specified by LibVLC core upon entry, then LibVLC will insert any required conversion filter automatically. So '''do not convert manually''' in the output module! | ||
==== S/PDIF ==== | ==== S/PDIF ==== |
Revision as of 09:43, 16 October 2011
Contents
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
For more details on writing modules in general, see Documentation:Hacker's Guide/Module Writers Guide. 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) set_callbacks(Open, Close)
(Note: The callbacks name can be different. We use Open() and Close() in this example.)
Instances of an audio output module should store their private internal state (if any) as an aout_sys_t structure:
struct aout_sys_t { /* ... */ };
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:
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 initial format when Open() starts, is usually VLC_CODEC_FL32 (float) on desktop systems, but not always. All formats are implicitly channel-interleaved. Uninterleaved audio is never used. For instance, stereo audio is ordered as:
- first left channel value,
- first right channel value,
- second left channel value,
- second right channel value,
- etc.
Currently, the following formats are supported:
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.
If the returned format differs from the one specified by LibVLC core upon entry, then LibVLC will insert any required conversion filter automatically. So do not convert manually in the output module!
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!