qt: add device preferences for mmdevice
[vlc.git] / modules / stream_out / transcode / audio.c
blobd3f5bf7cf3483a87b2034334221c5534340922d3
1 /*****************************************************************************
2 * audio.c: transcoding stream output module (audio)
3 *****************************************************************************
4 * Copyright (C) 2003-2009 VLC authors and VideoLAN
5 * $Id$
7 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8 * Gildas Bazin <gbazin@videolan.org>
9 * Jean-Paul Saman <jpsaman #_at_# m2x dot nl>
10 * Antoine Cellerier <dionoea at videolan dot org>
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU Lesser General Public License as published by
14 * the Free Software Foundation; either version 2.1 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public License
23 * along with this program; if not, write to the Free Software Foundation,
24 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25 *****************************************************************************/
27 /*****************************************************************************
28 * Preamble
29 *****************************************************************************/
31 #include "transcode.h"
33 #include <vlc_aout.h>
34 #include <vlc_input.h>
35 #include <vlc_meta.h>
36 #include <vlc_modules.h>
38 static const int pi_channels_maps[9] =
41 AOUT_CHAN_CENTER,
42 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
43 AOUT_CHAN_LFE | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
44 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
45 | AOUT_CHAN_REARRIGHT,
46 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
47 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT,
48 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
49 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE,
50 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
51 | AOUT_CHAN_REARCENTER | AOUT_CHAN_MIDDLELEFT
52 | AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_LFE,
53 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT
54 | AOUT_CHAN_REARRIGHT | AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT
55 | AOUT_CHAN_LFE,
58 static int audio_update_format( decoder_t *p_dec )
60 sout_stream_id_sys_t *id = p_dec->p_queue_ctx;
62 p_dec->fmt_out.audio.i_format = p_dec->fmt_out.i_codec;
63 aout_FormatPrepare( &p_dec->fmt_out.audio );
65 vlc_mutex_lock(&id->fifo.lock);
66 id->audio_dec_out = p_dec->fmt_out.audio;
67 vlc_mutex_unlock(&id->fifo.lock);
69 return ( p_dec->fmt_out.audio.i_bitspersample > 0 ) ? 0 : -1;
72 static int transcode_audio_initialize_filters( sout_stream_t *p_stream, sout_stream_id_sys_t *id,
73 sout_stream_sys_t *p_sys )
75 /* Load user specified audio filters */
76 /* XXX: These variable names come kinda out of nowhere... */
77 var_Create( p_stream, "audio-time-stretch", VLC_VAR_BOOL );
78 var_Create( p_stream, "audio-filter", VLC_VAR_STRING );
79 if( p_sys->psz_af )
80 var_SetString( p_stream, "audio-filter", p_sys->psz_af );
81 id->p_af_chain = aout_FiltersNew( p_stream, &id->audio_dec_out,
82 &id->p_encoder->fmt_in.audio, NULL, NULL );
83 var_Destroy( p_stream, "audio-filter" );
84 var_Destroy( p_stream, "audio-time-stretch" );
85 if( id->p_af_chain == NULL )
87 msg_Err( p_stream, "Unable to initialize audio filters" );
88 module_unneed( id->p_encoder, id->p_encoder->p_module );
89 id->p_encoder->p_module = NULL;
90 module_unneed( id->p_decoder, id->p_decoder->p_module );
91 id->p_decoder->p_module = NULL;
92 return VLC_EGENERIC;
94 id->fmt_audio.i_rate = id->audio_dec_out.i_rate;
95 id->fmt_audio.i_physical_channels = id->audio_dec_out.i_physical_channels;
96 return VLC_SUCCESS;
99 static int transcode_audio_initialize_encoder( sout_stream_id_sys_t *id, sout_stream_t *p_stream )
101 sout_stream_sys_t *p_sys = p_stream->p_sys;
103 /* Complete destination format */
104 id->p_encoder->fmt_out.i_codec = p_sys->i_acodec;
105 id->p_encoder->fmt_out.audio.i_rate = p_sys->i_sample_rate > 0 ?
106 p_sys->i_sample_rate : id->audio_dec_out.i_rate;
107 id->p_encoder->fmt_out.i_bitrate = p_sys->i_abitrate;
108 id->p_encoder->fmt_out.audio.i_bitspersample = id->audio_dec_out.i_bitspersample;
109 id->p_encoder->fmt_out.audio.i_channels = p_sys->i_channels > 0 ?
110 p_sys->i_channels : id->audio_dec_out.i_channels;
111 assert(id->p_encoder->fmt_out.audio.i_channels > 0);
112 if( id->p_encoder->fmt_out.audio.i_channels >= ARRAY_SIZE(pi_channels_maps) )
113 id->p_encoder->fmt_out.audio.i_channels = ARRAY_SIZE(pi_channels_maps) - 1;
115 id->p_encoder->fmt_in.audio.i_physical_channels =
116 id->p_encoder->fmt_out.audio.i_physical_channels =
117 pi_channels_maps[id->p_encoder->fmt_out.audio.i_channels];
119 /* Initialization of encoder format structures */
120 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
121 id->audio_dec_out.i_format );
122 id->p_encoder->fmt_in.audio.i_format = id->audio_dec_out.i_format;
123 id->p_encoder->fmt_in.audio.i_rate = id->p_encoder->fmt_out.audio.i_rate;
124 id->p_encoder->fmt_in.audio.i_physical_channels =
125 id->p_encoder->fmt_out.audio.i_physical_channels;
126 aout_FormatPrepare( &id->p_encoder->fmt_in.audio );
128 id->p_encoder->p_cfg = p_stream->p_sys->p_audio_cfg;
129 id->p_encoder->p_module =
130 module_need( id->p_encoder, "encoder", p_sys->psz_aenc, true );
131 /* p_sys->i_acodec = 0 if there isn't acodec defined */
132 if( !id->p_encoder->p_module && p_sys->i_acodec )
134 msg_Err( p_stream, "cannot find audio encoder (module:%s fourcc:%4.4s). "
135 "Take a look few lines earlier to see possible reason.",
136 p_sys->psz_aenc ? p_sys->psz_aenc : "any",
137 (char *)&p_sys->i_acodec );
138 module_unneed( id->p_decoder, id->p_decoder->p_module );
139 id->p_decoder->p_module = NULL;
140 return VLC_EGENERIC;
143 id->p_encoder->fmt_out.i_codec =
144 vlc_fourcc_GetCodec( AUDIO_ES, id->p_encoder->fmt_out.i_codec );
146 /* Fix input format */
147 id->p_encoder->fmt_in.audio.i_format = id->p_encoder->fmt_in.i_codec;
148 if( !id->p_encoder->fmt_in.audio.i_physical_channels )
150 if( id->p_encoder->fmt_in.audio.i_channels < (sizeof(pi_channels_maps) / sizeof(*pi_channels_maps)) )
151 id->p_encoder->fmt_in.audio.i_physical_channels =
152 pi_channels_maps[id->p_encoder->fmt_in.audio.i_channels];
154 aout_FormatPrepare( &id->p_encoder->fmt_in.audio );
156 return VLC_SUCCESS;
159 static int decoder_queue_audio( decoder_t *p_dec, block_t *p_audio )
161 sout_stream_id_sys_t *id = p_dec->p_queue_ctx;
163 vlc_mutex_lock(&id->fifo.lock);
164 *id->fifo.audio.last = p_audio;
165 id->fifo.audio.last = &p_audio->p_next;
166 vlc_mutex_unlock(&id->fifo.lock);
167 return 0;
170 static block_t *transcode_dequeue_all_audios( sout_stream_id_sys_t *id )
172 vlc_mutex_lock(&id->fifo.lock);
173 block_t *p_audio_bufs = id->fifo.audio.first;
174 id->fifo.audio.first = NULL;
175 id->fifo.audio.last = &id->fifo.audio.first;
176 vlc_mutex_unlock(&id->fifo.lock);
178 return p_audio_bufs;
181 static int transcode_audio_new( sout_stream_t *p_stream,
182 sout_stream_id_sys_t *id )
184 sout_stream_sys_t *p_sys = p_stream->p_sys;
187 * Open decoder
190 /* Initialization of decoder structures */
191 id->p_decoder->pf_decode = NULL;
192 id->p_decoder->pf_queue_audio = decoder_queue_audio;
193 id->p_decoder->p_queue_ctx = id;
194 id->p_decoder->pf_aout_format_update = audio_update_format;
195 /* id->p_decoder->p_cfg = p_sys->p_audio_cfg; */
196 id->p_decoder->p_module =
197 module_need_var( id->p_decoder, "audio decoder", "codec" );
198 if( !id->p_decoder->p_module )
200 msg_Err( p_stream, "cannot find audio decoder" );
201 return VLC_EGENERIC;
204 vlc_mutex_lock(&id->fifo.lock);
205 /* The decoder fmt_out can be uninitialized here (since it can initialized
206 * asynchronously). Fix audio_dec_out with default values in that case.
207 * This should be enough to initialize the encoder for the first time (it
208 * will be reloaded when all informations from the decoder are available).
209 * */
210 id->audio_dec_out = id->p_decoder->fmt_out.audio;
211 id->audio_dec_out.i_format = id->p_decoder->fmt_out.i_codec;
212 if (id->audio_dec_out.i_format == 0)
213 id->audio_dec_out.i_format = VLC_CODEC_FL32;
214 if (id->audio_dec_out.i_rate == 0)
216 id->audio_dec_out.i_rate = id->p_decoder->fmt_in.audio.i_rate;
217 if (id->audio_dec_out.i_rate == 0)
218 id->audio_dec_out.i_rate = 48000;
220 if (id->audio_dec_out.i_physical_channels == 0)
222 id->audio_dec_out.i_physical_channels = id->p_decoder->fmt_in.audio.i_physical_channels;
223 if (id->audio_dec_out.i_physical_channels == 0)
224 id->audio_dec_out.i_physical_channels = AOUT_CHANS_STEREO;
226 aout_FormatPrepare( &id->audio_dec_out );
229 * Open encoder
231 if( transcode_audio_initialize_encoder( id, p_stream ) == VLC_EGENERIC )
233 vlc_mutex_unlock(&id->fifo.lock);
234 return VLC_EGENERIC;
237 if( unlikely( transcode_audio_initialize_filters( p_stream, id, p_sys ) != VLC_SUCCESS ) )
239 vlc_mutex_unlock(&id->fifo.lock);
240 return VLC_EGENERIC;
242 vlc_mutex_unlock(&id->fifo.lock);
244 return VLC_SUCCESS;
247 void transcode_audio_close( sout_stream_id_sys_t *id )
249 /* Close decoder */
250 if( id->p_decoder->p_module )
251 module_unneed( id->p_decoder, id->p_decoder->p_module );
252 id->p_decoder->p_module = NULL;
254 if( id->p_decoder->p_description )
255 vlc_meta_Delete( id->p_decoder->p_description );
256 id->p_decoder->p_description = NULL;
258 /* Close encoder */
259 if( id->p_encoder->p_module )
260 module_unneed( id->p_encoder, id->p_encoder->p_module );
261 id->p_encoder->p_module = NULL;
263 /* Close filters */
264 if( id->p_af_chain != NULL )
265 aout_FiltersDelete( (vlc_object_t *)NULL, id->p_af_chain );
268 int transcode_audio_process( sout_stream_t *p_stream,
269 sout_stream_id_sys_t *id,
270 block_t *in, block_t **out )
272 sout_stream_sys_t *p_sys = p_stream->p_sys;
273 *out = NULL;
275 int ret = id->p_decoder->pf_decode( id->p_decoder, in );
276 if( ret != VLCDEC_SUCCESS )
277 return VLC_EGENERIC;
279 block_t *p_audio_bufs = transcode_dequeue_all_audios( id );
280 if( p_audio_bufs == NULL )
281 goto end;
285 block_t *p_audio_buf = p_audio_bufs;
286 p_audio_bufs = p_audio_bufs->p_next;
287 p_audio_buf->p_next = NULL;
289 if( id->b_error )
291 block_Release( p_audio_buf );
292 continue;
295 vlc_mutex_lock(&id->fifo.lock);
296 if( unlikely( !id->p_encoder->p_module ) )
298 if( transcode_audio_initialize_encoder( id, p_stream ) )
300 msg_Err( p_stream, "cannot create audio chain" );
301 vlc_mutex_unlock(&id->fifo.lock);
302 goto error;
304 if( unlikely( transcode_audio_initialize_filters( p_stream, id, p_sys ) != VLC_SUCCESS ) )
306 vlc_mutex_unlock(&id->fifo.lock);
307 goto error;
309 date_Init( &id->next_input_pts, id->audio_dec_out.i_rate, 1 );
310 date_Set( &id->next_input_pts, p_audio_buf->i_pts );
312 if (!id->id)
314 id->id = sout_StreamIdAdd( p_stream->p_next, &id->p_encoder->fmt_out );
315 if (!id->id)
317 vlc_mutex_unlock(&id->fifo.lock);
318 goto error;
323 /* Check if audio format has changed, and filters need reinit */
324 if( unlikely( ( id->audio_dec_out.i_rate != id->fmt_audio.i_rate ) ||
325 ( id->audio_dec_out.i_physical_channels != id->fmt_audio.i_physical_channels ) ) )
327 msg_Info( p_stream, "Audio changed, trying to reinitialize filters" );
328 if( id->p_af_chain != NULL )
329 aout_FiltersDelete( (vlc_object_t *)NULL, id->p_af_chain );
331 if( transcode_audio_initialize_filters( p_stream, id, p_sys ) != VLC_SUCCESS )
333 vlc_mutex_unlock(&id->fifo.lock);
334 goto error;
337 /* Set next_input_pts to run with new samplerate */
338 date_Init( &id->next_input_pts, id->fmt_audio.i_rate, 1 );
339 date_Set( &id->next_input_pts, p_audio_buf->i_pts );
341 vlc_mutex_unlock(&id->fifo.lock);
343 if( p_sys->b_master_sync )
345 mtime_t i_pts = date_Get( &id->next_input_pts );
346 mtime_t i_drift = 0;
348 if( likely( p_audio_buf->i_pts != VLC_TS_INVALID ) )
349 i_drift = p_audio_buf->i_pts - i_pts;
351 if ( unlikely(i_drift > MASTER_SYNC_MAX_DRIFT
352 || i_drift < -MASTER_SYNC_MAX_DRIFT) )
354 msg_Dbg( p_stream,
355 "audio drift is too high (%"PRId64"), resetting master sync",
356 i_drift );
357 date_Set( &id->next_input_pts, p_audio_buf->i_pts );
358 i_pts = date_Get( &id->next_input_pts );
359 if( likely(p_audio_buf->i_pts != VLC_TS_INVALID ) )
360 i_drift = p_audio_buf->i_pts - i_pts;
362 p_sys->i_master_drift = i_drift;
363 date_Increment( &id->next_input_pts, p_audio_buf->i_nb_samples );
366 p_audio_buf->i_dts = p_audio_buf->i_pts;
368 /* Run filter chain */
369 p_audio_buf = aout_FiltersPlay( id->p_af_chain, p_audio_buf,
370 INPUT_RATE_DEFAULT );
371 if( !p_audio_buf )
372 goto error;
374 p_audio_buf->i_dts = p_audio_buf->i_pts;
376 block_t *p_block = id->p_encoder->pf_encode_audio( id->p_encoder, p_audio_buf );
378 block_ChainAppend( out, p_block );
379 block_Release( p_audio_buf );
380 continue;
381 error:
382 if( p_audio_buf )
383 block_Release( p_audio_buf );
384 id->b_error = true;
385 } while( p_audio_bufs );
387 end:
388 /* Drain encoder */
389 if( unlikely( !id->b_error && in == NULL ) )
391 if( id->p_encoder->p_module )
393 block_t *p_block;
394 do {
395 p_block = id->p_encoder->pf_encode_audio(id->p_encoder, NULL );
396 block_ChainAppend( out, p_block );
397 } while( p_block );
401 return id->b_error ? VLC_EGENERIC : VLC_SUCCESS;
404 bool transcode_audio_add( sout_stream_t *p_stream, const es_format_t *p_fmt,
405 sout_stream_id_sys_t *id )
407 sout_stream_sys_t *p_sys = p_stream->p_sys;
409 msg_Dbg( p_stream,
410 "creating audio transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
411 (char*)&p_fmt->i_codec, (char*)&p_sys->i_acodec );
413 id->fifo.audio.first = NULL;
414 id->fifo.audio.last = &id->fifo.audio.first;
416 /* Complete destination format */
417 id->p_encoder->fmt_out.i_codec = p_sys->i_acodec;
418 id->p_encoder->fmt_out.audio.i_rate = p_sys->i_sample_rate > 0 ?
419 p_sys->i_sample_rate : p_fmt->audio.i_rate;
420 id->p_encoder->fmt_out.i_bitrate = p_sys->i_abitrate;
421 id->p_encoder->fmt_out.audio.i_bitspersample =
422 p_fmt->audio.i_bitspersample;
423 id->p_encoder->fmt_out.audio.i_channels = p_sys->i_channels > 0 ?
424 p_sys->i_channels : p_fmt->audio.i_channels;
426 if( id->p_encoder->fmt_out.audio.i_channels >= ARRAY_SIZE(pi_channels_maps) )
427 id->p_encoder->fmt_out.audio.i_channels = ARRAY_SIZE(pi_channels_maps) - 1;
429 id->p_encoder->fmt_in.audio.i_physical_channels =
430 id->p_encoder->fmt_out.audio.i_physical_channels =
431 pi_channels_maps[id->p_encoder->fmt_out.audio.i_channels];
433 /* Build decoder -> filter -> encoder chain */
434 if( transcode_audio_new( p_stream, id ) == VLC_EGENERIC )
436 msg_Err( p_stream, "cannot create audio chain" );
437 return false;
440 /* Open output stream */
441 id->b_transcode = true;
443 /* Reinit encoder again later on, when all information from decoders
444 * is available. */
445 if( id->p_encoder->p_module )
447 module_unneed( id->p_encoder, id->p_encoder->p_module );
448 id->p_encoder->p_module = NULL;
449 if( id->p_encoder->fmt_out.p_extra )
451 free( id->p_encoder->fmt_out.p_extra );
452 id->p_encoder->fmt_out.p_extra = NULL;
453 id->p_encoder->fmt_out.i_extra = 0;
455 if( id->p_af_chain != NULL )
456 aout_FiltersDelete( (vlc_object_t *)NULL, id->p_af_chain );
457 id->p_af_chain = NULL;
459 return true;