]> git.sesse.net Git - vlc/blob - src/audio_output/aout_spdif.c
a195eb1ecc4ff883e5750b4676328eae851e9abc
[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.6 2001/05/19 00:39:30 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 1000
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
64     /* get a blank frame ready */
65     memset( pi_blank, 0, sizeof(pi_blank) );
66     memcpy( pi_blank, pi_spdif_blank, sizeof(pi_spdif_blank) );
67    
68     intf_WarnMsg( 3, "aout info: starting spdif output loop" );
69
70     /* variable used to compute the nnumber of blank frames since the
71      * last significant frame */
72     i_blank = 0;
73
74     while( !p_aout->b_die )
75     {
76         /* we leave some time for aout fifo to fill and not to stress
77          * the external decoder too much */
78         msleep( 10000 );
79
80         /* variable to check that we send data to the decoder
81          * once per loop at least */
82         i_frame = 0;
83
84         /* FIXME: find a way to hnadle the locks here */
85         for( i_fifo = 0 ; i_fifo < AOUT_MAX_FIFOS ; i_fifo++ )
86         {
87             /* the loop read each fifo so that we can change the stream
88              * on the fly but mulitplexing is not handled yet so
89              * the sound will be broken is more than one fifo has data */ 
90             /* TODO: write the muliplexer :) */
91             if( p_aout->fifo[i_fifo].i_type == AOUT_ADEC_SPDIF_FIFO )
92             {
93                 vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
94                 if( p_aout->fifo[i_fifo].b_die )
95                 {
96                     vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
97                     aout_FreeFifo( &p_aout->fifo[i_fifo] );
98                 }
99                 else if( !AOUT_FIFO_ISEMPTY( p_aout->fifo[i_fifo] ) )
100                 {
101 //                    vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
102 //fprintf(stderr, "delay %lld\n",p_aout->fifo[i_fifo].date[p_aout->fifo[i_fifo].l_start_frame]  -mdate() );
103                    
104                     /* play spdif frame to the external decoder */
105                     p_aout->pf_play( p_aout,
106                                      p_aout->fifo[i_fifo].buffer +
107                                         p_aout->fifo[i_fifo].l_start_frame*
108                                         SPDIF_FRAME_SIZE,
109                                      p_aout->fifo[i_fifo].l_frame_size );
110         
111 //                    vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
112                     p_aout->fifo[i_fifo].l_start_frame = 
113                         (p_aout->fifo[i_fifo].l_start_frame + 1 )
114                         & AOUT_FIFO_SIZE;
115                     vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
116                     
117                     i_frame++;
118                     i_blank = 0;
119                 }
120                 else
121                 {
122                     vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
123                 }
124             }
125         }
126         if( !i_frame )
127         {
128             /* insert blank frame for stream continuity to
129              * the external decoder */
130             p_aout->pf_play( p_aout, pi_blank, SPDIF_FRAME_SIZE );
131
132             /* we kill the output if we don't have any stream */
133             if( ++i_blank > BLANK_FRAME_MAX )
134             {
135                 p_aout->b_die = 1;
136             }
137         }
138     }
139     
140     intf_WarnMsg( 3, "aout info: exiting spdif loop" );
141
142     return;
143 }
144