1 /*****************************************************************************
2 * aout_spdif: ac3 passthrough output
3 *****************************************************************************
4 * Copyright (C) 2001 VideoLAN
5 * $Id: aout_spdif.c,v 1.11 2001/05/31 16:10:05 stef Exp $
7 * Authors: Michel Kaempf <maxx@via.ecp.fr>
8 * Stéphane Borel <stef@via.ecp.fr>
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.
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.
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 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
30 #include <stdio.h> /* "intf_msg.h" */
31 #include <stdlib.h> /* calloc(), malloc(), free() */
32 #include <string.h> /* memset() */
37 #include "mtime.h" /* mtime_t, mdate(), msleep() */
39 #include "intf_msg.h" /* intf_DbgMsg(), intf_ErrMsg() */
41 #include "audio_output.h"
42 #include "aout_common.h"
44 #define BLANK_FRAME_MAX 1000
45 #define SLEEP_TIME 16000
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.
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 )
58 u8 pi_spdif_blank [9] =
59 { 0x72, 0xf8, 0x1f, 0x4e, 0x01, 0x00, 0x08, 0x00, 0x77 };
60 u8 pi_blank[SPDIF_FRAME_SIZE];
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) );
72 intf_WarnMsg( 3, "aout info: starting spdif output loop" );
74 /* variable used to compute the nnumber of blank frames since the
75 * last significant frame */
78 /* Compute the theorical duration of an ac3 frame */
80 while( !p_aout->b_die )
82 /* variable to check that we send data to the decoder
83 * once per loop at least */
86 /* FIXME: find a way to handle the locks here */
87 for( i_fifo = 0 ; i_fifo < AOUT_MAX_FIFOS ; i_fifo++ )
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 )
95 vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
96 if( p_aout->fifo[i_fifo].b_die )
98 vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
99 aout_FreeFifo( &p_aout->fifo[i_fifo] );
101 else if( !AOUT_FIFO_ISEMPTY( p_aout->fifo[i_fifo] ) )
103 mplay = p_aout->fifo[i_fifo].date[p_aout->fifo[i_fifo].
105 mdelta = mplay - mdate();
107 if( mdelta < ( 2 * SLEEP_TIME ) )
109 intf_WarnMsg( 12, "spdif out (%d):"
110 "playing frame %lld (%lld)",
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 );
122 p_aout->fifo[i_fifo].l_start_frame =
123 (p_aout->fifo[i_fifo].l_start_frame + 1 )
129 vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
133 vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
140 /* we leave some time for aout fifo to fill and not to stress
141 * the external decoder too much */
142 msleep( SLEEP_TIME );
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 );
151 /* we kill the output if we don't have any stream */
152 if( ++i_blank > BLANK_FRAME_MAX )
159 intf_WarnMsg( 3, "aout info: exiting spdif loop" );
160 vlc_mutex_lock( &p_aout->fifos_lock );
162 for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
164 aout_FreeFifo( &p_aout->fifo[i_fifo] );
167 vlc_mutex_unlock( &p_aout->fifos_lock );