]> git.sesse.net Git - vlc/blob - src/audio_output/aout_spdif.c
-Changes and bugfixes to make network work in VLAN Broadcast mode.
[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.7 2001/05/30 05:19:03 stef 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
46 /*****************************************************************************
47  * aout_SpdifThread: audio output thread that sends raw spdif data
48  *                   to an external decoder
49  *****************************************************************************
50  * This output thread is quite specific as it can only handle one fifo now.
51  *
52  * Note: spdif can demux up to 8 ac3 streams, and can even take
53  * care of time stamps (cf ac3 spec).
54  *****************************************************************************/
55 void aout_SpdifThread( aout_thread_t * p_aout )
56 {
57     u8          pi_spdif_blank [9] =
58                     { 0x72, 0xf8, 0x1f, 0x4e, 0x01, 0x00, 0x08, 0x00, 0x77 };
59     u8          pi_blank[SPDIF_FRAME_SIZE];
60     int         i_fifo;
61     int         i_frame;
62     int         i_blank;
63     mtime_t     mplay;
64     mtime_t     mdelta;
65     mtime_t     mlast = 0;
66     mtime_t     m_frame_time;
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     m_frame_time = 1000000 * AC3_FRAME_SIZE / p_aout->fifo[0].l_rate;
80
81     while( !p_aout->b_die )
82     {
83         /* variable to check that we send data to the decoder
84          * once per loop at least */
85         i_frame = 0;
86
87         /* FIXME: find a way to handle the locks here */
88         for( i_fifo = 0 ; i_fifo < AOUT_MAX_FIFOS ; i_fifo++ )
89         {
90             /* the loop read each fifo so that we can change the stream
91              * on the fly but mulitplexing is not handled yet so
92              * the sound will be broken is more than one fifo has data */ 
93             /* TODO: write the muliplexer :) */
94             if( p_aout->fifo[i_fifo].i_type == AOUT_ADEC_SPDIF_FIFO )
95             {
96                 vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
97                 if( p_aout->fifo[i_fifo].b_die )
98                 {
99                     vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
100                     aout_FreeFifo( &p_aout->fifo[i_fifo] );
101                 }
102                 else if( !AOUT_FIFO_ISEMPTY( p_aout->fifo[i_fifo] ) )
103                 {
104                     mplay = p_aout->fifo[i_fifo].date[p_aout->fifo[i_fifo].
105                                 l_start_frame];
106                     mdelta = mplay - mdate();
107
108                     if( mdelta < ( 2 * m_frame_time ) )
109                     {
110                         intf_WarnMsg( 12, "spdif out (%d):"
111                                           "playing frame %lld (%lld)",
112                                            i_fifo,
113                                            mdelta,
114                                            mplay-mlast );
115                         mlast = mplay;
116                         /* play spdif frame to the external decoder */
117                         p_aout->pf_play( p_aout,
118                                          p_aout->fifo[i_fifo].buffer +
119                                             p_aout->fifo[i_fifo].l_start_frame*
120                                             SPDIF_FRAME_SIZE,
121                                          p_aout->fifo[i_fifo].l_frame_size );
122
123                         p_aout->fifo[i_fifo].l_start_frame = 
124                             (p_aout->fifo[i_fifo].l_start_frame + 1 )
125                             & AOUT_FIFO_SIZE;
126                         
127                         i_frame++;
128                         i_blank = 0;
129                     }
130                     vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
131                 }
132                 else
133                 {
134                     vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
135                 }
136             }
137         }
138
139         if( i_frame )
140         {
141             /* we leave some time for aout fifo to fill and not to stress
142              * the external decoder too much */
143             msleep( m_frame_time / 2 );
144         }
145         else
146         {
147             /* insert blank frame for stream continuity to
148              * the external decoder */
149             intf_WarnMsg( 6, "spdif warning: blank frame" );
150             p_aout->pf_play( p_aout, pi_blank, SPDIF_FRAME_SIZE/4 );
151
152             /* we kill the output if we don't have any stream */
153             if( ++i_blank > BLANK_FRAME_MAX )
154             {
155                 p_aout->b_die = 1;
156             }
157         }
158     }
159     
160     intf_WarnMsg( 3, "aout info: exiting spdif loop" );
161     vlc_mutex_lock( &p_aout->fifos_lock );
162
163     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
164     {
165         aout_FreeFifo( &p_aout->fifo[i_fifo] );
166     }
167
168     vlc_mutex_unlock( &p_aout->fifos_lock );
169
170     return;
171 }
172