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.15 2002/02/24 20:51:09 gbazin 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"
46 #include "ac3_iec958.h"
50 /****************************************************************************
52 ****************************************************************************/
53 static int decoder_Probe ( u8 * );
54 static int decoder_Run ( decoder_config_t * );
55 static int InitThread ( ac3_spdif_thread_t * );
56 static void EndThread ( ac3_spdif_thread_t * );
57 static void BitstreamCallback ( bit_stream_t *, boolean_t );
59 /*****************************************************************************
61 *****************************************************************************/
62 void _M( adec_getfunctions )( function_list_t * p_function_list )
64 p_function_list->functions.dec.pf_probe = decoder_Probe;
65 p_function_list->functions.dec.pf_run = decoder_Run;
68 /*****************************************************************************
69 * Build configuration tree.
70 *****************************************************************************/
75 SET_DESCRIPTION( "SPDIF pass-through AC3 decoder" )
76 ADD_CAPABILITY( DECODER, 100 )
80 _M( adec_getfunctions )( &p_module->p_functions->dec );
83 MODULE_DEACTIVATE_START
84 MODULE_DEACTIVATE_STOP
86 /*****************************************************************************
87 * decoder_Probe: probe the decoder and return score
88 *****************************************************************************
89 * Tries to launch a decoder and return score so that the interface is able
91 *****************************************************************************/
92 static int decoder_Probe( u8 *pi_type )
94 return( ( config_GetIntVariable( AOUT_SPDIF_VAR )
95 && *pi_type == AC3_AUDIO_ES ) ? 0 : -1 );
99 /****************************************************************************
100 * decoder_Run: the whole thing
101 ****************************************************************************
102 * This function is called just after the thread is launched.
103 ****************************************************************************/
104 static int decoder_Run( decoder_config_t * p_config )
106 ac3_spdif_thread_t * p_spdif;
107 mtime_t i_frame_time;
109 /* PTS of the current frame */
110 mtime_t i_current_pts = 0;
112 /* Allocate the memory needed to store the thread's structure */
113 p_spdif = malloc( sizeof(ac3_spdif_thread_t) );
115 if( p_spdif == NULL )
117 intf_ErrMsg ( "spdif error: not enough memory "
118 "for spdif_CreateThread() to create the new thread");
119 DecoderError( p_config->p_decoder_fifo );
123 p_spdif->p_config = p_config;
125 if (InitThread( p_spdif ) )
127 intf_ErrMsg( "spdif error: could not initialize thread" );
128 DecoderError( p_config->p_decoder_fifo );
133 /* Compute the theorical duration of an ac3 frame */
134 i_frame_time = 1000000 * AC3_FRAME_SIZE /
135 p_spdif->ac3_info.i_sample_rate;
137 while( !p_spdif->p_fifo->b_die && !p_spdif->p_fifo->b_error )
139 /* Handle the dates */
140 if( p_spdif->i_real_pts )
142 mtime_t i_delta = p_spdif->i_real_pts - i_current_pts -
144 if( i_delta > i_frame_time || i_delta < -i_frame_time )
146 intf_WarnMsg( 3, "spdif warning: date discontinuity (%d)",
149 i_current_pts = p_spdif->i_real_pts;
150 p_spdif->i_real_pts = 0;
154 i_current_pts += i_frame_time;
157 /* if we're late here the output won't have to play the frame */
158 if( i_current_pts > mdate() )
160 p_spdif->p_aout_fifo->date[p_spdif->p_aout_fifo->l_end_frame] =
163 /* Write in the first free packet of aout fifo */
164 p_spdif->p_iec = ((u8*)(p_spdif->p_aout_fifo->buffer) +
165 (p_spdif->p_aout_fifo->l_end_frame * SPDIF_FRAME_SIZE ));
167 /* Build burst to be sent to hardware decoder */
168 ac3_iec958_build_burst( p_spdif );
170 vlc_mutex_lock (&p_spdif->p_aout_fifo->data_lock);
171 p_spdif->p_aout_fifo->l_end_frame =
172 (p_spdif->p_aout_fifo->l_end_frame + 1 ) & AOUT_FIFO_SIZE;
173 vlc_mutex_unlock (&p_spdif->p_aout_fifo->data_lock);
176 /* Find syncword again in case of stream discontinuity */
177 /* Here we have p_spdif->i_pts == 0
178 * Therefore a non-zero value after a call to GetBits() means the PES
183 while( GetBits( &p_spdif->bit_stream, 8 ) != 0x0b );
184 p_spdif->i_real_pts = p_spdif->i_pts;
186 b_sync = ( ShowBits( &p_spdif->bit_stream, 8 ) == 0x77 );
188 RemoveBits( &p_spdif->bit_stream, 8 );
190 /* Read data from bitstream */
191 GetChunk( &p_spdif->bit_stream, p_spdif->p_ac3 + 2,
192 p_spdif->ac3_info.i_frame_size - 2 );
195 /* If b_error is set, the ac3 spdif thread enters the error loop */
196 if( p_spdif->p_fifo->b_error )
198 DecoderError( p_spdif->p_fifo );
201 /* End of the ac3 decoder thread */
202 EndThread( p_spdif );
207 /****************************************************************************
208 * InitThread: initialize thread data and create output fifo
209 ****************************************************************************/
210 static int InitThread( ac3_spdif_thread_t * p_spdif )
212 boolean_t b_sync = 0;
214 /* Temporary buffer to store ac3 frames to be transformed */
215 p_spdif->p_ac3 = malloc( SPDIF_FRAME_SIZE );
217 if( p_spdif->p_ac3 == NULL )
219 free( p_spdif->p_ac3 );
224 * Initialize the thread properties
226 p_spdif->p_fifo = p_spdif->p_config->p_decoder_fifo;
228 InitBitstream( &p_spdif->bit_stream, p_spdif->p_config->p_decoder_fifo,
229 BitstreamCallback, (void*)p_spdif );
232 p_spdif->p_ac3[0] = 0x0b;
233 p_spdif->p_ac3[1] = 0x77;
238 while( GetBits( &p_spdif->bit_stream, 8 ) != 0x0b );
239 p_spdif->i_real_pts = p_spdif->i_pts;
241 b_sync = ( ShowBits( &p_spdif->bit_stream, 8 ) == 0x77 );
243 RemoveBits( &p_spdif->bit_stream, 8 );
245 /* Check stream properties */
246 if( ac3_iec958_parse_syncinfo( p_spdif ) < 0 )
248 intf_ErrMsg( "spdif error: stream not valid");
250 aout_DestroyFifo( p_spdif->p_aout_fifo );
254 /* Check that we can handle the rate
255 * FIXME: we should check that we have the same rate for all fifos
256 * but all rates should be supported by the decoder (32, 44.1, 48) */
257 if( p_spdif->ac3_info.i_sample_rate != 48000 )
259 intf_ErrMsg( "spdif error: Only 48000 Hz streams tested"
260 "expect weird things !" );
261 //intf_ErrMsg( "spdif error: Only 48000 Hz streams supported");
263 //aout_DestroyFifo( p_spdif->p_aout_fifo );
267 /* Creating the audio output fifo */
268 p_spdif->p_aout_fifo = aout_CreateFifo( AOUT_ADEC_SPDIF_FIFO, 1,
269 p_spdif->ac3_info.i_sample_rate,
270 0, SPDIF_FRAME_SIZE, NULL );
272 if( p_spdif->p_aout_fifo == NULL )
277 intf_WarnMsg( 3, "spdif: aout fifo #%d created",
278 p_spdif->p_aout_fifo->i_fifo );
280 GetChunk( &p_spdif->bit_stream, p_spdif->p_ac3 + sizeof(sync_frame_t),
281 p_spdif->ac3_info.i_frame_size - sizeof(sync_frame_t) );
286 /*****************************************************************************
287 * EndThread : ac3 spdif thread destruction
288 *****************************************************************************/
289 static void EndThread( ac3_spdif_thread_t * p_spdif )
291 /* If the audio output fifo was created, we destroy it */
292 if( p_spdif->p_aout_fifo != NULL )
294 aout_DestroyFifo( p_spdif->p_aout_fifo );
296 /* Make sure the output thread leaves the NextFrame() function */
297 vlc_mutex_lock( &(p_spdif->p_aout_fifo->data_lock ) );
298 vlc_cond_signal( &(p_spdif->p_aout_fifo->data_wait ) );
299 vlc_mutex_unlock( &(p_spdif->p_aout_fifo->data_lock ) );
303 /* Destroy descriptor */
304 free( p_spdif->p_ac3 );
308 /*****************************************************************************
309 * BitstreamCallback: Import parameters from the new data/PES packet
310 *****************************************************************************
311 * This function is called by input's NextDataPacket.
312 *****************************************************************************/
313 static void BitstreamCallback ( bit_stream_t * p_bit_stream,
316 ac3_spdif_thread_t * p_spdif;
320 p_spdif = (ac3_spdif_thread_t *)p_bit_stream->p_callback_arg;
322 p_bit_stream->p_byte += 3;
325 p_bit_stream->p_decoder_fifo->p_first->i_pts;
326 p_bit_stream->p_decoder_fifo->p_first->i_pts = 0;