1 /*****************************************************************************
2 * aout_spdif.c: A52 passthrough output
3 *****************************************************************************
4 * Copyright (C) 2001 VideoLAN
5 * $Id: aout_spdif.c,v 1.30 2002/08/04 17:23:44 sam 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 *****************************************************************************/
28 #include <stdlib.h> /* calloc(), malloc(), free() */
29 #include <string.h> /* memset() */
37 #include "audio_output.h"
38 #include "aout_spdif.h"
40 /****************************************************************************
41 * iec958_build_burst: builds an iec958/spdif frame
42 ****************************************************************************/
43 void iec958_build_burst( u8 * p_buf, aout_fifo_t * p_fifo )
45 const u8 p_sync[6] = { 0x72, 0xF8, 0x1F, 0x4E, 0x01, 0x00 };
46 int i_length = p_fifo->i_frame_size;
48 /* Skip the first byte if i_length is odd */
49 u16 * p_in = (u16 *)( p_fifo->buffer + ( i_length & 0x1 ) );
50 u16 * p_out = (u16 *)p_buf;
53 /* Add the spdif headers */
54 memcpy( p_buf, p_sync, 6 );
55 p_buf[6] = ( i_length * 8 ) & 0xFF;
56 p_buf[7] = ( ( i_length * 8 ) >> 8 ) & 0xFF;
59 swab( p_fifo->buffer + p_fifo->i_start_frame * i_length,
60 p_buf + 8, i_length );
62 /* i_length should be even */
67 *p_out = ( (*p_in & 0x00ff) << 16 ) | ( (*p_in & 0xff00) >> 16 );
74 /* Add zeroes to complete the spdif frame,
75 * they will be ignored by the decoder */
76 memset( p_buf + 8 + i_length, 0, SPDIF_FRAME_SIZE - 8 - i_length );
80 /*****************************************************************************
81 * aout_SpdifThread: audio output thread that sends raw spdif data
82 * to an external decoder
83 *****************************************************************************
84 * This output thread is quite specific as it can only handle one fifo now.
86 * Note: spdif can demux up to 8 A52 streams, and can even take
87 * care of time stamps (cf A52 spec) but I'm not sure all decoders
89 *****************************************************************************/
90 void aout_SpdifThread( aout_thread_t * p_aout )
93 mtime_t m_frame_time = 0;
97 while( !p_aout->b_die )
100 /* Find spdif fifo */
101 while( ( p_aout->fifo[i_fifo].i_format != AOUT_FIFO_SPDIF ) &&
102 ( i_fifo < AOUT_MAX_FIFOS ) && !p_aout->b_die )
109 while( !p_aout->b_die &&
110 !p_aout->fifo[i_fifo].b_die )
112 vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
113 if( !AOUT_FIFO_ISEMPTY( p_aout->fifo[i_fifo] ) )
115 /* Copy data from fifo to buffer to release the
117 iec958_build_burst( p_aout->buffer,
118 &p_aout->fifo[i_fifo] );
120 m_play = p_aout->fifo[i_fifo].date[p_aout->fifo[i_fifo].
123 p_aout->fifo[i_fifo].i_start_frame =
124 (p_aout->fifo[i_fifo].i_start_frame + 1 )
127 /* Compute the theorical duration of an A52 frame */
128 m_frame_time = 1000000 * A52_FRAME_SIZE
129 / p_aout->fifo[i_fifo].i_rate;
131 vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
133 /* Play spdif frame to the external decoder
134 * the kernel driver will sleep until the
135 * dsp buffer is empty enough to accept the data */
136 if( m_play > ( mdate() - m_frame_time ) )
138 /* check continuity */
139 if( (m_play - m_old) != m_frame_time )
141 mwait( m_play - m_frame_time );
145 mwait( m_play - 2 * m_frame_time );
149 p_aout->pf_getbufinfo( p_aout, 0 );
151 p_aout->pf_play( p_aout, (byte_t *)p_aout->buffer,
157 msg_Warn( p_aout, "empty spdif fifo" );
158 while( AOUT_FIFO_ISEMPTY( p_aout->fifo[i_fifo] ) &&
160 !p_aout->fifo[i_fifo].b_die )
163 vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
164 msleep( m_frame_time );
165 vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
167 vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
171 vlc_mutex_lock( &p_aout->fifos_lock );
172 aout_FreeFifo( &p_aout->fifo[i_fifo] );
173 vlc_mutex_unlock( &p_aout->fifos_lock );