vlc_aout.h 24.5 KB
Newer Older
1
/*****************************************************************************
2
 * vlc_aout.h : audio output interface
3
 *****************************************************************************
Jean-Baptiste Kempf's avatar
LGPL    
Jean-Baptiste Kempf committed
4
 * Copyright (C) 2002-2011 VLC authors and VideoLAN
5
 *
6
 * Authors: Christophe Massiot <massiot@via.ecp.fr>
7
 *
Jean-Baptiste Kempf's avatar
LGPL    
Jean-Baptiste Kempf committed
8
9
10
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
11
 * (at your option) any later version.
12
 *
13
14
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Jean-Baptiste Kempf's avatar
LGPL    
Jean-Baptiste Kempf committed
15
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
17
 *
Jean-Baptiste Kempf's avatar
LGPL    
Jean-Baptiste Kempf committed
18
19
20
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21
 *****************************************************************************/
zorglub's avatar
zorglub committed
22

23
24
#ifndef VLC_AOUT_H
#define VLC_AOUT_H 1
zorglub's avatar
zorglub committed
25

26
#include <assert.h>
27
#include <vlc_list.h>
28

29
/**
30
31
32
 * \defgroup audio_output Audio output
 * \ingroup output
 * @{
33
 * \file
34
 * Audio output modules interface
35
36
 */

37
38
/* Buffers which arrive in advance of more than AOUT_MAX_ADVANCE_TIME
 * will be considered as bogus and be trashed */
39
#define AOUT_MAX_ADVANCE_TIME           (AOUT_MAX_PREPARE_TIME + VLC_TICK_FROM_SEC(1))
40
41
42

/* Buffers which arrive in advance of more than AOUT_MAX_PREPARE_TIME
 * will cause the calling thread to sleep */
43
#define AOUT_MAX_PREPARE_TIME           VLC_TICK_FROM_SEC(2)
44
45
46

/* Buffers which arrive after pts - AOUT_MIN_PREPARE_TIME will be trashed
 * to avoid too heavy resampling */
47
#define AOUT_MIN_PREPARE_TIME           AOUT_MAX_PTS_ADVANCE
48

49
50
51
/* Tolerance values from EBU Recommendation 37 */
/** Maximum advance of actual audio playback time to coded PTS,
 * above which downsampling will be performed */
52
#define AOUT_MAX_PTS_ADVANCE            VLC_TICK_FROM_MS(40)
53
54
55

/** Maximum delay of actual audio playback time from coded PTS,
 * above which upsampling will be performed */
56
#define AOUT_MAX_PTS_DELAY              VLC_TICK_FROM_MS(60)
57
58
59

/* Max acceptable resampling (in %) */
#define AOUT_MAX_RESAMPLING             10
60

61
#include "vlc_es.h"
Michel Kaempf's avatar
Michel Kaempf committed
62

63
#define AOUT_FMTS_IDENTICAL( p_first, p_second ) (                          \
64
    ((p_first)->i_format == (p_second)->i_format)                           \
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
65
      && AOUT_FMTS_SIMILAR(p_first, p_second) )
66

67
68
69
/* Check if i_rate == i_rate and i_channels == i_channels */
#define AOUT_FMTS_SIMILAR( p_first, p_second ) (                            \
    ((p_first)->i_rate == (p_second)->i_rate)                               \
70
      && ((p_first)->channel_type == (p_second)->channel_type)            \
71
      && ((p_first)->i_physical_channels == (p_second)->i_physical_channels)\
72
      && ((p_first)->i_chan_mode == (p_second)->i_chan_mode) )
73

74
75
76
#define AOUT_FMT_LINEAR( p_format ) \
    (aout_BitsPerSample((p_format)->i_format) != 0)

77
78
#define VLC_CODEC_SPDIFL VLC_FOURCC('s','p','d','i')
#define VLC_CODEC_SPDIFB VLC_FOURCC('s','p','d','b')
79

80
#define AOUT_FMT_SPDIF( p_format ) \
81
82
    ( ((p_format)->i_format == VLC_CODEC_SPDIFL)       \
       || ((p_format)->i_format == VLC_CODEC_SPDIFB)   \
83
       || ((p_format)->i_format == VLC_CODEC_A52)      \
84
       || ((p_format)->i_format == VLC_CODEC_DTS) )
