]> git.sesse.net Git - vlc/blob - src/audio_output/aout_spdif.c
6c0575788e95f1b9a60ffa1afe5a9791bf3ab63b
[vlc] / src / audio_output / aout_spdif.c
1 /*****************************************************************************
2  * aout_spdif: ac3 passthrough output
3  *****************************************************************************
4  * Copyright (C) 2001 VideoLAN
5  * $Id: aout_spdif.c,v 1.10 2001/05/31 03:12:49 sam Exp $
6  *
7  * Authors: Michel Kaempf <maxx@via.ecp.fr>
8  *          Stéphane Borel <stef@via.ecp.fr>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  * 
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include "defs.h"
29
30 #include <stdio.h>                                           /* "intf_msg.h" */
31 #include <stdlib.h>                            /* calloc(), malloc(), free() */
32 #include <string.h>                                              /* memset() */
33
34 #include "config.h"
35 #include "common.h"
36 #include "threads.h"
37 #include "mtime.h"                             /* mtime_t, mdate(), msleep() */
38
39 #include "intf_msg.h"                        /* intf_DbgMsg(), intf_ErrMsg() */
40
41 #include "audio_output.h"
42 #include "aout_common.h"
43
44 #define BLANK_FRAME_MAX 100
45 #define SLEEP_TIME      16000
46
47 /*****************************************************************************
48  * aout_SpdifThread: audio output thread that sends raw spdif data
49  *                   to an external decoder
50  *****************************************************************************
51  * This output thread is quite specific as it can only handle one fifo now.
52  *
53  * Note: spdif can demux up to 8 ac3 streams, and can even take
54  * care of time stamps (cf ac3 spec).
55  *****************************************************************************/
56 void aout_SpdifThread( aout_thread_t * p_aout )
57 {
58     u8          pi_spdif_blank [9] =
59                     { 0x72, 0xf8, 0x1f, 0x4e, 0x01, 0x00, 0x08, 0x00, 0x77 };
60     u8          pi_blank[SPDIF_FRAME_SIZE];
61     int         i_fifo;
62     int         i_frame;
63     int         i_blank;
64     mtime_t     mplay;
65     mtime_t     mdelta;
66     mtime_t     mlast = 0;
67
68     /* get a blank frame ready */
69     memset( pi_blank, 0, sizeof(pi_blank) );
70     memcpy( pi_blank, pi_spdif_blank, sizeof(pi_spdif_blank) );
71    
72     intf_WarnMsg( 3, "aout info: starting spdif output loop" );
73
74     /* variable used to compute the nnumber of blank frames since the
75      * last significant frame */
76     i_blank = 0;
77
78     /* Compute the theorical duration of an ac3 frame */
79
80     while( !p_aout->b_die )
81     {
82         /* variable to check that we send data to the decoder
83          * once per loop at least */
84         i_frame = 0;
85
86         /* FIXME: find a way to handle the locks here */
87         for( i_fifo = 0 ; i_fifo < AOUT_MAX_FIFOS ; i_fifo++ )
88         {
89             /* the loop read each fifo so that we can change the stream
90              * on the fly but mulitplexing is not handled yet so
91              * the sound will be broken is more than one fifo has data */ 
92             /* TODO: write the muliplexer :) */
93             if( p_aout->fifo[i_fifo].i_type == AOUT_ADEC_SPDIF_FIFO )
94             {
95                 vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
96                 if( p_aout->fifo[i_fifo].b_die )
97                 {
98                     vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
99                     aout_FreeFifo( &p_aout->fifo[i_fifo] );
100                 }
101                 else if( !AOUT_FIFO_ISEMPTY( p_aout->fifo[i_fifo] ) )
102                 {
103                     mplay = p_aout->fifo[i_fifo].date[p_aout->fifo[i_fifo].
104                                 l_start_frame];
105                     mdelta = mplay - mdate();
106
107                     if( mdelta < ( 2 * SLEEP_TIME ) )
108                     {
109                         intf_WarnMsg( 12, "spdif out (%d):"
110                                           "playing frame %lld (%lld)",
111                                            i_fifo,
112                                            mdelta,
113                                            mplay-mlast );
114                         mlast = mplay;
115                         /* play spdif frame to the external decoder */
116                         p_aout->pf_play( p_aout,
117                                      ( (byte_t *)p_aout->fifo[i_fifo].buffer
118                                          + p_aout->fifo[i_fifo].l_start_frame
119                                             * SPDIF_FRAME_SIZE ),
120                                      p_aout->fifo[i_fifo].l_frame_size );
121
122                         p_aout->fifo[i_fifo].l_start_frame = 
123                             (p_aout->fifo[i_fifo].l_start_frame + 1 )
124                             & AOUT_FIFO_SIZE;
125                         
126                         i_frame++;
127                         i_blank = 0;
128                     }
129                     vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
130                 }
131                 else
132                 {
133                     vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
134                 }
135             }
136         }
137
138         if( i_frame )
139         {
140             /* we leave some time for aout fifo to fill and not to stress
141              * the external decoder too much */
142             msleep( SLEEP_TIME );
143         }
144         else
145         {
146             /* insert blank frame for stream continuity to
147              * the external decoder */
148             intf_WarnMsg( 6, "spdif warning: blank frame" );
149             p_aout->pf_play( p_aout, pi_blank, SPDIF_FRAME_SIZE/4 );
150
151             /* we kill the output if we don't have any stream */
152             if( ++i_blank > BLANK_FRAME_MAX )
153             {
154                 p_aout->b_die = 1;
155             }
156         }
157     }
158     
159     intf_WarnMsg( 3, "aout info: exiting spdif loop" );
160     vlc_mutex_lock( &p_aout->fifos_lock );
161
162     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
163     {
164         aout_FreeFifo( &p_aout->fifo[i_fifo] );
165     }
166
167     vlc_mutex_unlock( &p_aout->fifos_lock );
168
169     return;
170 }
171