]> git.sesse.net Git - vlc/blob - plugins/ac3_spdif/ac3_spdif.c
* ALL: got rid of p_object->p_this which is now useless.
[vlc] / plugins / ac3_spdif / ac3_spdif.c
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.28 2002/06/01 18:04:48 sam Exp $
6  *
7  * Authors: Stéphane Borel <stef@via.ecp.fr>
8  *          Juha Yrjola <jyrjola@cc.hut.fi>
9  *          German Gomez Garcia <german@piraos.com>
10  *
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.
15  * 
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.
20  *
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  *****************************************************************************/
25
26 /*****************************************************************************
27  * Preamble
28  *****************************************************************************/
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>                                              /* memcpy() */
32 #include <fcntl.h>
33
34 #include <vlc/vlc.h>
35 #include <vlc/decoder.h>
36 #include <vlc/aout.h>
37
38 #ifdef HAVE_UNISTD_H
39 #   include <unistd.h>
40 #endif
41
42 #include "ac3_spdif.h"
43
44 /****************************************************************************
45  * Local Prototypes
46  ****************************************************************************/
47 static int  decoder_Probe     ( u8 * );
48 static int  decoder_Run       ( decoder_fifo_t * );
49 static int  InitThread        ( ac3_spdif_thread_t * );
50 static void EndThread         ( ac3_spdif_thread_t * );
51 static void BitstreamCallback ( bit_stream_t *, vlc_bool_t );
52
53 int     ac3_parse_syncinfo   ( struct ac3_spdif_thread_s * );
54
55 /****************************************************************************
56  * Local structures and tables
57  ****************************************************************************/
58 static const frame_size_t p_frame_size_code[64] =
59 {
60         { 32  ,{64   ,69   ,96   } },
61         { 32  ,{64   ,70   ,96   } },
62         { 40  ,{80   ,87   ,120  } },
63         { 40  ,{80   ,88   ,120  } },
64         { 48  ,{96   ,104  ,144  } },
65         { 48  ,{96   ,105  ,144  } },
66         { 56  ,{112  ,121  ,168  } },
67         { 56  ,{112  ,122  ,168  } },
68         { 64  ,{128  ,139  ,192  } },
69         { 64  ,{128  ,140  ,192  } },
70         { 80  ,{160  ,174  ,240  } },
71         { 80  ,{160  ,175  ,240  } },
72         { 96  ,{192  ,208  ,288  } },
73         { 96  ,{192  ,209  ,288  } },
74         { 112 ,{224  ,243  ,336  } },
75         { 112 ,{224  ,244  ,336  } },
76         { 128 ,{256  ,278  ,384  } },
77         { 128 ,{256  ,279  ,384  } },
78         { 160 ,{320  ,348  ,480  } },
79         { 160 ,{320  ,349  ,480  } },
80         { 192 ,{384  ,417  ,576  } },
81         { 192 ,{384  ,418  ,576  } },
82         { 224 ,{448  ,487  ,672  } },
83         { 224 ,{448  ,488  ,672  } },
84         { 256 ,{512  ,557  ,768  } },
85         { 256 ,{512  ,558  ,768  } },
86         { 320 ,{640  ,696  ,960  } },
87         { 320 ,{640  ,697  ,960  } },
88         { 384 ,{768  ,835  ,1152 } },
89         { 384 ,{768  ,836  ,1152 } },
90         { 448 ,{896  ,975  ,1344 } },
91         { 448 ,{896  ,976  ,1344 } },
92         { 512 ,{1024 ,1114 ,1536 } },
93         { 512 ,{1024 ,1115 ,1536 } },
94         { 576 ,{1152 ,1253 ,1728 } },
95         { 576 ,{1152 ,1254 ,1728 } },
96         { 640 ,{1280 ,1393 ,1920 } },
97         { 640 ,{1280 ,1394 ,1920 } }
98 };
99
100 /*****************************************************************************
101  * Capabilities
102  *****************************************************************************/
103 void _M( adec_getfunctions )( function_list_t * p_function_list )
104 {
105     p_function_list->functions.dec.pf_probe = decoder_Probe;
106     p_function_list->functions.dec.pf_run   = decoder_Run;
107 }
108
109 /*****************************************************************************
110  * Build configuration tree.
111  *****************************************************************************/
112 MODULE_CONFIG_START
113 MODULE_CONFIG_STOP
114
115 MODULE_INIT_START
116     SET_DESCRIPTION( _("SPDIF pass-through AC3 decoder") )
117     ADD_CAPABILITY( DECODER, 0 )
118     ADD_SHORTCUT( "pass_through" )
119     ADD_SHORTCUT( "pass" )
120 MODULE_INIT_STOP
121
122 MODULE_ACTIVATE_START
123     _M( adec_getfunctions )( &p_module->p_functions->dec );
124 MODULE_ACTIVATE_STOP
125
126 MODULE_DEACTIVATE_START
127 MODULE_DEACTIVATE_STOP
128
129 /*****************************************************************************
130  * decoder_Probe: probe the decoder and return score
131  *****************************************************************************
132  * Tries to launch a decoder and return score so that the interface is able 
133  * to chose.
134  *****************************************************************************/
135 static int decoder_Probe( u8 *pi_type )
136 {
137     return( *pi_type == AC3_AUDIO_ES ) ? 0 : -1;
138 }
139
140
141 /****************************************************************************
142  * decoder_Run: the whole thing
143  ****************************************************************************
144  * This function is called just after the thread is launched.
145  ****************************************************************************/
146 static int decoder_Run( decoder_fifo_t * p_fifo )
147 {
148     ac3_spdif_thread_t *   p_spdif;
149     mtime_t     i_frame_time;
150     vlc_bool_t  b_sync;
151     /* PTS of the current frame */
152     mtime_t     i_current_pts = 0;
153     u16         i_length;
154     
155     /* Allocate the memory needed to store the thread's structure */
156     p_spdif = malloc( sizeof(ac3_spdif_thread_t) );
157
158     if( p_spdif == NULL )
159     {
160         msg_Err( p_fifo, "out of memory" );
161         DecoderError( p_fifo );
162         return( -1 );
163     }
164   
165     p_spdif->p_fifo = p_fifo; 
166     
167     if (InitThread( p_spdif ) )
168     {
169         msg_Err( p_fifo, "could not initialize thread" );
170         DecoderError( p_fifo );
171         free( p_spdif );
172         return( -1 );
173     }
174
175     /* Compute the theorical duration of an ac3 frame */
176     i_frame_time = 1000000 * AC3_FRAME_SIZE /
177                              p_spdif->ac3_info.i_sample_rate;
178     i_length = p_spdif->ac3_info.i_frame_size;
179     
180     while( !p_spdif->p_fifo->b_die && !p_spdif->p_fifo->b_error )
181     {
182         p_spdif->p_ac3[0] = 0x0b;
183         p_spdif->p_ac3[1] = 0x77;
184         
185          /* Handle the dates */
186         if( p_spdif->i_real_pts )
187         {
188             mtime_t     i_delta = p_spdif->i_real_pts - i_current_pts -
189                                   i_frame_time;
190             if( i_delta > i_frame_time || i_delta < -i_frame_time )
191             {
192                 msg_Warn( p_fifo,
193                           "date discontinuity (%d)", i_delta );
194             }
195             i_current_pts = p_spdif->i_real_pts;
196             p_spdif->i_real_pts = 0;
197         }
198         else
199         {
200             i_current_pts += i_frame_time;
201         }
202         
203         vlc_mutex_lock (&p_spdif->p_aout_fifo->data_lock);
204         
205         p_spdif->p_aout_fifo->date[p_spdif->p_aout_fifo->i_end_frame] =
206             i_current_pts;
207
208         p_spdif->p_aout_fifo->i_end_frame = 
209                 (p_spdif->p_aout_fifo->i_end_frame + 1 ) & AOUT_FIFO_SIZE;
210         
211         p_spdif->p_ac3 = ((u8*)(p_spdif->p_aout_fifo->buffer)) +
212                      (p_spdif->p_aout_fifo->i_end_frame * i_length );
213         
214         vlc_mutex_unlock (&p_spdif->p_aout_fifo->data_lock);
215
216         /* Find syncword again in case of stream discontinuity */
217         /* Here we have p_spdif->i_pts == 0
218          * Therefore a non-zero value after a call to GetBits() means the PES
219          * has changed. */
220         b_sync = 0;
221         while( !p_spdif->p_fifo->b_die
222             && !p_spdif->p_fifo->b_error
223             && !b_sync )
224         {
225             while( !p_spdif->p_fifo->b_die
226                 && !p_spdif->p_fifo->b_error
227                 && GetBits( &p_spdif->bit_stream, 8 ) != 0x0b );
228             p_spdif->i_real_pts = p_spdif->i_pts;
229             p_spdif->i_pts = 0;
230             b_sync = ( ShowBits( &p_spdif->bit_stream, 8 ) == 0x77 );
231         }
232         RemoveBits( &p_spdif->bit_stream, 8 );
233
234         /* Read data from bitstream */
235         GetChunk( &p_spdif->bit_stream, p_spdif->p_ac3 + 2, i_length - 2 );
236     }
237
238     /* If b_error is set, the ac3 spdif thread enters the error loop */
239     if( p_spdif->p_fifo->b_error )
240     {
241         DecoderError( p_spdif->p_fifo );
242     }
243
244     /* End of the ac3 decoder thread */
245     EndThread( p_spdif );
246     
247     return( 0 );
248 }
249
250 /****************************************************************************
251  * InitThread: initialize thread data and create output fifo
252  ****************************************************************************/
253 static int InitThread( ac3_spdif_thread_t * p_spdif )
254 {
255     vlc_bool_t b_sync = 0;
256
257     /* Temporary buffer to store first ac3 frame */
258     p_spdif->p_ac3 = malloc( SPDIF_FRAME_SIZE );
259
260     if( p_spdif->p_ac3 == NULL )
261     {
262         free( p_spdif->p_ac3 );
263         return( -1 );
264     }
265
266     /*
267      * Initialize the thread properties
268      */
269     p_spdif->p_fifo = p_spdif->p_fifo;
270
271     InitBitstream( &p_spdif->bit_stream, p_spdif->p_fifo,
272                    BitstreamCallback, (void*)p_spdif );
273
274     /* Find syncword */
275     while( !p_spdif->p_fifo->b_die
276         && !p_spdif->p_fifo->b_error
277         && !b_sync )
278     {
279         while( !p_spdif->p_fifo->b_die
280             && !p_spdif->p_fifo->b_error
281             && GetBits( &p_spdif->bit_stream, 8 ) != 0x0b );
282         p_spdif->i_real_pts = p_spdif->i_pts;
283         p_spdif->i_pts = 0;
284         b_sync = ( ShowBits( &p_spdif->bit_stream, 8 ) == 0x77 );
285     }
286
287     if( p_spdif->p_fifo->b_die || p_spdif->p_fifo->b_error )
288     {
289         return -1;
290     }
291
292     RemoveBits( &p_spdif->bit_stream, 8 );
293
294     /* Check stream properties */
295     if( ac3_parse_syncinfo( p_spdif ) < 0 )
296     {
297         msg_Err( p_spdif->p_fifo, "stream not valid" );
298
299         return( -1 );
300     }
301
302     /* Check that we can handle the rate 
303      * FIXME: we should check that we have the same rate for all fifos 
304      * but all rates should be supported by the decoder (32, 44.1, 48) */
305     if( p_spdif->ac3_info.i_sample_rate != 48000 )
306     {
307         msg_Err( p_spdif->p_fifo,
308                  "only 48000 Hz streams tested, expect weird things!" );
309     }
310
311     /* The audio output need to be ready for an ac3 stream */
312     p_spdif->i_previous_format = config_GetInt( p_spdif->p_fifo,
313                                                 "audio-format" );
314     config_PutInt( p_spdif->p_fifo, "audio-format", 8 );
315     
316     /* Creating the audio output fifo */
317     p_spdif->p_aout_fifo =
318                     aout_CreateFifo( p_spdif->p_fifo, AOUT_FIFO_SPDIF,
319                                      1, p_spdif->ac3_info.i_sample_rate,
320                                      p_spdif->ac3_info.i_frame_size, NULL );
321
322     if( p_spdif->p_aout_fifo == NULL )
323     {
324         return( -1 );
325     }
326
327     msg_Dbg( p_spdif->p_fifo, "aout fifo #%d created",
328                               p_spdif->p_aout_fifo->i_fifo );
329
330     /* Put read data into fifo */
331     memcpy( (u8*)(p_spdif->p_aout_fifo->buffer) +
332                  (p_spdif->p_aout_fifo->i_end_frame *
333                    p_spdif->ac3_info.i_frame_size ),
334             p_spdif->p_ac3, sizeof(sync_frame_t) );
335     free( p_spdif->p_ac3 );
336     p_spdif->p_ac3 = ((u8*)(p_spdif->p_aout_fifo->buffer) +
337                            (p_spdif->p_aout_fifo->i_end_frame *
338                             p_spdif->ac3_info.i_frame_size ));
339
340     GetChunk( &p_spdif->bit_stream, p_spdif->p_ac3 + sizeof(sync_frame_t),
341         p_spdif->ac3_info.i_frame_size - sizeof(sync_frame_t) );
342
343     return( 0 );
344 }
345
346 /*****************************************************************************
347  * EndThread : ac3 spdif thread destruction
348  *****************************************************************************/
349 static void EndThread( ac3_spdif_thread_t * p_spdif )
350 {
351     /* If the audio output fifo was created, we destroy it */
352     if( p_spdif->p_aout_fifo != NULL )
353     {
354         aout_DestroyFifo( p_spdif->p_aout_fifo );
355
356         /* Make sure the output thread leaves the NextFrame() function */
357         vlc_mutex_lock( &(p_spdif->p_aout_fifo->data_lock ) );
358         vlc_cond_signal( &(p_spdif->p_aout_fifo->data_wait ) );
359         vlc_mutex_unlock( &(p_spdif->p_aout_fifo->data_lock ) );
360         
361     }
362
363     /* restore previous setting for output format */
364     config_PutInt( p_spdif->p_fifo, "audio-format",
365                                     p_spdif->i_previous_format );
366
367     /* Destroy descriptor */
368     free( p_spdif );
369 }
370
371 /*****************************************************************************
372  * BitstreamCallback: Import parameters from the new data/PES packet
373  *****************************************************************************
374  * This function is called by input's NextDataPacket.
375  *****************************************************************************/
376 static void BitstreamCallback( bit_stream_t * p_bit_stream,
377                                vlc_bool_t b_new_pes )
378 {
379     ac3_spdif_thread_t *    p_spdif;
380
381     if( b_new_pes )
382     {
383         p_spdif = (ac3_spdif_thread_t *)p_bit_stream->p_callback_arg;
384
385 /*        p_bit_stream->p_byte += 3; */
386
387         p_spdif->i_pts =
388             p_bit_stream->p_decoder_fifo->p_first->i_pts;
389         p_bit_stream->p_decoder_fifo->p_first->i_pts = 0;
390     }
391 }
392
393 /****************************************************************************
394  * ac3_parse_syncinfo: parse ac3 sync info
395  ****************************************************************************/
396 int ac3_parse_syncinfo( ac3_spdif_thread_t *p_spdif )
397 {
398     int             p_sample_rates[4] = { 48000, 44100, 32000, -1 };
399     int             i_frame_rate_code;
400     int             i_frame_size_code;
401     sync_frame_t *  p_sync_frame;
402
403     /* Read sync frame */
404     GetChunk( &p_spdif->bit_stream, p_spdif->p_ac3 + 2,
405               sizeof(sync_frame_t) - 2 );
406     if( p_spdif->p_fifo->b_die ) return -1;
407
408     p_sync_frame = (sync_frame_t*)p_spdif->p_ac3;
409
410     /* Compute frame rate */
411     i_frame_rate_code = (p_sync_frame->syncinfo.code >> 6) & 0x03;
412     p_spdif->ac3_info.i_sample_rate = p_sample_rates[i_frame_rate_code];
413     if( p_spdif->ac3_info.i_sample_rate == -1 )
414     {
415         return -1;
416     }
417
418     /* Compute frame size */
419     i_frame_size_code = p_sync_frame->syncinfo.code & 0x3f;
420     p_spdif->ac3_info.i_frame_size = 2 *
421         p_frame_size_code[i_frame_size_code].i_frame_size[i_frame_rate_code];
422     p_spdif->ac3_info.i_bit_rate =
423         p_frame_size_code[i_frame_size_code].i_bit_rate;
424
425     if( ( ( p_sync_frame->bsi.bsidmod >> 3 ) & 0x1f ) != 0x08 )
426     {
427         return -1;
428     }
429
430     p_spdif->ac3_info.i_bs_mod = p_sync_frame->bsi.bsidmod & 0x7;
431
432     return 0;
433 }