85

Thomas Guillem's avatar
Thomas Guillem committed
86
87
#define AOUT_FMT_HDMI( p_format )                   \
    ( (p_format)->i_format == VLC_CODEC_EAC3        \
Thomas Guillem's avatar
Thomas Guillem committed
88
    ||(p_format)->i_format == VLC_CODEC_DTSHD       \
89
90
    ||(p_format)->i_format == VLC_CODEC_TRUEHD      \
    ||(p_format)->i_format == VLC_CODEC_MLP         \
Thomas Guillem's avatar
Thomas Guillem committed
91
92
    )

93
/* Values used for the audio-channels object variable */
94
#define AOUT_VAR_CHAN_UNSET         0 /* must be zero */
gbazin's avatar
   
gbazin committed
95
96
97
98
99
#define AOUT_VAR_CHAN_STEREO        1
#define AOUT_VAR_CHAN_RSTEREO       2
#define AOUT_VAR_CHAN_LEFT          3
#define AOUT_VAR_CHAN_RIGHT         4
#define AOUT_VAR_CHAN_DOLBYS        5
100
#define AOUT_VAR_CHAN_HEADPHONES    6
101
#define AOUT_VAR_CHAN_MONO          7
102

103
/*****************************************************************************
zorglub's avatar
zorglub committed
104
 * Main audio output structures
105
 *****************************************************************************/
zorglub's avatar
zorglub committed
106

Christophe Massiot's avatar
Christophe Massiot committed
107
108
/* Size of a frame for S/PDIF output. */
#define AOUT_SPDIF_SIZE 6144
109

110
/* Number of samples in an A/52 frame. */
111
#define A52_FRAME_NB 1536
112

113
/* FIXME to remove once aout.h is cleaned a bit more */
114
#include <vlc_block.h>
115

116
struct vlc_audio_output_events {
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
117
    void (*timing_report)(audio_output_t *, vlc_tick_t system_now, vlc_tick_t pts);
118
119
120
121
122
123
124
125
126
    void (*volume_report)(audio_output_t *, float);
    void (*mute_report)(audio_output_t *, bool);
    void (*policy_report)(audio_output_t *, bool);
    void (*device_report)(audio_output_t *, const char *);
    void (*hotplug_report)(audio_output_t *, const char *, const char *);
    void (*restart_request)(audio_output_t *, unsigned);
    int (*gain_request)(audio_output_t *, float);
};

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
127
128
129
130
131
132
133
134
135
136
137
138
139
/** Audio output object
 *
 * The audio output object is the abstraction for rendering decoded
 * (or pass-through) audio samples. In addition to playing samples,
 * the abstraction exposes controls for pause/resume, flush/drain,
 * changing the volume or mut flag, and listing and changing output device.
 *
 * An audio output can be in one of three different states:
 * stopped, playing or paused.
 * The audio output is always created in stopped state and is always destroyed
 * in that state also. It is moved from stopped to playing state by start(),
 * and from playing or paused states back to stopped state by stop().
 **/
