1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/*****************************************************************************
* aout_spdif: ac3 passthrough output
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: aout_spdif.c,v 1.22 2002/02/19 00:50:19 sam Exp $
*
* Authors: Michel Kaempf <maxx@via.ecp.fr>
* Stphane Borel <stef@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <stdio.h> /* "intf_msg.h" */
#include <stdlib.h> /* calloc(), malloc(), free() */
#include <string.h> /* memset() */
#include <videolan/vlc.h>
#include "audio_output.h"
#include "aout_common.h"
/*****************************************************************************
* aout_SpdifThread: audio output thread that sends raw spdif data
* to an external decoder
*****************************************************************************
* This output thread is quite specific as it can only handle one fifo now.
*
* Note: spdif can demux up to 8 ac3 streams, and can even take
* care of time stamps (cf ac3 spec) but I'm not sure all decoders
* implement it.
*****************************************************************************/
void aout_SpdifThread( aout_thread_t * p_aout )
{
int i_fifo;
mtime_t m_frame_time = 0;
mtime_t m_play;
mtime_t m_old = 0;
while( !p_aout->b_die )
{
for( i_fifo = 0 ; i_fifo < AOUT_MAX_FIFOS ; i_fifo++ )
{
/* the loop read each fifo so that we can change the stream
* on the fly but mulitplexing is not handled yet so
* the sound will be broken is more than one fifo has data */
/* TODO: write the muliplexer :) */
if( p_aout->fifo[i_fifo].i_type == AOUT_ADEC_SPDIF_FIFO )
{
vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
if( p_aout->fifo[i_fifo].b_die )
{
vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
vlc_mutex_lock( &p_aout->fifos_lock );
aout_FreeFifo( &p_aout->fifo[i_fifo] );
vlc_mutex_unlock( &p_aout->fifos_lock );
}
else if( !AOUT_FIFO_ISEMPTY( p_aout->fifo[i_fifo] ) )
{
/* Copy data from fifo to buffer to release the lock earlier */
memcpy( p_aout->buffer,
(byte_t *)p_aout->fifo[i_fifo].buffer
+ p_aout->fifo[i_fifo].l_start_frame
* SPDIF_FRAME_SIZE,
SPDIF_FRAME_SIZE );
m_play = p_aout->fifo[i_fifo].date[p_aout->fifo[i_fifo].
l_start_frame];
p_aout->fifo[i_fifo].l_start_frame =
(p_aout->fifo[i_fifo].l_start_frame + 1 )
& AOUT_FIFO_SIZE;
/* Compute the theorical duration of an ac3 frame */
m_frame_time = 1000000 * AC3_FRAME_SIZE
/ p_aout->fifo[i_fifo].l_rate;
vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
/* play spdif frame to the external decoder
* the kernel driver will sleep until the
* dsp buffer is empty enough to accept the data */
if( m_play > ( mdate() - m_frame_time ) )
{
/* check continuity */
if( (m_play - m_old) != m_frame_time )
{
mwait( m_play - m_frame_time );
}
else
{
mwait( m_play - 2 * m_frame_time );
}
m_old = m_play;
p_aout->pf_play( p_aout,
(byte_t *)p_aout->buffer,
SPDIF_FRAME_SIZE );
}
}
else
{
vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
msleep( m_frame_time );
intf_WarnMsg( 3, "aout warning: empty spdif fifo" );
}
}
}
}
vlc_mutex_lock( &p_aout->fifos_lock );
for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
{
aout_FreeFifo( &p_aout->fifo[i_fifo] );
}
vlc_mutex_unlock( &p_aout->fifos_lock );
return;
}