]> git.sesse.net Git - vlc/blob - modules/stream_out/transcode/audio.c
Check for MMX at build-time if possible
[vlc] / modules / stream_out / transcode / audio.c
1 /*****************************************************************************
2  * audio.c: transcoding stream output module (audio)
3  *****************************************************************************
4  * Copyright (C) 2003-2009 the VideoLAN team
5  * $Id$
6  *
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>
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
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 General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25  *****************************************************************************/
26
27 /*****************************************************************************
28  * Preamble
29  *****************************************************************************/
30
31 #include "transcode.h"
32
33 #include <vlc_aout.h>
34 #include <vlc_meta.h>
35 #include <vlc_modules.h>
36
37 static const int pi_channels_maps[6] =
38 {
39     0,
40     AOUT_CHAN_CENTER,   AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
41     AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
42     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
43      | AOUT_CHAN_REARRIGHT,
44     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
45      | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
46 };
47
48 static block_t *audio_new_buffer( decoder_t *p_dec, int i_samples )
49 {
50     block_t *p_block;
51     int i_size;
52
53     if( p_dec->fmt_out.audio.i_bitspersample )
54     {
55         i_size = i_samples * p_dec->fmt_out.audio.i_bitspersample / 8 *
56             p_dec->fmt_out.audio.i_channels;
57     }
58     else if( p_dec->fmt_out.audio.i_bytes_per_frame &&
59              p_dec->fmt_out.audio.i_frame_length )
60     {
61         i_size = i_samples * p_dec->fmt_out.audio.i_bytes_per_frame /
62             p_dec->fmt_out.audio.i_frame_length;
63     }
64     else
65     {
66         i_size = i_samples * 4 * p_dec->fmt_out.audio.i_channels;
67     }
68
69     p_block = block_New( p_dec, i_size );
70     p_block->i_nb_samples = i_samples;
71     return p_block;
72 }
73
74 static int transcode_audio_filter_allocation_init( filter_t *p_filter,
75                                                    void *data )
76 {
77     VLC_UNUSED(p_filter);
78     VLC_UNUSED(data);
79     return VLC_SUCCESS;
80 }
81
82 static bool transcode_audio_filter_needed( const es_format_t *p_fmt1, const es_format_t *p_fmt2 )
83 {
84     if( p_fmt1->i_codec != p_fmt2->i_codec ||
85         p_fmt1->audio.i_channels != p_fmt2->audio.i_channels ||
86         p_fmt1->audio.i_rate != p_fmt2->audio.i_rate )
87         return true;
88     return false;
89 }
90 static int transcode_audio_filter_chain_build( sout_stream_t *p_stream, filter_chain_t *p_chain,
91                                                const es_format_t *p_dst, const es_format_t *p_src )
92 {
93     if( !transcode_audio_filter_needed( p_dst, p_src ) )
94         return VLC_SUCCESS;
95
96     es_format_t current = *p_src;
97
98     msg_Dbg( p_stream, "Looking for filter "
99              "(%4.4s->%4.4s, channels %d->%d, rate %d->%d)",
100          (const char *)&p_src->i_codec,
101          (const char *)&p_dst->i_codec,
102          p_src->audio.i_channels,
103          p_dst->audio.i_channels,
104          p_src->audio.i_rate,
105          p_dst->audio.i_rate );
106
107     /* If any filter is needed, convert to fl32 */
108     if( current.i_codec != VLC_CODEC_FL32 )
109     {
110         /* First step, convert to fl32 */
111         current.i_codec =
112         current.audio.i_format = VLC_CODEC_FL32;
113         aout_FormatPrepare( &current.audio );
114
115         if( !filter_chain_AppendFilter( p_chain, NULL, NULL, NULL, &current ) )
116         {
117             msg_Err( p_stream, "Failed to find conversion filter to fl32" );
118             return VLC_EGENERIC;
119         }
120         current = *filter_chain_GetFmtOut( p_chain );
121     }
122
123     /* Fix sample rate */
124     if( current.audio.i_rate != p_dst->audio.i_rate )
125     {
126         current.audio.i_rate = p_dst->audio.i_rate;
127         aout_FormatPrepare( &current.audio );
128         if( !filter_chain_AppendFilter( p_chain, NULL, NULL, NULL, &current ) )
129         {
130             msg_Err( p_stream, "Failed to find conversion filter for resampling" );
131             return VLC_EGENERIC;
132         }
133         current = *filter_chain_GetFmtOut( p_chain );
134     }
135
136     /* Fix channels */
137     if( current.audio.i_channels != p_dst->audio.i_channels )
138     {
139         current.audio.i_channels = p_dst->audio.i_channels;
140         current.audio.i_physical_channels = p_dst->audio.i_physical_channels;
141         current.audio.i_original_channels = p_dst->audio.i_original_channels;
142
143         if( ( !current.audio.i_physical_channels || !current.audio.i_original_channels ) &&
144             current.audio.i_channels < 6 )
145             current.audio.i_physical_channels =
146             current.audio.i_original_channels = pi_channels_maps[current.audio.i_channels];
147
148         aout_FormatPrepare( &current.audio );
149         if( !filter_chain_AppendFilter( p_chain, NULL, NULL, NULL, &current ) )
150         {
151             msg_Err( p_stream, "Failed to find conversion filter for channel mixing" );
152             return VLC_EGENERIC;
153         }
154         current = *filter_chain_GetFmtOut( p_chain );
155     }
156     /* And last step, convert to the requested codec */
157     if( current.i_codec != p_dst->i_codec )
158     {
159         current.i_codec = p_dst->i_codec;
160         aout_FormatPrepare( &current.audio );
161         if( !filter_chain_AppendFilter( p_chain, NULL, NULL, NULL, &current ) )
162         {
163             msg_Err( p_stream, "Failed to find conversion filter to %4.4s",
164                      (const char*)&p_dst->i_codec);
165             return VLC_EGENERIC;
166         }
167         current = *filter_chain_GetFmtOut( p_chain );
168     }
169
170     if( transcode_audio_filter_needed( p_dst, &current ) )
171     {
172         /* Weird case, a filter has side effects, doomed */
173         msg_Err( p_stream, "Failed to create a valid audio filter chain" );
174         return VLC_EGENERIC;
175     }
176
177     msg_Dbg( p_stream, "Got complete audio filter chain" );
178     return VLC_SUCCESS;
179 }
180
181
182 int transcode_audio_new( sout_stream_t *p_stream,
183                                 sout_stream_id_t *id )
184 {
185     sout_stream_sys_t *p_sys = p_stream->p_sys;
186     es_format_t fmt_last;
187
188     /*
189      * Open decoder
190      */
191
192     /* Initialization of decoder structures */
193     id->p_decoder->fmt_out = id->p_decoder->fmt_in;
194     id->p_decoder->fmt_out.i_extra = 0;
195     id->p_decoder->fmt_out.p_extra = 0;
196     id->p_decoder->pf_decode_audio = NULL;
197     id->p_decoder->pf_aout_buffer_new = audio_new_buffer;
198     /* id->p_decoder->p_cfg = p_sys->p_audio_cfg; */
199
200     id->p_decoder->p_module =
201         module_need( id->p_decoder, "decoder", "$codec", false );
202     if( !id->p_decoder->p_module )
203     {
204         msg_Err( p_stream, "cannot find audio decoder" );
205         return VLC_EGENERIC;
206     }
207     /* decoders don't set audio.i_format, but audio filters use it */
208     id->p_decoder->fmt_out.audio.i_format = id->p_decoder->fmt_out.i_codec;
209     id->p_decoder->fmt_out.audio.i_bitspersample =
210         aout_BitsPerSample( id->p_decoder->fmt_out.i_codec );
211     fmt_last = id->p_decoder->fmt_out;
212     /* Fix AAC SBR changing number of channels and sampling rate */
213     if( !(id->p_decoder->fmt_in.i_codec == VLC_CODEC_MP4A &&
214         fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate &&
215         fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels) )
216         fmt_last.audio.i_rate = id->p_decoder->fmt_in.audio.i_rate;
217
218     /*
219      * Open encoder
220      */
221
222     /* Initialization of encoder format structures */
223     es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
224                     id->p_decoder->fmt_out.i_codec );
225     id->p_encoder->fmt_in.audio.i_format = id->p_decoder->fmt_out.i_codec;
226
227     id->p_encoder->fmt_in.audio.i_rate = id->p_encoder->fmt_out.audio.i_rate;
228     id->p_encoder->fmt_in.audio.i_physical_channels =
229         id->p_encoder->fmt_out.audio.i_physical_channels;
230     id->p_encoder->fmt_in.audio.i_original_channels =
231         id->p_encoder->fmt_out.audio.i_original_channels;
232     id->p_encoder->fmt_in.audio.i_channels =
233         id->p_encoder->fmt_out.audio.i_channels;
234     id->p_encoder->fmt_in.audio.i_bitspersample =
235         aout_BitsPerSample( id->p_encoder->fmt_in.i_codec );
236
237     id->p_encoder->p_cfg = p_stream->p_sys->p_audio_cfg;
238     id->p_encoder->p_module =
239         module_need( id->p_encoder, "encoder", p_sys->psz_aenc, true );
240     if( !id->p_encoder->p_module )
241     {
242         msg_Err( p_stream, "cannot find audio encoder (module:%s fourcc:%4.4s). Take a look few lines earlier to see possible reason.",
243                  p_sys->psz_aenc ? p_sys->psz_aenc : "any",
244                  (char *)&p_sys->i_acodec );
245         module_unneed( id->p_decoder, id->p_decoder->p_module );
246         id->p_decoder->p_module = NULL;
247         return VLC_EGENERIC;
248     }
249     id->p_encoder->fmt_in.audio.i_format = id->p_encoder->fmt_in.i_codec;
250     id->p_encoder->fmt_in.audio.i_bitspersample =
251         aout_BitsPerSample( id->p_encoder->fmt_in.i_codec );
252
253     /* Load user specified audio filters */
254     if( p_sys->psz_af )
255     {
256         es_format_t fmt_fl32 = fmt_last;
257         fmt_fl32.i_codec =
258         fmt_fl32.audio.i_format = VLC_CODEC_FL32;
259         id->p_uf_chain = filter_chain_New( p_stream, "audio filter", false,
260                                            transcode_audio_filter_allocation_init, NULL, NULL );
261         filter_chain_Reset( id->p_uf_chain, &fmt_last, &fmt_fl32 );
262
263         if( transcode_audio_filter_chain_build( p_stream, id->p_uf_chain,
264                                                 &fmt_fl32, &fmt_last ) )
265         {
266             transcode_audio_close( id );
267             return VLC_EGENERIC;
268         }
269         fmt_last = fmt_fl32;
270
271         if( filter_chain_AppendFromString( id->p_uf_chain, p_sys->psz_af ) > 0 )
272             fmt_last = *filter_chain_GetFmtOut( id->p_uf_chain );
273     }
274
275     /* Load conversion filters */
276     id->p_f_chain = filter_chain_New( p_stream, "audio filter", true,
277                     transcode_audio_filter_allocation_init, NULL, NULL );
278     filter_chain_Reset( id->p_f_chain, &fmt_last, &id->p_encoder->fmt_in );
279
280     if( transcode_audio_filter_chain_build( p_stream, id->p_f_chain,
281                                             &id->p_encoder->fmt_in, &fmt_last ) )
282     {
283         transcode_audio_close( id );
284         return VLC_EGENERIC;
285     }
286     fmt_last = id->p_encoder->fmt_in;
287
288     /* */
289     id->p_encoder->fmt_out.i_codec =
290         vlc_fourcc_GetCodec( AUDIO_ES, id->p_encoder->fmt_out.i_codec );
291
292     return VLC_SUCCESS;
293 }
294
295 void transcode_audio_close( sout_stream_id_t *id )
296 {
297     /* Close decoder */
298     if( id->p_decoder->p_module )
299         module_unneed( id->p_decoder, id->p_decoder->p_module );
300     id->p_decoder->p_module = NULL;
301
302     if( id->p_decoder->p_description )
303         vlc_meta_Delete( id->p_decoder->p_description );
304     id->p_decoder->p_description = NULL;
305
306     /* Close encoder */
307     if( id->p_encoder->p_module )
308         module_unneed( id->p_encoder, id->p_encoder->p_module );
309     id->p_encoder->p_module = NULL;
310
311     /* Close filters */
312     if( id->p_uf_chain )
313         filter_chain_Delete( id->p_uf_chain );
314     if( id->p_f_chain )
315         filter_chain_Delete( id->p_f_chain );
316 }
317
318 int transcode_audio_process( sout_stream_t *p_stream,
319                                     sout_stream_id_t *id,
320                                     block_t *in, block_t **out )
321 {
322     sout_stream_sys_t *p_sys = p_stream->p_sys;
323     block_t *p_block, *p_audio_buf;
324     *out = NULL;
325
326     while( (p_audio_buf = id->p_decoder->pf_decode_audio( id->p_decoder,
327                                                           &in )) )
328     {
329         if( p_sys->b_master_sync )
330         {
331             mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
332             mtime_t i_drift = p_audio_buf->i_pts - i_pts;
333             if (i_drift > MASTER_SYNC_MAX_DRIFT || i_drift < -MASTER_SYNC_MAX_DRIFT)
334             {
335                 msg_Dbg( p_stream,
336                     "drift is too high (%"PRId64"), resetting master sync",
337                     i_drift );
338                 date_Set( &id->interpolated_pts, p_audio_buf->i_pts );
339                 i_pts = p_audio_buf->i_pts + 1;
340             }
341             p_sys->i_master_drift = p_audio_buf->i_pts - i_pts;
342             date_Increment( &id->interpolated_pts, p_audio_buf->i_nb_samples );
343             p_audio_buf->i_pts = i_pts;
344         }
345
346         p_audio_buf->i_dts = p_audio_buf->i_pts;
347
348         /* Run filter chain */
349         if( id->p_uf_chain )
350         {
351             p_audio_buf = filter_chain_AudioFilter( id->p_uf_chain,
352                                                     p_audio_buf );
353             if( !p_audio_buf )
354                 abort();
355         }
356
357         p_audio_buf = filter_chain_AudioFilter( id->p_f_chain, p_audio_buf );
358         if( !p_audio_buf )
359             abort();
360
361         p_audio_buf->i_dts = p_audio_buf->i_pts;
362
363         p_block = id->p_encoder->pf_encode_audio( id->p_encoder, p_audio_buf );
364
365         block_ChainAppend( out, p_block );
366         block_Release( p_audio_buf );
367     }
368
369     return VLC_SUCCESS;
370 }
371
372 bool transcode_audio_add( sout_stream_t *p_stream, es_format_t *p_fmt, 
373             sout_stream_id_t *id )
374 {
375     sout_stream_sys_t *p_sys = p_stream->p_sys;
376
377     msg_Dbg( p_stream,
378              "creating audio transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
379              (char*)&p_fmt->i_codec, (char*)&p_sys->i_acodec );
380
381     /* Complete destination format */
382     id->p_encoder->fmt_out.i_codec = p_sys->i_acodec;
383     id->p_encoder->fmt_out.audio.i_rate = p_sys->i_sample_rate > 0 ?
384         p_sys->i_sample_rate : p_fmt->audio.i_rate;
385     id->p_encoder->fmt_out.i_bitrate = p_sys->i_abitrate;
386     id->p_encoder->fmt_out.audio.i_bitspersample =
387         p_fmt->audio.i_bitspersample;
388     id->p_encoder->fmt_out.audio.i_channels = p_sys->i_channels > 0 ?
389         p_sys->i_channels : p_fmt->audio.i_channels;
390     /* Sanity check for audio channels */
391     id->p_encoder->fmt_out.audio.i_channels =
392         __MIN( id->p_encoder->fmt_out.audio.i_channels,
393                id->p_decoder->fmt_in.audio.i_channels );
394     id->p_encoder->fmt_out.audio.i_original_channels =
395         id->p_decoder->fmt_in.audio.i_physical_channels;
396     if( id->p_decoder->fmt_in.audio.i_channels ==
397         id->p_encoder->fmt_out.audio.i_channels )
398     {
399         id->p_encoder->fmt_out.audio.i_physical_channels =
400             id->p_decoder->fmt_in.audio.i_physical_channels;
401     }
402     else
403     {
404         id->p_encoder->fmt_out.audio.i_physical_channels =
405             pi_channels_maps[id->p_encoder->fmt_out.audio.i_channels];
406     }
407
408     /* Build decoder -> filter -> encoder chain */
409     if( transcode_audio_new( p_stream, id ) )
410     {
411         msg_Err( p_stream, "cannot create audio chain" );
412         return false;
413     }
414
415     /* Open output stream */
416     id->id = sout_StreamIdAdd( p_stream->p_next, &id->p_encoder->fmt_out );
417     id->b_transcode = true;
418
419     if( !id->id )
420     {
421         transcode_audio_close( id );
422         return false;
423     }
424
425     date_Init( &id->interpolated_pts, p_fmt->audio.i_rate, 1 );
426
427     return true;
428 }