140
struct audio_output
zorglub's avatar
zorglub committed
141
{
142
    struct vlc_object_t obj;
zorglub's avatar
zorglub committed
143

144
    void *sys; /**< Private data for callbacks */
145
146
147

    int (*start)(audio_output_t *, audio_sample_format_t *fmt);
    /**< Starts a new stream (mandatory, cannot be NULL).
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
148
149
150
151
152
      *
      * This callback changes the audio output from stopped to playing state
      * (if succesful). After the callback returns, time_get(), play(),
      * pause(), flush() and eventually stop() callbacks may be called.
      *
153
154
155
      * \param fmt input stream sample format upon entry,
      *            output stream sample format upon return [IN/OUT]
      * \return VLC_SUCCESS on success, non-zero on failure
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
156
157
158
159
160
      *
      * \note This callback can only be called while the audio output is in
      * stopped state. There can be only one stream per audio output at a time.
      *
      * \note This callbacks needs not be reentrant.
161
      */
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
162

163
    void (*stop)(audio_output_t *);
164
    /**< Stops the existing stream (mandatory, cannot be NULL).
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
165
166
167
168
169
      *
      * This callback terminates the current audio stream,
      * and returns the audio output to stopped state.
      *
      * \note This callback needs not be reentrant.
170
      */
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
171

Steve Lhomme's avatar
Steve Lhomme committed
172
    int (*time_get)(audio_output_t *, vlc_tick_t *delay);
173
174
175
176
177
178
179
180
    /**< Estimates playback buffer latency (mandatory, cannot be NULL).
      *
      * This callback computes an estimation of the delay until the current
      * tail of the audio output buffer would be rendered. This is essential
      * for (lip) synchronization and long term drift between the audio output
      * clock and the media upstream clock (if any).
      *
      * If the audio output clock is exactly synchronized with the system
181
      * monotonic clock (i.e. vlc_tick_now()), then aout_TimeGetDefault() can
182
183
184
185
186
187
188
189
      * implement this callback. In that case, drain must be implemented (since
      * the default implementation uses the delay to wait for the end of the
      * stream).
      *
      * This callback is called before the first play() in order to get the
      * initial delay (the hw latency). Most modules won't be able to know this
      * latency before the first play. In that case, they should return -1 and
      * handle the first play() date, cf. play() documentation.
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
190
      *
191
192
      * \param delay pointer to the delay until the next sample to be written
      *              to the playback buffer is rendered [OUT]
193
      * \return 0 on success, non-zero on failure or lack of data
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
194
195
      *
      * \note This callback cannot be called in stopped state.
196
      */
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
197

Steve Lhomme's avatar
Steve Lhomme committed
198
    void (*play)(audio_output_t *, block_t *block, vlc_tick_t date);
199
    /**< Queues a block of samples for playback (mandatory, cannot be NULL).
200
201
202
203
204
205
      *
      * The first play() date (after a flush()/start()) will be most likely in
      * the future. Modules that don't know the hw latency before a first play
      * (when they return -1 from the first time_get()) will need to handle
      * this. They can play a silence buffer with 'length = date - now()', or
      * configure their render callback to start at the given date.
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
206
      *
207
208
      * \param block block of audio samples
      * \param date intended system time to render the first sample
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
209
210
      *
      * \note This callback cannot be called in stopped state.
211
      */
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
212

Steve Lhomme's avatar
Steve Lhomme committed
213
    void (*pause)( audio_output_t *, bool pause, vlc_tick_t date);
214
215
216
217
218
219
220
221
222
    /**< Pauses or resumes playback (mandatory, cannot be NULL).
      *
      * This callback pauses or resumes audio playback as quickly as possible.
      * When pausing, it is desirable to stop producing sound immediately, but
      * retain already queued audio samples in the buffer to play when later
      * when resuming.
      *
      * If pausing is impossible, then aout_PauseDefault() can provide a
      * fallback implementation of this callback.
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
223
      *
224
225
      * \param pause pause if true, resume from pause if false
      * \param date timestamp when the pause or resume was requested
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
226
227
      *
      * \note This callback cannot be called in stopped state.
228
      */
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
229

230
231
    void (*flush)( audio_output_t *);
    /**< Flushes the playback buffers (mandatory, cannot be NULL).
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
232
      *
233
234
      * \param wait true to wait for playback of pending buffers (drain),
      *             false to discard pending buffers (flush)
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
235
236
      *
      * \note This callback cannot be called in stopped state.
237
      */
238
239
240
241
242
243
    void (*drain)(audio_output_t *);
    /**< Drain the playback buffers (can be NULL).
      *
      * If NULL, the caller will wait for the delay returned by time_get before
      * calling stop().
      */
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
244

245
246
    int (*volume_set)(audio_output_t *, float volume);
    /**< Changes playback volume (optional, may be NULL).
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
247
      *
248
      * \param volume requested volume (0. = mute, 1. = nominal)
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
249
      *
250
      * \note The volume is always a positive number.
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
251
      *
252
      * \warning A stream may or may not have been started when called.
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
253
254
255
256
      * \warning This callback may be called concurrently with
      * time_get(), play(), pause() or flush().
      * It will however be protected against concurrent calls to
      * start(), stop(), volume_set(), mute_set() or device_select().
257
      */
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
258

259
260
    int (*mute_set)(audio_output_t *, bool mute);
    /**< Changes muting (optinal, may be NULL).
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
261
      *
262
      * \param mute true to mute, false to unmute
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
263
      * \warning The same constraints apply as with volume_set().
264
      */
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
265

266
267
    int (*device_select)(audio_output_t *, const char *id);
    /**< Selects an audio output device (optional, may be NULL).
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
268
      *
269
270
      * \param id nul-terminated device unique identifier.
      * \return 0 on success, non-zero on failure.
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
271
272
      *
      * \warning The same constraints apply as with volume_set().
273
      */
274
275
276
277
278
279
280

    struct {
        bool headphones; /**< Default to false, set it to true if the current
                              sink is using headphones */
    } current_sink_info;
    /**< Current sink informations set by the module from the start() function */

281
    const struct vlc_audio_output_events *events;
zorglub's avatar
zorglub committed
282
283
};

