1 /*****************************************************************************
2 * ac3_spdif.c: ac3 pass-through to external decoder with enabled soundcard
3 *****************************************************************************
4 * Copyright (C) 2001 VideoLAN
5 * $Id: ac3_spdif.c,v 1.24 2002/05/17 18:01:25 stef Exp $
7 * Authors: Stéphane Borel <stef@via.ecp.fr>
8 * Juha Yrjola <jyrjola@cc.hut.fi>
9 * German Gomez Garcia <german@piraos.com>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 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 General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
24 *****************************************************************************/
26 /*****************************************************************************
28 *****************************************************************************/
31 #include <string.h> /* memcpy() */
34 #include <videolan/vlc.h>
40 #include "audio_output.h"
42 #include "stream_control.h"
43 #include "input_ext-dec.h"
45 #include "ac3_spdif.h"
47 /****************************************************************************
49 ****************************************************************************/
50 static int decoder_Probe ( u8 * );
51 static int decoder_Run ( decoder_config_t * );
52 static int InitThread ( ac3_spdif_thread_t * );
53 static void EndThread ( ac3_spdif_thread_t * );
54 static void BitstreamCallback ( bit_stream_t *, boolean_t );
56 int ac3_parse_syncinfo ( struct ac3_spdif_thread_s * );
58 /****************************************************************************
59 * Local structures and tables
60 ****************************************************************************/
61 static const frame_size_t p_frame_size_code[64] =
63 { 32 ,{64 ,69 ,96 } },
64 { 32 ,{64 ,70 ,96 } },
65 { 40 ,{80 ,87 ,120 } },
66 { 40 ,{80 ,88 ,120 } },
67 { 48 ,{96 ,104 ,144 } },
68 { 48 ,{96 ,105 ,144 } },
69 { 56 ,{112 ,121 ,168 } },
70 { 56 ,{112 ,122 ,168 } },
71 { 64 ,{128 ,139 ,192 } },
72 { 64 ,{128 ,140 ,192 } },
73 { 80 ,{160 ,174 ,240 } },
74 { 80 ,{160 ,175 ,240 } },
75 { 96 ,{192 ,208 ,288 } },
76 { 96 ,{192 ,209 ,288 } },
77 { 112 ,{224 ,243 ,336 } },
78 { 112 ,{224 ,244 ,336 } },
79 { 128 ,{256 ,278 ,384 } },
80 { 128 ,{256 ,279 ,384 } },
81 { 160 ,{320 ,348 ,480 } },
82 { 160 ,{320 ,349 ,480 } },
83 { 192 ,{384 ,417 ,576 } },
84 { 192 ,{384 ,418 ,576 } },
85 { 224 ,{448 ,487 ,672 } },
86 { 224 ,{448 ,488 ,672 } },
87 { 256 ,{512 ,557 ,768 } },
88 { 256 ,{512 ,558 ,768 } },
89 { 320 ,{640 ,696 ,960 } },
90 { 320 ,{640 ,697 ,960 } },
91 { 384 ,{768 ,835 ,1152 } },
92 { 384 ,{768 ,836 ,1152 } },
93 { 448 ,{896 ,975 ,1344 } },
94 { 448 ,{896 ,976 ,1344 } },
95 { 512 ,{1024 ,1114 ,1536 } },
96 { 512 ,{1024 ,1115 ,1536 } },
97 { 576 ,{1152 ,1253 ,1728 } },
98 { 576 ,{1152 ,1254 ,1728 } },
99 { 640 ,{1280 ,1393 ,1920 } },
100 { 640 ,{1280 ,1394 ,1920 } }
103 /*****************************************************************************
105 *****************************************************************************/
106 void _M( adec_getfunctions )( function_list_t * p_function_list )
108 p_function_list->functions.dec.pf_probe = decoder_Probe;
109 p_function_list->functions.dec.pf_run = decoder_Run;
112 /*****************************************************************************
113 * Build configuration tree.
114 *****************************************************************************/
119 SET_DESCRIPTION( _("SPDIF pass-through AC3 decoder") )
120 ADD_CAPABILITY( DECODER, 0 )
121 ADD_SHORTCUT( "ac3_spdif" )
122 ADD_SHORTCUT( "pass_through" )
123 ADD_SHORTCUT( "pass" )
126 MODULE_ACTIVATE_START
127 _M( adec_getfunctions )( &p_module->p_functions->dec );
130 MODULE_DEACTIVATE_START
131 MODULE_DEACTIVATE_STOP
133 /*****************************************************************************
134 * decoder_Probe: probe the decoder and return score
135 *****************************************************************************
136 * Tries to launch a decoder and return score so that the interface is able
138 *****************************************************************************/
139 static int decoder_Probe( u8 *pi_type )
141 return( *pi_type == AC3_AUDIO_ES ) ? 0 : -1;
145 /****************************************************************************
146 * decoder_Run: the whole thing
147 ****************************************************************************
148 * This function is called just after the thread is launched.
149 ****************************************************************************/
150 static int decoder_Run( decoder_config_t * p_config )
152 ac3_spdif_thread_t * p_spdif;
153 mtime_t i_frame_time;
155 /* PTS of the current frame */
156 mtime_t i_current_pts = 0;
159 /* Allocate the memory needed to store the thread's structure */
160 p_spdif = malloc( sizeof(ac3_spdif_thread_t) );
162 if( p_spdif == NULL )
164 intf_ErrMsg ( "spdif error: not enough memory "
165 "for spdif_CreateThread() to create the new thread");
166 DecoderError( p_config->p_decoder_fifo );
170 p_spdif->p_config = p_config;
172 if (InitThread( p_spdif ) )
174 intf_ErrMsg( "spdif error: could not initialize thread" );
175 DecoderError( p_config->p_decoder_fifo );
180 /* Compute the theorical duration of an ac3 frame */
181 i_frame_time = 1000000 * AC3_FRAME_SIZE /
182 p_spdif->ac3_info.i_sample_rate;
183 i_length = p_spdif->ac3_info.i_frame_size;
185 while( !p_spdif->p_fifo->b_die && !p_spdif->p_fifo->b_error )
187 p_spdif->p_ac3[0] = 0x0b;
188 p_spdif->p_ac3[1] = 0x77;
190 /* Handle the dates */
191 if( p_spdif->i_real_pts )
193 mtime_t i_delta = p_spdif->i_real_pts - i_current_pts -
195 if( i_delta > i_frame_time || i_delta < -i_frame_time )
197 intf_WarnMsg( 3, "spdif warning: date discontinuity (%d)",
200 i_current_pts = p_spdif->i_real_pts;
201 p_spdif->i_real_pts = 0;
205 i_current_pts += i_frame_time;
208 vlc_mutex_lock (&p_spdif->p_aout_fifo->data_lock);
210 p_spdif->p_aout_fifo->date[p_spdif->p_aout_fifo->i_end_frame] =
213 p_spdif->p_aout_fifo->i_end_frame =
214 (p_spdif->p_aout_fifo->i_end_frame + 1 ) & AOUT_FIFO_SIZE;
216 p_spdif->p_ac3 = ((u8*)(p_spdif->p_aout_fifo->buffer)) +
217 (p_spdif->p_aout_fifo->i_end_frame * i_length );
219 vlc_mutex_unlock (&p_spdif->p_aout_fifo->data_lock);
221 /* Find syncword again in case of stream discontinuity */
222 /* Here we have p_spdif->i_pts == 0
223 * Therefore a non-zero value after a call to GetBits() means the PES
226 while( !p_spdif->p_fifo->b_die
227 && !p_spdif->p_fifo->b_error
230 while( !p_spdif->p_fifo->b_die
231 && !p_spdif->p_fifo->b_error
232 && GetBits( &p_spdif->bit_stream, 8 ) != 0x0b );
233 p_spdif->i_real_pts = p_spdif->i_pts;
235 b_sync = ( ShowBits( &p_spdif->bit_stream, 8 ) == 0x77 );
237 RemoveBits( &p_spdif->bit_stream, 8 );
239 /* Read data from bitstream */
240 GetChunk( &p_spdif->bit_stream, p_spdif->p_ac3 + 2, i_length - 2 );
243 /* If b_error is set, the ac3 spdif thread enters the error loop */
244 if( p_spdif->p_fifo->b_error )
246 DecoderError( p_spdif->p_fifo );
249 /* End of the ac3 decoder thread */
250 EndThread( p_spdif );
255 /****************************************************************************
256 * InitThread: initialize thread data and create output fifo
257 ****************************************************************************/
258 static int InitThread( ac3_spdif_thread_t * p_spdif )
260 boolean_t b_sync = 0;
262 /* Temporary buffer to store first ac3 frame */
263 p_spdif->p_ac3 = malloc( SPDIF_FRAME_SIZE );
265 if( p_spdif->p_ac3 == NULL )
267 free( p_spdif->p_ac3 );
272 * Initialize the thread properties
274 p_spdif->p_fifo = p_spdif->p_config->p_decoder_fifo;
276 InitBitstream( &p_spdif->bit_stream, p_spdif->p_config->p_decoder_fifo,
277 BitstreamCallback, (void*)p_spdif );
280 while( !p_spdif->p_fifo->b_die
281 && !p_spdif->p_fifo->b_error
284 while( !p_spdif->p_fifo->b_die
285 && !p_spdif->p_fifo->b_error
286 && GetBits( &p_spdif->bit_stream, 8 ) != 0x0b );
287 p_spdif->i_real_pts = p_spdif->i_pts;
289 b_sync = ( ShowBits( &p_spdif->bit_stream, 8 ) == 0x77 );
292 if( p_spdif->p_fifo->b_die || p_spdif->p_fifo->b_error )
297 RemoveBits( &p_spdif->bit_stream, 8 );
299 /* Check stream properties */
300 if( ac3_parse_syncinfo( p_spdif ) < 0 )
302 intf_ErrMsg( "spdif error: stream not valid");
307 /* Check that we can handle the rate
308 * FIXME: we should check that we have the same rate for all fifos
309 * but all rates should be supported by the decoder (32, 44.1, 48) */
310 if( p_spdif->ac3_info.i_sample_rate != 48000 )
312 intf_ErrMsg( "spdif error: Only 48000 Hz streams tested"
313 "expect weird things !" );
316 /* The audio output need to be ready for an ac3 stream */
317 p_spdif->i_previous_format = config_GetIntVariable( "audio-format" );
318 config_PutIntVariable( "audio-format", 8 );
320 /* Creating the audio output fifo */
321 p_spdif->p_aout_fifo = aout_CreateFifo( AOUT_FIFO_SPDIF, 1,
322 p_spdif->ac3_info.i_sample_rate,
323 p_spdif->ac3_info.i_frame_size,
326 if( p_spdif->p_aout_fifo == NULL )
331 intf_WarnMsg( 3, "spdif: aout fifo #%d created",
332 p_spdif->p_aout_fifo->i_fifo );
334 /* Put read data into fifo */
335 memcpy( (u8*)(p_spdif->p_aout_fifo->buffer) +
336 (p_spdif->p_aout_fifo->i_end_frame *
337 p_spdif->ac3_info.i_frame_size ),
338 p_spdif->p_ac3, sizeof(sync_frame_t) );
339 free( p_spdif->p_ac3 );
340 p_spdif->p_ac3 = ((u8*)(p_spdif->p_aout_fifo->buffer) +
341 (p_spdif->p_aout_fifo->i_end_frame *
342 p_spdif->ac3_info.i_frame_size ));
344 GetChunk( &p_spdif->bit_stream, p_spdif->p_ac3 + sizeof(sync_frame_t),
345 p_spdif->ac3_info.i_frame_size - sizeof(sync_frame_t) );
350 /*****************************************************************************
351 * EndThread : ac3 spdif thread destruction
352 *****************************************************************************/
353 static void EndThread( ac3_spdif_thread_t * p_spdif )
355 /* If the audio output fifo was created, we destroy it */
356 if( p_spdif->p_aout_fifo != NULL )
358 aout_DestroyFifo( p_spdif->p_aout_fifo );
360 /* Make sure the output thread leaves the NextFrame() function */
361 vlc_mutex_lock( &(p_spdif->p_aout_fifo->data_lock ) );
362 vlc_cond_signal( &(p_spdif->p_aout_fifo->data_wait ) );
363 vlc_mutex_unlock( &(p_spdif->p_aout_fifo->data_lock ) );
367 /* restore previous setting for output format */
368 config_PutIntVariable( "audio-format", p_spdif->i_previous_format );
370 /* Destroy descriptor */
374 /*****************************************************************************
375 * BitstreamCallback: Import parameters from the new data/PES packet
376 *****************************************************************************
377 * This function is called by input's NextDataPacket.
378 *****************************************************************************/
379 static void BitstreamCallback( bit_stream_t * p_bit_stream,
380 boolean_t b_new_pes )
382 ac3_spdif_thread_t * p_spdif;
386 p_spdif = (ac3_spdif_thread_t *)p_bit_stream->p_callback_arg;
388 p_bit_stream->p_byte += 3;
391 p_bit_stream->p_decoder_fifo->p_first->i_pts;
392 p_bit_stream->p_decoder_fifo->p_first->i_pts = 0;
396 /****************************************************************************
397 * ac3_parse_syncinfo: parse ac3 sync info
398 ****************************************************************************/
399 int ac3_parse_syncinfo( ac3_spdif_thread_t *p_spdif )
401 int p_sample_rates[4] = { 48000, 44100, 32000, -1 };
402 int i_frame_rate_code;
403 int i_frame_size_code;
404 sync_frame_t * p_sync_frame;
406 /* Read sync frame */
407 GetChunk( &p_spdif->bit_stream, p_spdif->p_ac3 + 2,
408 sizeof(sync_frame_t) - 2 );
409 p_sync_frame = (sync_frame_t*)p_spdif->p_ac3;
411 /* Compute frame rate */
412 i_frame_rate_code = (p_sync_frame->syncinfo.code >> 6) & 0x03;
413 p_spdif->ac3_info.i_sample_rate = p_sample_rates[i_frame_rate_code];
414 if( p_spdif->ac3_info.i_sample_rate == -1 )
419 /* Compute frame size */
420 i_frame_size_code = p_sync_frame->syncinfo.code & 0x3f;
421 p_spdif->ac3_info.i_frame_size = 2 *
422 p_frame_size_code[i_frame_size_code].i_frame_size[i_frame_rate_code];
423 p_spdif->ac3_info.i_bit_rate =
424 p_frame_size_code[i_frame_size_code].i_bit_rate;
426 if( ( ( p_sync_frame->bsi.bsidmod >> 3 ) & 0x1f ) != 0x08 )
431 p_spdif->ac3_info.i_bs_mod = p_sync_frame->bsi.bsidmod & 0x7;