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.1 2001/11/13 12:09:17 henri 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 #define MODULE_NAME ac3_spdif
27 #include "modules_inner.h"
29 /*****************************************************************************
31 *****************************************************************************/
36 #include <string.h> /* memcpy() */
47 #include "intf_msg.h" /* intf_DbgMsg(), intf_ErrMsg() */
49 #include "audio_output.h"
52 #include "modules_export.h"
54 #include "stream_control.h"
55 #include "input_ext-dec.h"
57 #include "ac3_spdif.h"
58 #include "ac3_iec958.h"
62 /****************************************************************************
64 ****************************************************************************/
65 static int ac3_spdif_Probe ( probedata_t * );
66 static int ac3_spdif_Run ( decoder_config_t * );
67 static int ac3_spdif_Init ( ac3_spdif_thread_t * );
68 static void ac3_spdif_ErrorThread ( ac3_spdif_thread_t * );
69 static void ac3_spdif_EndThread ( ac3_spdif_thread_t * );
70 static void BitstreamCallback( bit_stream_t *, boolean_t );
72 /*****************************************************************************
74 *****************************************************************************/
75 void _M( adec_getfunctions )( function_list_t * p_function_list )
77 p_function_list->pf_probe = ac3_spdif_Probe;
78 p_function_list->functions.dec.pf_RunThread = ac3_spdif_Run;
81 /*****************************************************************************
82 * Build configuration tree.
83 *****************************************************************************/
85 ADD_WINDOW( "Configuration for ac3 spdif decoder module" )
86 ADD_COMMENT( "Nothing to configure" )
90 p_module->i_capabilities = MODULE_CAPABILITY_DEC;
91 p_module->psz_longname = "Ac3 SPDIF decoder for AC3 pass-through";
95 _M( adec_getfunctions )( &p_module->p_functions->dec );
98 MODULE_DEACTIVATE_START
99 MODULE_DEACTIVATE_STOP
101 /*****************************************************************************
102 * ac3_spdif_Probe: probe the decoder and return score
103 *****************************************************************************
104 * Tries to launch a decoder and return score so that the interface is able
106 *****************************************************************************/
107 static int ac3_spdif_Probe( probedata_t *p_data )
109 if( main_GetIntVariable( AOUT_SPDIF_VAR, 0 ) &&
110 p_data->i_type == AC3_AUDIO_ES )
117 /****************************************************************************
118 * ac3_spdif_Run: the whole thing
119 ****************************************************************************
120 * This function is called just after the thread is launched.
121 ****************************************************************************/
122 static int ac3_spdif_Run( decoder_config_t * p_config )
124 ac3_spdif_thread_t * p_spdif;
125 mtime_t i_frame_time;
127 /* PTS of the current frame */
128 mtime_t i_current_pts = 0;
130 intf_DbgMsg( "spdif debug: ac3_spdif thread created, initializing." );
132 /* Allocate the memory needed to store the thread's structure */
133 p_spdif = malloc( sizeof(ac3_spdif_thread_t) );
135 if( p_spdif == NULL )
137 intf_ErrMsg ( "spdif error: not enough memory "
138 "for spdif_CreateThread() to create the new thread");
142 p_spdif->p_config = p_config;
144 if (ac3_spdif_Init( p_spdif ) )
146 intf_ErrMsg( "spdif error: could not initialize thread" );
150 /* Compute the theorical duration of an ac3 frame */
151 i_frame_time = 1000000 * AC3_FRAME_SIZE /
152 p_spdif->ac3_info.i_sample_rate;
154 intf_DbgMsg( "spdif debug: ac3_spdif thread (%p) initialized", p_spdif );
156 while( !p_spdif->p_fifo->b_die && !p_spdif->p_fifo->b_error )
158 /* Handle the dates */
159 if( p_spdif->i_real_pts )
161 if(i_current_pts + i_frame_time != p_spdif->i_real_pts)
163 intf_WarnMsg( 2, "spdif warning: date discontinuity (%d)",
164 p_spdif->i_real_pts - i_current_pts -
167 i_current_pts = p_spdif->i_real_pts;
168 p_spdif->i_real_pts = 0;
172 i_current_pts += i_frame_time;
175 /* if we're late here the output won't have to play the frame */
176 if( i_current_pts > mdate() )
178 p_spdif->p_aout_fifo->date[p_spdif->p_aout_fifo->l_end_frame] =
181 /* Write in the first free packet of aout fifo */
182 p_spdif->p_iec = ((u8*)(p_spdif->p_aout_fifo->buffer) +
183 (p_spdif->p_aout_fifo->l_end_frame * SPDIF_FRAME_SIZE ));
185 /* Build burst to be sent to hardware decoder */
186 ac3_iec958_build_burst( p_spdif );
188 vlc_mutex_lock (&p_spdif->p_aout_fifo->data_lock);
189 p_spdif->p_aout_fifo->l_end_frame =
190 (p_spdif->p_aout_fifo->l_end_frame + 1 ) & AOUT_FIFO_SIZE;
191 vlc_mutex_unlock (&p_spdif->p_aout_fifo->data_lock);
194 /* Find syncword again in case of stream discontinuity */
195 /* Here we have p_spdif->i_pts == 0
196 * Therefore a non-zero value after a call to GetBits() means the PES
201 while( GetBits( &p_spdif->bit_stream, 8 ) != 0x0b );
202 p_spdif->i_real_pts = p_spdif->i_pts;
204 b_sync = ( ShowBits( &p_spdif->bit_stream, 8 ) == 0x77 );
206 RemoveBits( &p_spdif->bit_stream, 8 );
208 /* Read data from bitstream */
209 GetChunk( &p_spdif->bit_stream, p_spdif->p_ac3 + 2,
210 p_spdif->ac3_info.i_frame_size - 2 );
213 /* If b_error is set, the ac3 spdif thread enters the error loop */
214 if( p_spdif->p_fifo->b_error )
216 ac3_spdif_ErrorThread( p_spdif );
219 /* End of the ac3 decoder thread */
220 ac3_spdif_EndThread( p_spdif );
225 /****************************************************************************
226 * ac3_spdif_Init: initialize thread data and create output fifo
227 ****************************************************************************/
228 static int ac3_spdif_Init( ac3_spdif_thread_t * p_spdif )
230 boolean_t b_sync = 0;
232 /* Temporary buffer to store ac3 frames to be transformed */
233 p_spdif->p_ac3 = malloc( SPDIF_FRAME_SIZE );
235 if( p_spdif->p_ac3 == NULL )
237 free( p_spdif->p_ac3 );
242 * Initialize the thread properties
244 p_spdif->p_fifo = p_spdif->p_config->p_decoder_fifo;
246 p_spdif->p_config->pf_init_bit_stream(
247 &p_spdif->bit_stream,
248 p_spdif->p_config->p_decoder_fifo,
249 BitstreamCallback, (void*)p_spdif );
251 /* Creating the audio output fifo */
252 p_spdif->p_aout_fifo = aout_CreateFifo( AOUT_ADEC_SPDIF_FIFO, 1, 48000, 0,
253 SPDIF_FRAME_SIZE, NULL );
255 if( p_spdif->p_aout_fifo == NULL )
260 intf_WarnMsg( 3, "spdif: aout fifo #%d created",
261 p_spdif->p_aout_fifo->i_fifo );
264 p_spdif->p_ac3[0] = 0x0b;
265 p_spdif->p_ac3[1] = 0x77;
270 while( GetBits( &p_spdif->bit_stream, 8 ) != 0x0b );
271 p_spdif->i_real_pts = p_spdif->i_pts;
273 b_sync = ( ShowBits( &p_spdif->bit_stream, 8 ) == 0x77 );
275 RemoveBits( &p_spdif->bit_stream, 8 );
277 /* Check stream properties */
278 if( ac3_iec958_parse_syncinfo( p_spdif ) < 0 )
280 intf_ErrMsg( "spdif error: stream not valid");
282 aout_DestroyFifo( p_spdif->p_aout_fifo );
286 /* Check that we can handle the rate
287 * FIXME: we should check that we have the same rate for all fifos
288 * but all rates should be supported by the decoder (32, 44.1, 48) */
289 if( p_spdif->ac3_info.i_sample_rate != 48000 )
291 intf_ErrMsg( "spdif error: Only 48000 Hz streams supported");
293 aout_DestroyFifo( p_spdif->p_aout_fifo );
296 p_spdif->p_aout_fifo->l_rate = p_spdif->ac3_info.i_sample_rate;
298 GetChunk( &p_spdif->bit_stream, p_spdif->p_ac3 + sizeof(sync_frame_t),
299 p_spdif->ac3_info.i_frame_size - sizeof(sync_frame_t) );
305 /*****************************************************************************
306 * ac3_spdif_ErrorThread : ac3 spdif's RunThread() error loop
307 *****************************************************************************/
308 static void ac3_spdif_ErrorThread( ac3_spdif_thread_t * p_spdif )
310 /* We take the lock, because we are going to read/write the start/end
311 * indexes of the decoder fifo */
312 vlc_mutex_lock (&p_spdif->p_fifo->data_lock);
314 /* Wait until a `die' order is sent */
315 while( !p_spdif->p_fifo->b_die )
317 /* Trash all received PES packets */
318 while( !DECODER_FIFO_ISEMPTY( *p_spdif->p_fifo ) )
320 p_spdif->p_fifo->pf_delete_pes(p_spdif->p_fifo->p_packets_mgt,
321 DECODER_FIFO_START( *p_spdif->p_fifo ) );
322 DECODER_FIFO_INCSTART( *p_spdif->p_fifo );
325 /* Waiting for the input thread to put new PES packets in the fifo */
326 vlc_cond_wait( &p_spdif->p_fifo->data_wait,
327 &p_spdif->p_fifo->data_lock );
330 /* We can release the lock before leaving */
331 vlc_mutex_unlock( &p_spdif->p_fifo->data_lock );
334 /*****************************************************************************
335 * ac3_spdif_EndThread : ac3 spdif thread destruction
336 *****************************************************************************/
337 static void ac3_spdif_EndThread( ac3_spdif_thread_t * p_spdif )
339 intf_DbgMsg( "spdif debug: destroying thread %p", p_spdif );
341 /* If the audio output fifo was created, we destroy it */
342 if( p_spdif->p_aout_fifo != NULL )
344 aout_DestroyFifo( p_spdif->p_aout_fifo );
346 /* Make sure the output thread leaves the NextFrame() function */
347 vlc_mutex_lock( &(p_spdif->p_aout_fifo->data_lock ) );
348 vlc_cond_signal( &(p_spdif->p_aout_fifo->data_wait ) );
349 vlc_mutex_unlock( &(p_spdif->p_aout_fifo->data_lock ) );
353 /* Destroy descriptor */
354 free( p_spdif->p_config );
355 free( p_spdif->p_ac3 );
358 intf_DbgMsg ("spdif debug: thread %p destroyed", p_spdif );
361 /*****************************************************************************
362 * BitstreamCallback: Import parameters from the new data/PES packet
363 *****************************************************************************
364 * This function is called by input's NextDataPacket.
365 *****************************************************************************/
366 static void BitstreamCallback ( bit_stream_t * p_bit_stream,
369 ac3_spdif_thread_t * p_spdif;
373 p_spdif = (ac3_spdif_thread_t *)p_bit_stream->p_callback_arg;
375 p_bit_stream->p_byte += 3;
378 DECODER_FIFO_START( *p_bit_stream->p_decoder_fifo )->i_pts;
379 DECODER_FIFO_START( *p_bit_stream->p_decoder_fifo )->i_pts = 0;