284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
typedef enum
{
    AOUT_CHANIDX_DISABLE = -1,
    AOUT_CHANIDX_LEFT,
    AOUT_CHANIDX_RIGHT,
    AOUT_CHANIDX_MIDDLELEFT,
    AOUT_CHANIDX_MIDDLERIGHT,
    AOUT_CHANIDX_REARLEFT,
    AOUT_CHANIDX_REARRIGHT,
    AOUT_CHANIDX_REARCENTER,
    AOUT_CHANIDX_CENTER,
    AOUT_CHANIDX_LFE,
    AOUT_CHANIDX_MAX
} vlc_chan_order_idx_t;

static_assert(AOUT_CHANIDX_MAX == AOUT_CHAN_MAX, "channel count mismatch");

#define AOUT_CHAN_REMAP_INIT { \
    AOUT_CHANIDX_LEFT,  \
    AOUT_CHANIDX_RIGHT, \
    AOUT_CHANIDX_MIDDLELEFT, \
    AOUT_CHANIDX_MIDDLERIGHT, \
    AOUT_CHANIDX_REARLEFT, \
    AOUT_CHANIDX_REARRIGHT, \
    AOUT_CHANIDX_REARCENTER, \
    AOUT_CHANIDX_CENTER, \
    AOUT_CHANIDX_LFE, \
}

313
/**
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
314
 * It describes the audio channel order VLC expect.
315
 */
316
static const uint32_t pi_vlc_chan_order_wg4[] =
317
318
319
320
321
322
323
{
    AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT,
    AOUT_CHAN_MIDDLELEFT, AOUT_CHAN_MIDDLERIGHT,
    AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, AOUT_CHAN_REARCENTER,
    AOUT_CHAN_CENTER, AOUT_CHAN_LFE, 0
};

324
325
#define AOUT_RESTART_FILTERS        0x1
#define AOUT_RESTART_OUTPUT         (AOUT_RESTART_FILTERS|0x2)
326
#define AOUT_RESTART_STEREOMODE     (AOUT_RESTART_OUTPUT|0x4)
327

328
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
329
 * Prototypes
330
 *****************************************************************************/
zorglub's avatar
zorglub committed
331

332
333
334
335
336
337
/**
 * This function computes the reordering needed to go from pi_chan_order_in to
 * pi_chan_order_out.
 * If pi_chan_order_in or pi_chan_order_out is NULL, it will assume that vlc
 * internal (WG4) order is requested.
 */
338
VLC_API unsigned aout_CheckChannelReorder( const uint32_t *, const uint32_t *,
339
                                           uint32_t mask, uint8_t *table );
340
VLC_API void aout_ChannelReorder(void *, size_t, uint8_t, const uint8_t *, vlc_fourcc_t);
341

342
343
344
VLC_API void aout_Interleave(void *dst, const void *const *planes,
                             unsigned samples, unsigned channels,
                             vlc_fourcc_t fourcc);
345
VLC_API void aout_Deinterleave(void *dst, const void *src, unsigned samples,
346
347
                             unsigned channels, vlc_fourcc_t fourcc);

348
/**
David Fuhrmann's avatar
David Fuhrmann committed
349
 * This function will compute the extraction parameter into pi_selection to go
350
351
352
353
354
355
356
357
358
359
360
361
362
363
 * from i_channels with their type given by pi_order_src[] into the order
 * describe by pi_order_dst.
 * It will also set :
 * - *pi_channels as the number of channels that will be extracted which is
 * lower (in case of non understood channels type) or equal to i_channels.
 * - the layout of the channels (*pi_layout).
 *
 * It will return true if channel extraction is really needed, in which case
 * aout_ChannelExtract must be used
 *
 * XXX It must be used when the source may have channel type not understood
 * by VLC. In this case the channel type pi_order_src[] must be set to 0.
 * XXX It must also be used if multiple channels have the same type.
 */
