s/sout_stream_id_t/sout_stream_id_sys_t/
[vlc.git] / modules / stream_out / transcode / audio.c
blobe298873d647e10517719467ba5e871cb06973c29
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[6] =
41 AOUT_CHAN_CENTER, AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
42 AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
43 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
44 | AOUT_CHAN_REARRIGHT,
45 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
46 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
49 static int audio_update_format( decoder_t *p_dec )
51 aout_FormatPrepare( &p_dec->fmt_out.audio );
52 return 0;
55 static int transcode_audio_initialize_filters( sout_stream_t *p_stream, sout_stream_id_sys_t *id,
56 sout_stream_sys_t *p_sys, audio_sample_format_t *fmt_last )
58 /* Load user specified audio filters */
59 /* XXX: These variable names come kinda out of nowhere... */
60 var_Create( p_stream, "audio-time-stretch", VLC_VAR_BOOL );
61 var_Create( p_stream, "audio-filter", VLC_VAR_STRING );
62 if( p_sys->psz_af )
63 var_SetString( p_stream, "audio-filter", p_sys->psz_af );
64 id->p_af_chain = aout_FiltersNew( p_stream, fmt_last,
65 &id->p_encoder->fmt_in.audio, NULL );
66 var_Destroy( p_stream, "audio-filter" );
67 var_Destroy( p_stream, "audio-time-stretch" );
68 if( id->p_af_chain == NULL )
70 msg_Err( p_stream, "Unable to initialize audio filters" );
71 module_unneed( id->p_encoder, id->p_encoder->p_module );
72 id->p_encoder->p_module = NULL;
73 module_unneed( id->p_decoder, id->p_decoder->p_module );
74 id->p_decoder->p_module = NULL;
75 return VLC_EGENERIC;
77 p_sys->fmt_audio.i_rate = fmt_last->i_rate;
78 p_sys->fmt_audio.i_physical_channels = fmt_last->i_physical_channels;
79 return VLC_SUCCESS;
82 static int transcode_audio_initialize_encoder( sout_stream_id_sys_t *id, sout_stream_t *p_stream )
84 sout_stream_sys_t *p_sys = p_stream->p_sys;
85 /* Initialization of encoder format structures */
86 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
87 id->p_decoder->fmt_out.i_codec );
88 id->p_encoder->fmt_in.audio.i_format = id->p_decoder->fmt_out.i_codec;
89 id->p_encoder->fmt_in.audio.i_rate = id->p_encoder->fmt_out.audio.i_rate;
90 id->p_encoder->fmt_in.audio.i_physical_channels =
91 id->p_encoder->fmt_out.audio.i_physical_channels;
92 aout_FormatPrepare( &id->p_encoder->fmt_in.audio );
94 id->p_encoder->p_cfg = p_stream->p_sys->p_audio_cfg;
95 id->p_encoder->p_module =
96 module_need( id->p_encoder, "encoder", p_sys->psz_aenc, true );
97 /* p_sys->i_acodec = 0 if there isn't acodec defined */
98 if( !id->p_encoder->p_module && p_sys->i_acodec )
100 msg_Err( p_stream, "cannot find audio encoder (module:%s fourcc:%4.4s). "
101 "Take a look few lines earlier to see possible reason.",
102 p_sys->psz_aenc ? p_sys->psz_aenc : "any",
103 (char *)&p_sys->i_acodec );
104 module_unneed( id->p_decoder, id->p_decoder->p_module );
105 id->p_decoder->p_module = NULL;
106 return VLC_EGENERIC;
109 id->p_encoder->fmt_out.i_codec =
110 vlc_fourcc_GetCodec( AUDIO_ES, id->p_encoder->fmt_out.i_codec );
112 /* Fix input format */
113 id->p_encoder->fmt_in.audio.i_format = id->p_encoder->fmt_in.i_codec;
114 if( !id->p_encoder->fmt_in.audio.i_physical_channels
115 || !id->p_encoder->fmt_in.audio.i_original_channels )
117 if( id->p_encoder->fmt_in.audio.i_channels < 6 )
118 id->p_encoder->fmt_in.audio.i_physical_channels =
119 id->p_encoder->fmt_in.audio.i_original_channels =
120 pi_channels_maps[id->p_encoder->fmt_in.audio.i_channels];
122 aout_FormatPrepare( &id->p_encoder->fmt_in.audio );
124 return VLC_SUCCESS;
127 int transcode_audio_new( sout_stream_t *p_stream,
128 sout_stream_id_sys_t *id )
130 sout_stream_sys_t *p_sys = p_stream->p_sys;
131 audio_sample_format_t fmt_last;
134 * Open decoder
137 /* Initialization of decoder structures */
138 id->p_decoder->fmt_out = id->p_decoder->fmt_in;
139 id->p_decoder->fmt_out.i_extra = 0;
140 id->p_decoder->fmt_out.p_extra = 0;
141 id->p_decoder->pf_decode_audio = NULL;
142 id->p_decoder->pf_aout_format_update = audio_update_format;
143 /* id->p_decoder->p_cfg = p_sys->p_audio_cfg; */
144 id->p_decoder->p_module =
145 module_need( id->p_decoder, "decoder", "$codec", false );
146 if( !id->p_decoder->p_module )
148 msg_Err( p_stream, "cannot find audio decoder" );
149 return VLC_EGENERIC;
151 /* decoders don't set audio.i_format, but audio filters use it */
152 id->p_decoder->fmt_out.audio.i_format = id->p_decoder->fmt_out.i_codec;
153 aout_FormatPrepare( &id->p_decoder->fmt_out.audio );
154 fmt_last = id->p_decoder->fmt_out.audio;
155 /* Fix AAC SBR changing number of channels and sampling rate */
156 if( !(id->p_decoder->fmt_in.i_codec == VLC_CODEC_MP4A &&
157 fmt_last.i_rate != id->p_encoder->fmt_in.audio.i_rate &&
158 fmt_last.i_channels != id->p_encoder->fmt_in.audio.i_channels) )
159 fmt_last.i_rate = id->p_decoder->fmt_in.audio.i_rate;
162 * Open encoder
164 if( transcode_audio_initialize_encoder( id, p_stream ) == VLC_EGENERIC )
165 return VLC_EGENERIC;
167 if( unlikely( transcode_audio_initialize_filters( p_stream, id, p_sys,
168 &fmt_last ) != VLC_SUCCESS ) )
169 return VLC_EGENERIC;
171 return VLC_SUCCESS;
174 void transcode_audio_close( sout_stream_id_sys_t *id )
176 /* Close decoder */
177 if( id->p_decoder->p_module )
178 module_unneed( id->p_decoder, id->p_decoder->p_module );
179 id->p_decoder->p_module = NULL;
181 if( id->p_decoder->p_description )
182 vlc_meta_Delete( id->p_decoder->p_description );
183 id->p_decoder->p_description = NULL;
185 /* Close encoder */
186 if( id->p_encoder->p_module )
187 module_unneed( id->p_encoder, id->p_encoder->p_module );
188 id->p_encoder->p_module = NULL;
190 /* Close filters */
191 if( id->p_af_chain != NULL )
192 aout_FiltersDelete( (vlc_object_t *)NULL, id->p_af_chain );
195 int transcode_audio_process( sout_stream_t *p_stream,
196 sout_stream_id_sys_t *id,
197 block_t *in, block_t **out )
199 sout_stream_sys_t *p_sys = p_stream->p_sys;
200 block_t *p_block, *p_audio_buf;
201 *out = NULL;
203 if( unlikely( in == NULL ) )
205 block_t *p_block;
206 do {
207 p_block = id->p_encoder->pf_encode_audio(id->p_encoder, NULL );
208 block_ChainAppend( out, p_block );
209 } while( p_block );
210 return VLC_SUCCESS;
213 while( (p_audio_buf = id->p_decoder->pf_decode_audio( id->p_decoder,
214 &in )) )
216 if( unlikely( !id->p_encoder->p_module ) )
218 /* Complete destination format */
219 id->p_encoder->fmt_out.i_codec = p_sys->i_acodec;
220 id->p_encoder->fmt_out.audio.i_rate = p_sys->i_sample_rate > 0 ?
221 p_sys->i_sample_rate : id->p_decoder->fmt_out.audio.i_rate;
222 id->p_encoder->fmt_out.i_bitrate = p_sys->i_abitrate;
223 id->p_encoder->fmt_out.audio.i_bitspersample =
224 id->p_decoder->fmt_out.audio.i_bitspersample;
225 id->p_encoder->fmt_out.audio.i_channels = p_sys->i_channels > 0 ?
226 p_sys->i_channels : id->p_decoder->fmt_out.audio.i_channels;
227 /* Sanity check for audio channels */
228 id->p_encoder->fmt_out.audio.i_channels =
229 __MIN( id->p_encoder->fmt_out.audio.i_channels,
230 id->p_decoder->fmt_out.audio.i_channels );
231 id->p_encoder->fmt_out.audio.i_original_channels =
232 id->p_decoder->fmt_in.audio.i_physical_channels;
233 id->p_encoder->fmt_out.audio.i_physical_channels =
234 pi_channels_maps[id->p_encoder->fmt_out.audio.i_channels];
235 if( transcode_audio_initialize_encoder( id, p_stream ) )
237 msg_Err( p_stream, "cannot create audio chain" );
238 return VLC_EGENERIC;
240 if( unlikely( transcode_audio_initialize_filters( p_stream, id, p_sys,
241 &id->p_decoder->fmt_out.audio ) != VLC_SUCCESS ) )
242 return VLC_EGENERIC;
243 date_Init( &id->interpolated_pts, id->p_decoder->fmt_out.audio.i_rate, 1 );
244 date_Set( &id->interpolated_pts, p_audio_buf->i_pts );
247 /* Check if audio format has changed, and filters need reinit */
248 if( unlikely( ( id->p_decoder->fmt_out.audio.i_rate != p_sys->fmt_audio.i_rate ) ||
249 ( id->p_decoder->fmt_out.audio.i_physical_channels != p_sys->fmt_audio.i_physical_channels ) ) )
251 msg_Info( p_stream, "Audio changed, trying to reinitialize filters" );
252 if( id->p_af_chain != NULL )
253 aout_FiltersDelete( (vlc_object_t *)NULL, id->p_af_chain );
255 /* decoders don't set audio.i_format, but audio filters use it */
256 id->p_decoder->fmt_out.audio.i_format = id->p_decoder->fmt_out.i_codec;
257 aout_FormatPrepare( &id->p_decoder->fmt_out.audio );
259 if( transcode_audio_initialize_filters( p_stream, id, p_sys,
260 &id->p_decoder->fmt_out.audio ) != VLC_SUCCESS )
261 return VLC_EGENERIC;
263 /* Set interpolated_pts to run with new samplerate */
264 date_Init( &id->interpolated_pts, p_sys->fmt_audio.i_rate, 1 );
265 date_Set( &id->interpolated_pts, p_audio_buf->i_pts );
268 if( p_sys->b_master_sync )
270 mtime_t i_pts = date_Get( &id->interpolated_pts );
271 mtime_t i_drift = 0;
273 if( likely( p_audio_buf->i_pts != VLC_TS_INVALID ) )
274 i_drift = p_audio_buf->i_pts - i_pts;
276 if ( unlikely(i_drift > MASTER_SYNC_MAX_DRIFT
277 || i_drift < -MASTER_SYNC_MAX_DRIFT) )
279 msg_Dbg( p_stream,
280 "audio drift is too high (%"PRId64"), resetting master sync",
281 i_drift );
282 date_Set( &id->interpolated_pts, p_audio_buf->i_pts );
283 i_pts = date_Get( &id->interpolated_pts );
284 if( likely(p_audio_buf->i_pts != VLC_TS_INVALID ) )
285 i_drift = p_audio_buf->i_pts - i_pts;
287 p_sys->i_master_drift = i_drift;
288 date_Increment( &id->interpolated_pts, p_audio_buf->i_nb_samples );
291 p_audio_buf->i_dts = p_audio_buf->i_pts;
293 /* Run filter chain */
294 p_audio_buf = aout_FiltersPlay( id->p_af_chain, p_audio_buf,
295 INPUT_RATE_DEFAULT );
296 if( !p_audio_buf )
297 abort();
299 p_audio_buf->i_dts = p_audio_buf->i_pts;
301 p_block = id->p_encoder->pf_encode_audio( id->p_encoder, p_audio_buf );
303 block_ChainAppend( out, p_block );
304 block_Release( p_audio_buf );
307 return VLC_SUCCESS;
310 bool transcode_audio_add( sout_stream_t *p_stream, es_format_t *p_fmt,
311 sout_stream_id_sys_t *id )
313 sout_stream_sys_t *p_sys = p_stream->p_sys;
315 msg_Dbg( p_stream,
316 "creating audio transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
317 (char*)&p_fmt->i_codec, (char*)&p_sys->i_acodec );
319 /* Complete destination format */
320 id->p_encoder->fmt_out.i_codec = p_sys->i_acodec;
321 id->p_encoder->fmt_out.audio.i_rate = p_sys->i_sample_rate > 0 ?
322 p_sys->i_sample_rate : p_fmt->audio.i_rate;
323 id->p_encoder->fmt_out.i_bitrate = p_sys->i_abitrate;
324 id->p_encoder->fmt_out.audio.i_bitspersample =
325 p_fmt->audio.i_bitspersample;
326 id->p_encoder->fmt_out.audio.i_channels = p_sys->i_channels > 0 ?
327 p_sys->i_channels : p_fmt->audio.i_channels;
328 /* Sanity check for audio channels */
329 id->p_encoder->fmt_out.audio.i_channels =
330 __MIN( id->p_encoder->fmt_out.audio.i_channels,
331 id->p_decoder->fmt_in.audio.i_channels );
332 id->p_encoder->fmt_out.audio.i_original_channels =
333 id->p_decoder->fmt_in.audio.i_physical_channels;
334 id->p_encoder->fmt_out.audio.i_physical_channels =
335 pi_channels_maps[id->p_encoder->fmt_out.audio.i_channels];
337 /* Build decoder -> filter -> encoder chain */
338 if( transcode_audio_new( p_stream, id ) == VLC_EGENERIC )
340 msg_Err( p_stream, "cannot create audio chain" );
341 return false;
344 /* Open output stream */
345 id->id = sout_StreamIdAdd( p_stream->p_next, &id->p_encoder->fmt_out );
346 id->b_transcode = true;
348 if( !id->id )
350 transcode_audio_close( id );
351 return false;
354 /* Reinit encoder again later on, when all information from decoders
355 * is available. */
356 if( id->p_encoder->p_module )
358 module_unneed( id->p_encoder, id->p_encoder->p_module );
359 id->p_encoder->p_module = NULL;
360 if( id->p_encoder->fmt_out.p_extra )
362 free( id->p_encoder->fmt_out.p_extra );
363 id->p_encoder->fmt_out.p_extra = NULL;
364 id->p_encoder->fmt_out.i_extra = 0;
366 if( id->p_af_chain != NULL )
367 aout_FiltersDelete( (vlc_object_t *)NULL, id->p_af_chain );
368 id->p_af_chain = NULL;
371 date_Init( &id->interpolated_pts, p_fmt->audio.i_rate, 1 );
373 return true;