1 /*****************************************************************************
2 * spu_decoder.c : spu decoder thread
3 *****************************************************************************
4 * Copyright (C) 2000 VideoLAN
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public
19 * License along with this program; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
22 *****************************************************************************/
24 /* repompé sur video_decoder.c
25 * FIXME: passer en terminate/destroy avec les signaux supplémentaires ?? */
27 /*****************************************************************************
29 *****************************************************************************/
32 #include <stdlib.h> /* malloc(), free() */
33 #include <sys/types.h> /* on BSD, uio.h needs types.h */
34 #include <sys/uio.h> /* for input.h */
35 #include <unistd.h> /* getpid() */
43 #include "debug.h" /* ASSERT */
46 #include "input_netlist.h"
47 #include "decoder_fifo.h"
49 #include "spu_decoder.h"
54 static int InitThread ( spudec_thread_t *p_spudec );
55 static void RunThread ( spudec_thread_t *p_spudec );
56 static void ErrorThread ( spudec_thread_t *p_spudec );
57 static void EndThread ( spudec_thread_t *p_spudec );
59 /*****************************************************************************
60 * spudec_CreateThread: create a spu decoder thread
61 *****************************************************************************/
62 spudec_thread_t * spudec_CreateThread( input_thread_t * p_input )
64 spudec_thread_t * p_spudec;
66 intf_DbgMsg("spudec debug: creating spu decoder thread\n");
68 /* Allocate the memory needed to store the thread's structure */
69 if ( (p_spudec = (spudec_thread_t *)malloc( sizeof(spudec_thread_t) )) == NULL )
71 intf_ErrMsg("spudec error: not enough memory for spudec_CreateThread() to create the new thread\n");
76 * Initialize the thread properties
79 p_spudec->b_error = 0;
82 * Initialize the input properties
84 /* Initialize the decoder fifo's data lock and conditional variable and set
85 * its buffer as empty */
86 vlc_mutex_init( &p_spudec->fifo.data_lock );
87 vlc_cond_init( &p_spudec->fifo.data_wait );
88 p_spudec->fifo.i_start = 0;
89 p_spudec->fifo.i_end = 0;
90 /* Initialize the bit stream structure */
91 p_spudec->bit_stream.p_input = p_input;
92 p_spudec->bit_stream.p_decoder_fifo = &p_spudec->fifo;
93 p_spudec->bit_stream.fifo.buffer = 0;
94 p_spudec->bit_stream.fifo.i_available = 0;
96 /* Spawn the spu decoder thread */
97 if ( vlc_thread_create(&p_spudec->thread_id, "spu decoder",
98 (vlc_thread_func_t)RunThread, (void *)p_spudec) )
100 intf_ErrMsg("spudec error: can't spawn spu decoder thread\n");
105 intf_DbgMsg("spudec debug: spu decoder thread (%p) created\n", p_spudec);
109 /*****************************************************************************
110 * spudec_DestroyThread: destroy a spu decoder thread
111 *****************************************************************************
112 * Destroy and terminate thread. This function will return 0 if the thread could
113 * be destroyed, and non 0 else. The last case probably means that the thread
114 * was still active, and another try may succeed.
115 *****************************************************************************/
116 void spudec_DestroyThread( spudec_thread_t *p_spudec )
118 intf_DbgMsg("spudec debug: requesting termination of spu decoder thread %p\n", p_spudec);
120 /* Ask thread to kill itself */
123 /* Warn the decoder that we're quitting */
124 vlc_mutex_lock( &p_spudec->fifo.data_lock );
125 vlc_cond_signal( &p_spudec->fifo.data_wait );
126 vlc_mutex_unlock( &p_spudec->fifo.data_lock );
128 /* Waiting for the decoder thread to exit */
129 /* Remove this as soon as the "status" flag is implemented */
130 vlc_thread_join( p_spudec->thread_id );
133 /* following functions are local */
135 /*****************************************************************************
136 * InitThread: initialize spu decoder thread
137 *****************************************************************************
138 * This function is called from RunThread and performs the second step of the
139 * initialization. It returns 0 on success. Note that the thread's flag are not
140 * modified inside this function.
141 *****************************************************************************/
142 static int InitThread( spudec_thread_t *p_spudec )
144 intf_DbgMsg("spudec debug: initializing spu decoder thread %p\n", p_spudec);
146 /* Our first job is to initialize the bit stream structure with the
147 * beginning of the input stream */
148 vlc_mutex_lock( &p_spudec->fifo.data_lock );
149 while ( DECODER_FIFO_ISEMPTY(p_spudec->fifo) )
151 if ( p_spudec->b_die )
153 vlc_mutex_unlock( &p_spudec->fifo.data_lock );
156 vlc_cond_wait( &p_spudec->fifo.data_wait, &p_spudec->fifo.data_lock );
159 p_spudec->bit_stream.p_ts = DECODER_FIFO_START( p_spudec->fifo )->p_first_ts;
160 p_spudec->bit_stream.p_byte = p_spudec->bit_stream.p_ts->buffer + p_spudec->bit_stream.p_ts->i_payload_start;
161 p_spudec->bit_stream.p_end = p_spudec->bit_stream.p_ts->buffer + p_spudec->bit_stream.p_ts->i_payload_end;
162 vlc_mutex_unlock( &p_spudec->fifo.data_lock );
164 /* Mark thread as running and return */
165 intf_DbgMsg( "spudec debug: InitThread(%p) succeeded\n", p_spudec );
169 /*****************************************************************************
170 * RunThread: spu decoder thread
171 *****************************************************************************
172 * spu decoder thread. This function does only return when the thread is
174 *****************************************************************************/
175 static void RunThread( spudec_thread_t *p_spudec )
177 intf_DbgMsg("spudec debug: running spu decoder thread (%p) (pid == %i)\n",
181 * Initialize thread and free configuration
183 p_spudec->b_error = InitThread( p_spudec );
188 * Main loop - it is not executed if an error occured during
191 vlc_mutex_lock( &p_spudec->fifo.data_lock );
192 while( (!p_spudec->b_die) && (!p_spudec->b_error) )
194 /* Trash all received PES packets */
195 while( !DECODER_FIFO_ISEMPTY(p_spudec->fifo) )
197 input_NetlistFreePES( p_spudec->bit_stream.p_input, DECODER_FIFO_START(p_spudec->fifo) );
198 DECODER_FIFO_INCSTART( p_spudec->fifo );
200 /* Waiting for the input thread to put new PES packets in the fifo */
201 vlc_cond_wait( &p_spudec->fifo.data_wait, &p_spudec->fifo.data_lock );
203 vlc_mutex_unlock( &p_spudec->fifo.data_lock );
208 if( p_spudec->b_error )
210 ErrorThread( p_spudec );
216 EndThread( p_spudec );
219 /*****************************************************************************
220 * ErrorThread: RunThread() error loop
221 *****************************************************************************
222 * This function is called when an error occured during thread main's loop. The
223 * thread can still receive feed, but must be ready to terminate as soon as
225 *****************************************************************************/
226 static void ErrorThread( spudec_thread_t *p_spudec )
228 /* We take the lock, because we are going to read/write the start/end
229 * indexes of the decoder fifo */
230 vlc_mutex_lock( &p_spudec->fifo.data_lock );
232 /* Wait until a `die' order is sent */
233 while( !p_spudec->b_die )
235 /* Trash all received PES packets */
236 while( !DECODER_FIFO_ISEMPTY(p_spudec->fifo) )
238 input_NetlistFreePES( p_spudec->bit_stream.p_input, DECODER_FIFO_START(p_spudec->fifo) );
239 DECODER_FIFO_INCSTART( p_spudec->fifo );
242 /* Waiting for the input thread to put new PES packets in the fifo */
243 vlc_cond_wait( &p_spudec->fifo.data_wait, &p_spudec->fifo.data_lock );
246 /* We can release the lock before leaving */
247 vlc_mutex_unlock( &p_spudec->fifo.data_lock );
250 /*****************************************************************************
251 * EndThread: thread destruction
252 *****************************************************************************
253 * This function is called when the thread ends after a sucessful
255 *****************************************************************************/
256 static void EndThread( spudec_thread_t *p_spudec )
258 intf_DbgMsg( "spudec debug: destroying spu decoder thread %p\n", p_spudec );
260 intf_DbgMsg( "spudec debug: spu decoder thread %p destroyed\n", p_spudec);