364
VLC_API bool aout_CheckChannelExtraction( int *pi_selection, uint32_t *pi_layout, int *pi_channels, const uint32_t pi_order_dst[AOUT_CHAN_MAX], const uint32_t *pi_order_src, int i_channels );
365
366
367
368
369
370

/**
 * Do the actual channels extraction using the parameters created by
 * aout_CheckChannelExtraction.
 *
 * XXX this function does not work in place (p_dst and p_src must not overlap).
371
 * XXX Only 8, 16, 32, 64 bits per sample are supported.
372
 */
373
VLC_API void aout_ChannelExtract( void *p_dst, int i_dst_channels, const void *p_src, int i_src_channels, int i_sample_count, const int *pi_selection, int i_bits_per_sample );
374
375

/* */
376
377
static inline unsigned aout_FormatNbChannels(const audio_sample_format_t *fmt)
{
378
    return vlc_popcount(fmt->i_physical_channels);
379
380
}

381
VLC_API unsigned int aout_BitsPerSample( vlc_fourcc_t i_format ) VLC_USED;
382
VLC_API void aout_FormatPrepare( audio_sample_format_t * p_format );
383
384
385
VLC_API void aout_FormatPrint(vlc_object_t *, const char *,
                              const audio_sample_format_t *);
#define aout_FormatPrint(o, t, f) aout_FormatPrint(VLC_OBJECT(o), t, f)
386
VLC_API const char * aout_FormatPrintChannels( const audio_sample_format_t * ) VLC_USED;
zorglub's avatar
zorglub committed
387

388
389
390
#define AOUT_VOLUME_DEFAULT             256
#define AOUT_VOLUME_MAX                 512

391
392
VLC_API float aout_VolumeGet (audio_output_t *);
VLC_API int aout_VolumeSet (audio_output_t *, float);
393
VLC_API int aout_VolumeUpdate (audio_output_t *, int, float *);
394
395
VLC_API int aout_MuteGet (audio_output_t *);
VLC_API int aout_MuteSet (audio_output_t *, bool);
396
397
398
VLC_API char *aout_DeviceGet (audio_output_t *);
VLC_API int aout_DeviceSet (audio_output_t *, const char *);
VLC_API int aout_DevicesList (audio_output_t *, char ***, char ***);
399

400
401
402
/**
 * Report change of configured audio volume to the core and UI.
 */
403
404
static inline void aout_VolumeReport(audio_output_t *aout, float volume)
{
405
    aout->events->volume_report(aout, volume);
406
407
}

408
409
410
/**
 * Report change of muted flag to the core and UI.
 */
411
static inline void aout_MuteReport(audio_output_t *aout, bool mute)
412
{
413
    aout->events->mute_report(aout, mute);
414
415
}

416
417
/**
 * Report audio policy status.
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
418
 * \param cork true to request a cork, false to undo any pending cork.
419
 */
420
421
static inline void aout_PolicyReport(audio_output_t *aout, bool cork)
{
422
    aout->events->policy_report(aout, cork);
423
424
}

425
426
427
428
429
/**
 * Report change of output device.
 */
static inline void aout_DeviceReport(audio_output_t *aout, const char *id)
{
430
    aout->events->device_report(aout, id);
431
432
}

433
434
435
436
437
438
439
440
/**
 * Report a device hot-plug event.
 * @param id device ID
 * @param name human-readable device name (NULL for hot unplug)
 */
static inline void aout_HotplugReport(audio_output_t *aout,
                                      const char *id, const char *name)
{
441
    aout->events->hotplug_report(aout, id, name);
442
443
}

444
445
446
447
448
/**
 * Request a change of software audio amplification.
 * \param gain linear amplitude gain (must be positive)
 * \warning Values in excess 1.0 may cause overflow and distorsion.
 */
449
static inline int aout_GainRequest(audio_output_t *aout, float gain)
450
{
451
    return aout->events->gain_request(aout, gain);
452
}
453

454
455
static inline void aout_RestartRequest(audio_output_t *aout, unsigned mode)
{
456
    aout->events->restart_request(aout, mode);
457
458
}

