vlc_aout.h 15.4 KB
Newer Older
1
/*****************************************************************************
2
 * vlc_aout.h : audio output interface
3
 *****************************************************************************
Jean-Baptiste Kempf's avatar
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
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
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
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
 *****************************************************************************/
22

23 24
#ifndef VLC_AOUT_H
#define VLC_AOUT_H 1
25

26 27
#include <assert.h>

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

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

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

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

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

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

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

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

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

66 67 68
/* 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)                               \
69
      && ((p_first)->channel_type == (p_second)->channel_type)            \
70
      && ((p_first)->i_physical_channels == (p_second)->i_physical_channels)\
71
      && ((p_first)->i_chan_mode == (p_second)->i_chan_mode) )
72

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

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

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

85 86
#define AOUT_FMT_HDMI( p_format )                   \
    ( (p_format)->i_format == VLC_CODEC_EAC3        \
87 88
    ||(p_format)->i_format == VLC_CODEC_TRUEHD      \
    ||(p_format)->i_format == VLC_CODEC_MLP         \
89 90
    )

91
/* Values used for the audio-channels object variable */
92
#define AOUT_VAR_CHAN_UNSET         0 /* must be zero */
93 94 95 96 97
#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
98
#define AOUT_VAR_CHAN_HEADPHONES    6
99

100
/*****************************************************************************
101
 * Main audio output structures
102
 *****************************************************************************/
103

Christophe Massiot's avatar
Christophe Massiot committed
104 105
/* Size of a frame for S/PDIF output. */
#define AOUT_SPDIF_SIZE 6144
106

107
/* Number of samples in an A/52 frame. */
108
#define A52_FRAME_NB 1536
109

110
/* FIXME to remove once aout.h is cleaned a bit more */
111
#include <vlc_block.h>
112

113
/** Audio output object */
114
struct audio_output
115 116 117
{
    VLC_COMMON_MEMBERS

118 119 120 121 122 123 124 125 126 127 128 129 130
    struct aout_sys_t *sys; /**< Private data for callbacks */

    int (*start)(audio_output_t *, audio_sample_format_t *fmt);
    /**< Starts a new stream (mandatory, cannot be NULL).
      * \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
      * \note No other stream may be already started when called.
      */
    void (*stop)(audio_output_t *);
    /**< Stops the existing stream (optional, may be NULL).
      * \note A stream must have been started when called.
      */
131 132 133 134
    int (*time_get)(audio_output_t *, mtime_t *delay);
    /**< Estimates playback buffer latency (optional, may be NULL).
      * \param delay pointer to the delay until the next sample to be written
      *              to the playback buffer is rendered [OUT]
135
      * \return 0 on success, non-zero on failure or lack of data
136 137 138
      * \note A stream must have been started when called.
      */
    void (*play)(audio_output_t *, block_t *);
139 140 141 142 143 144 145 146 147 148
    /**< Queues a block of samples for playback (mandatory, cannot be NULL).
      * \note A stream must have been started when called.
      */
    void (*pause)( audio_output_t *, bool pause, mtime_t date);
    /**< Pauses or resumes playback (optional, may be NULL).
      * \param pause pause if true, resume from pause if false
      * \param date timestamp when the pause or resume was requested
      * \note A stream must have been started when called.
      */
    void (*flush)( audio_output_t *, bool wait);
149
    /**< Flushes or drains the playback buffers (mandatory, cannot be NULL).
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
      * \param wait true to wait for playback of pending buffers (drain),
      *             false to discard pending buffers (flush)
      * \note A stream must have been started when called.
      */
    int (*volume_set)(audio_output_t *, float volume);
    /**< Changes playback volume (optional, may be NULL).
      * \param volume requested volume (0. = mute, 1. = nominal)
      * \note The volume is always a positive number.
      * \warning A stream may or may not have been started when called.
      */
    int (*mute_set)(audio_output_t *, bool mute);
    /**< Changes muting (optinal, may be NULL).
      * \param mute true to mute, false to unmute
      * \warning A stream may or may not have been started when called.
      */
165 166 167 168 169 170
    int (*device_select)(audio_output_t *, const char *id);
    /**< Selects an audio output device (optional, may be NULL).
      * \param id nul-terminated device unique identifier.
      * \return 0 on success, non-zero on failure.
      * \warning A stream may or may not have been started when called.
      */
171 172 173 174 175 176 177

    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 */

178 179 180
    struct {
        void (*volume_report)(audio_output_t *, float);
        void (*mute_report)(audio_output_t *, bool);
181
        void (*policy_report)(audio_output_t *, bool);
182
        void (*device_report)(audio_output_t *, const char *);
183
        void (*hotplug_report)(audio_output_t *, const char *, const char *);
184
        int (*gain_request)(audio_output_t *, float);
185
        void (*restart_request)(audio_output_t *, unsigned);
186
    } event;
187 188
};

189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
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, \
}

218
/**
219
 * It describes the audio channel order VLC expect.
220 221 222 223 224 225 226 227 228
 */
static const uint32_t pi_vlc_chan_order_wg4[] =
{
    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
};

229 230
#define AOUT_RESTART_FILTERS        0x1
#define AOUT_RESTART_OUTPUT         (AOUT_RESTART_FILTERS|0x2)
231
#define AOUT_RESTART_STEREOMODE     (AOUT_RESTART_OUTPUT|0x4)
232

233
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
234
 * Prototypes
