1 /*****************************************************************************
2 * audio.c: transcoding stream output module (audio)
3 *****************************************************************************
4 * Copyright (C) 2003-2009 VLC authors and VideoLAN
6 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
7 * Gildas Bazin <gbazin@videolan.org>
8 * Jean-Paul Saman <jpsaman #_at_# m2x dot nl>
9 * Antoine Cellerier <dionoea at videolan dot org>
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation; either version 2.1 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public License
22 * along with this program; if not, write to the Free Software Foundation,
23 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24 *****************************************************************************/
26 /*****************************************************************************
28 *****************************************************************************/
33 #include <vlc_common.h>
35 #include <vlc_input.h>
37 #include <vlc_modules.h>
40 #include "transcode.h"
42 static int audio_update_format( decoder_t
*p_dec
)
44 struct decoder_owner
*p_owner
= dec_get_owner( p_dec
);
45 sout_stream_id_sys_t
*id
= p_owner
->id
;
47 if( !AOUT_FMT_LINEAR(&p_dec
->fmt_out
.audio
) )
50 p_dec
->fmt_out
.audio
.i_format
= p_dec
->fmt_out
.i_codec
;
51 aout_FormatPrepare( &p_dec
->fmt_out
.audio
);
53 vlc_mutex_lock(&id
->fifo
.lock
);
54 es_format_Clean( &id
->decoder_out
);
55 es_format_Copy( &id
->decoder_out
, &p_dec
->fmt_out
);
56 vlc_mutex_unlock(&id
->fifo
.lock
);
61 static int transcode_audio_filters_init( sout_stream_t
*p_stream
,
62 const sout_filters_config_t
*p_cfg
,
63 const audio_format_t
*p_dec_out
,
64 const audio_format_t
*p_enc_in
,
65 aout_filters_t
**pp_chain
)
67 /* Load user specified audio filters */
68 /* XXX: These variable names come kinda out of nowhere... */
69 var_Create( p_stream
, "audio-time-stretch", VLC_VAR_BOOL
);
70 var_Create( p_stream
, "audio-filter", VLC_VAR_STRING
);
71 if( p_cfg
->psz_filters
)
72 var_SetString( p_stream
, "audio-filter", p_cfg
->psz_filters
);
73 *pp_chain
= aout_FiltersNew( p_stream
, p_dec_out
, p_enc_in
, NULL
);
74 var_Destroy( p_stream
, "audio-filter" );
75 var_Destroy( p_stream
, "audio-time-stretch" );
76 return ( *pp_chain
!= NULL
) ? VLC_SUCCESS
: VLC_EGENERIC
;
79 static void decoder_queue_audio( decoder_t
*p_dec
, block_t
*p_audio
)
81 struct decoder_owner
*p_owner
= dec_get_owner( p_dec
);
82 sout_stream_id_sys_t
*id
= p_owner
->id
;
84 vlc_mutex_lock(&id
->fifo
.lock
);
85 *id
->fifo
.audio
.last
= p_audio
;
86 id
->fifo
.audio
.last
= &p_audio
->p_next
;
87 vlc_mutex_unlock(&id
->fifo
.lock
);
90 static block_t
*transcode_dequeue_all_audios( sout_stream_id_sys_t
*id
)
92 vlc_mutex_lock(&id
->fifo
.lock
);
93 block_t
*p_audio_bufs
= id
->fifo
.audio
.first
;
94 id
->fifo
.audio
.first
= NULL
;
95 id
->fifo
.audio
.last
= &id
->fifo
.audio
.first
;
96 vlc_mutex_unlock(&id
->fifo
.lock
);
101 int transcode_audio_init( sout_stream_t
*p_stream
, const es_format_t
*p_fmt
,
102 sout_stream_id_sys_t
*id
)
105 "creating audio transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
106 (char*)&p_fmt
->i_codec
, (char*)&id
->p_enccfg
->i_codec
);
108 id
->fifo
.audio
.first
= NULL
;
109 id
->fifo
.audio
.last
= &id
->fifo
.audio
.first
;
110 id
->b_transcode
= true;
111 es_format_Init( &id
->decoder_out
, AUDIO_ES
, 0 );
116 dec_get_owner( id
->p_decoder
)->id
= id
;
118 static const struct decoder_owner_callbacks dec_cbs
=
121 .format_update
= audio_update_format
,
122 .queue
= decoder_queue_audio
,
125 id
->p_decoder
->cbs
= &dec_cbs
;
126 id
->p_decoder
->pf_decode
= NULL
;
127 id
->p_decoder
->p_module
= module_need_var( id
->p_decoder
, "audio decoder", "codec" );
128 if( !id
->p_decoder
->p_module
)
130 msg_Err( p_stream
, "cannot find audio decoder" );
131 es_format_Clean( &id
->decoder_out
);
135 if( id
->decoder_out
.i_codec
== 0 ) /* format_update can happen on open() */
137 es_format_Clean( &id
->decoder_out
);
138 es_format_Copy( &id
->decoder_out
, &id
->p_decoder
->fmt_out
);
141 vlc_mutex_lock(&id
->fifo
.lock
);
143 /* The decoder fmt_out can be uninitialized here (since it can initialized
144 * asynchronously). Fix decoder_out with default values in that case.
145 * This should be enough to initialize the encoder for the first time (it
146 * will be reloaded when all informations from the decoder are available).
148 id
->decoder_out
.audio
.i_format
= FIRSTVALID( id
->decoder_out
.audio
.i_format
,
149 id
->p_decoder
->fmt_out
.i_codec
,
151 id
->decoder_out
.audio
.i_rate
= FIRSTVALID( id
->decoder_out
.audio
.i_rate
,
152 id
->p_decoder
->fmt_in
.audio
.i_rate
,
154 id
->decoder_out
.audio
.i_physical_channels
=
155 FIRSTVALID( id
->decoder_out
.audio
.i_physical_channels
,
156 id
->p_decoder
->fmt_in
.audio
.i_physical_channels
,
158 aout_FormatPrepare( &id
->decoder_out
.audio
);
160 /* Should be the same format until encoder loads */
161 es_format_t encoder_tested_fmt_in
;
162 es_format_Init( &encoder_tested_fmt_in
, id
->decoder_out
.i_cat
, 0 );
164 /* The decoder fmt_out can be uninitialized here (since it can initialized
165 * asynchronously). Fix audio_dec_out with default values in that case.
166 * This should be enough to initialize the encoder for the first time (it
167 * will be reloaded when all informations from the decoder are available).
169 if( transcode_encoder_test( VLC_OBJECT(p_stream
),
172 id
->p_decoder
->fmt_out
.i_codec
,
173 &encoder_tested_fmt_in
) )
175 vlc_mutex_unlock(&id
->fifo
.lock
);
176 module_unneed( id
->p_decoder
, id
->p_decoder
->p_module
);
177 id
->p_decoder
->p_module
= NULL
;
178 es_format_Clean( &id
->decoder_out
);
179 es_format_Clean( &encoder_tested_fmt_in
);
183 es_format_SetMeta( &encoder_tested_fmt_in
, p_fmt
);
185 vlc_mutex_unlock(&id
->fifo
.lock
);
187 id
->encoder
= transcode_encoder_new( VLC_OBJECT(p_stream
), &encoder_tested_fmt_in
);
190 module_unneed( id
->p_decoder
, id
->p_decoder
->p_module
);
191 id
->p_decoder
->p_module
= NULL
;
192 es_format_Clean( &id
->decoder_out
);
193 es_format_Clean( &encoder_tested_fmt_in
);
197 es_format_Clean( &encoder_tested_fmt_in
);
202 void transcode_audio_clean( sout_stream_t
*p_stream
, sout_stream_id_sys_t
*id
)
205 if( id
->p_decoder
->p_module
)
206 module_unneed( id
->p_decoder
, id
->p_decoder
->p_module
);
207 id
->p_decoder
->p_module
= NULL
;
209 if( id
->p_decoder
->p_description
)
210 vlc_meta_Delete( id
->p_decoder
->p_description
);
211 id
->p_decoder
->p_description
= NULL
;
214 transcode_encoder_close( id
->encoder
);
215 transcode_encoder_delete( id
->encoder
);
217 es_format_Clean( &id
->decoder_out
);
220 if( id
->p_af_chain
!= NULL
)
221 aout_FiltersDelete( p_stream
, id
->p_af_chain
);
224 static bool transcode_audio_format_IsSimilar( const audio_format_t
*a
,
225 const audio_format_t
*b
)
228 a
->i_rate
== b
->i_rate
&&
229 a
->i_physical_channels
== b
->i_physical_channels
;
232 int transcode_audio_process( sout_stream_t
*p_stream
,
233 sout_stream_id_sys_t
*id
,
234 block_t
*in
, block_t
**out
)
238 int ret
= id
->p_decoder
->pf_decode( id
->p_decoder
, in
);
239 if( ret
!= VLCDEC_SUCCESS
)
242 block_t
*p_audio_bufs
= transcode_dequeue_all_audios( id
);
246 block_t
*p_audio_buf
= p_audio_bufs
;
247 if( p_audio_buf
== NULL
)
249 p_audio_bufs
= p_audio_buf
->p_next
;
250 p_audio_buf
->p_next
= NULL
;
254 block_Release( p_audio_buf
);
258 vlc_mutex_lock(&id
->fifo
.lock
);
260 if( p_audio_buf
&& ( unlikely(!transcode_encoder_opened( id
->encoder
)) ||
261 !transcode_audio_format_IsSimilar( &id
->fmt_input_audio
, &id
->decoder_out
.audio
) ) )
263 if( !transcode_encoder_opened( id
->encoder
) )
265 transcode_encoder_audio_configure( VLC_OBJECT(p_stream
), id
->p_enccfg
,
266 &id
->decoder_out
.audio
, id
->encoder
, true );
267 id
->fmt_input_audio
= id
->decoder_out
.audio
;
271 /* Check if audio format has changed, and filters need reinit */
272 msg_Info( p_stream
, "Audio changed, trying to reinitialize filters" );
273 if( id
->p_af_chain
!= NULL
)
275 aout_FiltersDelete( p_stream
, id
->p_af_chain
);
276 id
->p_af_chain
= NULL
;
280 if( !id
->p_af_chain
&&
281 transcode_audio_filters_init( p_stream
,
283 &id
->decoder_out
.audio
,
284 &transcode_encoder_format_in( id
->encoder
)->audio
,
287 vlc_mutex_unlock(&id
->fifo
.lock
);
291 date_Init( &id
->next_input_pts
, id
->decoder_out
.audio
.i_rate
, 1 );
292 date_Set( &id
->next_input_pts
, p_audio_buf
->i_pts
);
294 if( !transcode_encoder_opened( id
->encoder
) &&
295 transcode_encoder_open( id
->encoder
, id
->p_enccfg
) )
297 vlc_mutex_unlock(&id
->fifo
.lock
);
301 if( !id
->downstream_id
)
303 id
->pf_transcode_downstream_add( p_stream
,
304 &id
->p_decoder
->fmt_in
,
305 transcode_encoder_format_out( id
->encoder
) );
306 if( !id
->downstream_id
)
308 msg_Err( p_stream
, "cannot output transcoded stream %4.4s",
309 (char *) &id
->p_enccfg
->i_codec
);
310 vlc_mutex_unlock(&id
->fifo
.lock
);
315 vlc_mutex_unlock(&id
->fifo
.lock
);
317 if( id
->pf_drift_validate
)
319 vlc_tick_t i_pts
= date_Get( &id
->next_input_pts
);
320 vlc_tick_t i_drift
= 0;
322 if( likely( p_audio_buf
->i_pts
!= VLC_TICK_INVALID
) )
323 i_drift
= p_audio_buf
->i_pts
- i_pts
;
324 if( id
->pf_drift_validate( id
->callback_data
, i_drift
) != VLC_SUCCESS
)
326 date_Set( &id
->next_input_pts
, p_audio_buf
->i_pts
);
330 vlc_mutex_lock(&id
->fifo
.lock
);
331 id
->i_drift
= i_drift
;
332 vlc_mutex_unlock(&id
->fifo
.lock
);
333 date_Increment( &id
->next_input_pts
, p_audio_buf
->i_nb_samples
);
336 p_audio_buf
->i_dts
= p_audio_buf
->i_pts
;
338 /* Run filter chain */
339 p_audio_buf
= aout_FiltersPlay( id
->p_af_chain
, p_audio_buf
, 1.f
);
343 p_audio_buf
->i_dts
= p_audio_buf
->i_pts
;
345 block_t
*p_block
= transcode_encoder_encode( id
->encoder
, p_audio_buf
);
346 block_ChainAppend( out
, p_block
);
347 block_Release( p_audio_buf
);
351 block_Release( p_audio_buf
);
353 } while( p_audio_bufs
);
356 if( unlikely( !id
->b_error
&& in
== NULL
) && transcode_encoder_opened( id
->encoder
) )
358 transcode_encoder_drain( id
->encoder
, out
);
361 return id
->b_error
? VLC_EGENERIC
: VLC_SUCCESS
;