459
460
461
462
/**
 * Default implementation for audio_output_t.time_get
 */
static inline int aout_TimeGetDefault(audio_output_t *aout,
Steve Lhomme's avatar
Steve Lhomme committed
463
                                      vlc_tick_t *restrict delay)
464
465
466
467
468
{
    (void) aout; (void) delay;
    return -1;
}

469
470
471
472
473
474
475
476
/**
 * Default implementation for audio_output_t.pause
 *
 * \warning This default callback implementation is suboptimal as it will
 * discard some audio samples.
 * Do not use this unless there are really no possible better alternatives.
 */
static inline void aout_PauseDefault(audio_output_t *aout, bool paused,
Steve Lhomme's avatar
Steve Lhomme committed
477
                                     vlc_tick_t date)
478
{
479
    if (paused)
480
        aout->flush(aout);
481
482
483
    (void) date;
}

484
/* Audio output filters */
485

Thomas Guillem's avatar
Thomas Guillem committed
486
487
488
489
490
491
492
493
494
495
/**
 * Enable or disable an audio filter ("audio-filter")
 *
 * \param aout a valid audio output
 * \param name a valid filter name
 * \param add true to add the filter, false to remove it
 * \return 0 on success, non-zero on failure.
 */
VLC_API int aout_EnableFilter(audio_output_t *aout, const char *name, bool add);

496
497
498
499
500
501
502
typedef struct
{
    /**
     * If the remap order differs from the WG4 order, a remap audio filter will
     * be inserted to remap channels according to this array.
     */
    int remap[AOUT_CHANIDX_MAX];
503
504
505
506
507
    /**
     * If true, a filter will be inserted to add a headphones effect (like a
     * binauralizer audio filter).
     */
    bool headphones;
508
509
510
511
} aout_filters_cfg_t;

#define AOUT_FILTERS_CFG_INIT (aout_filters_cfg_t) \
    { .remap = AOUT_CHAN_REMAP_INIT, \
512
      .headphones = false, \
513
514
    };

515
516
517
518
519
typedef struct aout_filters aout_filters_t;

VLC_API aout_filters_t *aout_FiltersNew(vlc_object_t *,
                                        const audio_sample_format_t *,
                                        const audio_sample_format_t *,
520
                                        const aout_filters_cfg_t *cfg) VLC_USED;
521
522
#define aout_FiltersNew(o,inf,outf,remap) \
        aout_FiltersNew(VLC_OBJECT(o),inf,outf,remap)
523
524
525
526
VLC_API void aout_FiltersDelete(vlc_object_t *, aout_filters_t *);
#define aout_FiltersDelete(o,f) \
        aout_FiltersDelete(VLC_OBJECT(o),f)
VLC_API bool aout_FiltersAdjustResampling(aout_filters_t *, int);
527
VLC_API block_t *aout_FiltersPlay(aout_filters_t *, block_t *, float rate);
528
529
VLC_API block_t *aout_FiltersDrain(aout_filters_t *);
VLC_API void     aout_FiltersFlush(aout_filters_t *);
530
VLC_API void     aout_FiltersChangeViewpoint(aout_filters_t *, const vlc_viewpoint_t *vp);
zorglub's avatar
zorglub committed
531

532
VLC_API vout_thread_t *aout_filter_GetVout(filter_t *, const video_format_t *);
533

534
535
536
537
538
static inline int aout_TimeGet(audio_output_t *aout, vlc_tick_t *delay)
{
    return aout->time_get(aout, delay);
}

539
540
/** @} */

541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
/**
 * @defgroup audio_output__meter Audio meter API
 */

/**
 * Audio loudness measurement
 */
struct vlc_audio_loudness
{
    /** Momentary loudness (last 400 ms), in LUFS */
    double loudness_momentary;
    /** Short term loudness (last 3seconds), in LUFS */
    double loudness_shortterm;
    /** Integrated loudness (global), in LUFS */
    double loudness_integrated;
    /** Loudness range, in LU */
    double loudness_range;
    /** True Peak, in dBTP */
    double truepeak;
};

/**
 * Audio meter callback
 *
 * Triggered from vlc_audio_meter_Process() and vlc_audio_meter_Flush().
 */