235
 *****************************************************************************/
236

237 238 239 240 241 242
/**
 * 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.
 */
243
VLC_API unsigned aout_CheckChannelReorder( const uint32_t *, const uint32_t *,
244
                                           uint32_t mask, uint8_t *table );
245
VLC_API void aout_ChannelReorder(void *, size_t, uint8_t, const uint8_t *, vlc_fourcc_t);
246

247 248 249
VLC_API void aout_Interleave(void *dst, const void *const *planes,
                             unsigned samples, unsigned channels,
                             vlc_fourcc_t fourcc);
250
VLC_API void aout_Deinterleave(void *dst, const void *src, unsigned samples,
251 252
                             unsigned channels, vlc_fourcc_t fourcc);

253
/**
David Fuhrmann's avatar
David Fuhrmann committed
254
 * This function will compute the extraction parameter into pi_selection to go
255 256 257 258 259 260 261 262 263 264 265 266 267 268
 * 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.
 */
269
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 );
270 271 272 273 274 275 276 277

/**
 * 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).
 * XXX Only 8, 16, 24, 32, 64 bits per sample are supported.
 */
278
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 );
279 280

/* */
281 282
static inline unsigned aout_FormatNbChannels(const audio_sample_format_t *fmt)
{
283
    return popcount(fmt->i_physical_channels);
284 285
}

286
VLC_API unsigned int aout_BitsPerSample( vlc_fourcc_t i_format ) VLC_USED;
287
VLC_API void aout_FormatPrepare( audio_sample_format_t * p_format );
288 289 290
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)
291
VLC_API const char * aout_FormatPrintChannels( const audio_sample_format_t * ) VLC_USED;
292

293 294 295
#define AOUT_VOLUME_DEFAULT             256
#define AOUT_VOLUME_MAX                 512

296 297
VLC_API float aout_VolumeGet (audio_output_t *);
VLC_API int aout_VolumeSet (audio_output_t *, float);
298
VLC_API int aout_VolumeUpdate (audio_output_t *, int, float *);
299 300
VLC_API int aout_MuteGet (audio_output_t *);
VLC_API int aout_MuteSet (audio_output_t *, bool);
301 302 303
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 ***);
304

305 306 307
/**
 * Report change of configured audio volume to the core and UI.
 */
308 309 310 311 312
static inline void aout_VolumeReport(audio_output_t *aout, float volume)
{
    aout->event.volume_report(aout, volume);
}

313 314 315
/**
 * Report change of muted flag to the core and UI.
 */
316
static inline void aout_MuteReport(audio_output_t *aout, bool mute)
317
{
318
    aout->event.mute_report(aout, mute);
319 320
}

321 322
/**
 * Report audio policy status.
323
 * \param cork true to request a cork, false to undo any pending cork.
324
 */
325 326 327 328 329
static inline void aout_PolicyReport(audio_output_t *aout, bool cork)
{
    aout->event.policy_report(aout, cork);
}

330 331 332 333 334 335 336 337
/**
 * Report change of output device.
 */
static inline void aout_DeviceReport(audio_output_t *aout, const char *id)
{
    aout->event.device_report(aout, id);
}

338 339 340 341 342 343 344 345 346 347 348
/**
 * 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)
{
    aout->event.hotplug_report(aout, id, name);
}

349 350 351 352 353
/**
 * 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.
 */
354
static inline int aout_GainRequest(audio_output_t *aout, float gain)
355
{
356
    return aout->event.gain_request(aout, gain);
357
}
358

359 360 361 362 363
static inline void aout_RestartRequest(audio_output_t *aout, unsigned mode)
{
    aout->event.restart_request(aout, mode);
}

364
/* Audio output filters */
365 366 367 368 369 370 371 372

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];
373 374 375 376 377
    /**
     * If true, a filter will be inserted to add a headphones effect (like a
     * binauralizer audio filter).
     */
    bool headphones;
378 379 380 381
} aout_filters_cfg_t;

#define AOUT_FILTERS_CFG_INIT (aout_filters_cfg_t) \
    { .remap = AOUT_CHAN_REMAP_INIT, \
382
      .headphones = false, \
383 384
    };

385 386 387 388 389 390
typedef struct aout_filters aout_filters_t;
typedef struct aout_request_vout aout_request_vout_t;

VLC_API aout_filters_t *aout_FiltersNew(vlc_object_t *,
                                        const audio_sample_format_t *,
                                        const audio_sample_format_t *,
391
                                        const aout_request_vout_t *,
392
                                        const aout_filters_cfg_t *cfg) VLC_USED;
393 394
#define aout_FiltersNew(o,inf,outf,rv,remap) \
        aout_FiltersNew(VLC_OBJECT(o),inf,outf,rv,remap)
395 396 397 398 399
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);
VLC_API block_t *aout_FiltersPlay(aout_filters_t *, block_t *, int rate);
400 401
VLC_API block_t *aout_FiltersDrain(aout_filters_t *);
VLC_API void     aout_FiltersFlush(aout_filters_t *);
402
VLC_API void     aout_FiltersChangeViewpoint(aout_filters_t *, const vlc_viewpoint_t *vp);
Clément Stenac's avatar
Clément Stenac committed
403

404
VLC_API vout_thread_t * aout_filter_RequestVout( filter_t *, vout_thread_t *p_vout, const video_format_t *p_fmt );
405

406 407
/** @} */

408
#endif /* VLC_AOUT_H */