struct vlc_audio_meter_cbs
{
    /**
     * Called when new loudness measurements are available
     *
     * @param date absolute date (likely in the future) of this measurement
     * @param loudness pointer to the loudness measurement
     * @param opaque pointer set by vlc_audio_meter_AddPlugin().
     */
    void (*on_loudness)(vlc_tick_t date, const struct vlc_audio_loudness *loudness, void *data);
};

/**
 * Audio meter plugin opaque structure
 *
 * This opaque structure is returned by vlc_audio_meter_AddPlugin().
 */
typedef struct vlc_audio_meter_plugin vlc_audio_meter_plugin;

/**
 * Audio meter plugin owner structure
 *
 * Used to setup callbacks and private data
 *
 * Can be registered with vlc_audio_meter_AddPlugin().
 */
struct vlc_audio_meter_plugin_owner
{
    const struct vlc_audio_meter_cbs *cbs;
    void *sys;
};

/**
 * Audio meter structure
 *
 * Initialise with vlc_audio_meter_Init()
 *
 * @warning variables of this struct should not be used directly
 */
struct vlc_audio_meter
{
    vlc_mutex_t lock;
    vlc_object_t *parent;
    const audio_sample_format_t *fmt;

    struct vlc_list plugins;
};

/**
 * Initialize the audio meter structure
 *
 * @param meter allocated audio meter structure
 * @param parent object that will be used to create audio filters
 */
VLC_API void
vlc_audio_meter_Init(struct vlc_audio_meter *meter, vlc_object_t *parent);
#define vlc_audio_meter_Init(a,b) vlc_audio_meter_Init(a, VLC_OBJECT(b))

/**
 * Free allocated resource from the audio meter structure
 *
 * @param meter allocated audio meter structure
 */
VLC_API void
vlc_audio_meter_Destroy(struct vlc_audio_meter *meter);

/**
 * Set or reset the audio format
 *
 * This will reload all plugins added with vlc_audio_meter_AddPlugin()
 *
 * @param meter audio meter structure
 * @param fmt NULL to unload all plugins or a valid pointer to an audio format,
 * must stay valid during the lifetime of the audio meter (until
 * vlc_audio_meter_Reset() or vlc_audio_meter_Destroy() are called)
 *
 * @return VLC_SUCCESS on success, VLC_EGENERIC if a plugin failed to load
 */
VLC_API int
vlc_audio_meter_Reset(struct vlc_audio_meter *meter, const audio_sample_format_t *fmt);

/**
 * Add an "audio meter" plugin
 *
 * The module to be loaded if meter->fmt is valid, otherwise, the module
 * will be loaded from a next call to vlc_audio_meter_Reset()
 *
 * @param meter audio meter structure
 * @param chain name of the module, can contain specific module options using
 * the following chain convention:"name{option1=a,option2=b}"
 * @param cbs pointer to a vlc_audio_meter_events structure, the
 * structure must stay valid during the lifetime of the plugin
 * @param cbs_data opaque pointer used by the callbacks
 * @return a valid audio meter plugin, or NULL in case of error
 */
VLC_API vlc_audio_meter_plugin *
vlc_audio_meter_AddPlugin(struct vlc_audio_meter *meter, const char *chain,
                          const struct vlc_audio_meter_plugin_owner *owner);

/**
 * Remove an "audio meter" plugin
 *
 * @param meter audio meter structure
 * @param plugin plugin returned by vlc_audio_meter_AddPlugin()
 */
VLC_API void
vlc_audio_meter_RemovePlugin(struct vlc_audio_meter *meter, vlc_audio_meter_plugin *plugin);

/**
 * Process an audio block
 *
 * vlc_audio_meter_events callbacks can be triggered from this function.
 *
 * @param meter audio meter structure
 * @param block pointer to a block, this block won't be released of modified
 * from this function
 * @param date absolute date (likely in the future) when this block should be rendered
 */
VLC_API void
vlc_audio_meter_Process(struct vlc_audio_meter *meter, block_t *block, vlc_tick_t date);

/**
 * Flush all "audio meter" plugins
 *
 * vlc_audio_meter_events callbacks can be triggered from this function.
 *
 * @param meter audio meter structure
 */
VLC_API void
vlc_audio_meter_Flush(struct vlc_audio_meter *meter);

/** @} */

700
#endif /* VLC_AOUT_H */