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 *****************************************************************************/
30 #include <stdlib.h> /* malloc(), free() */
31 #include <sys/types.h> /* on BSD, uio.h needs types.h */
32 #include <sys/uio.h> /* for input.h */
33 #include <unistd.h> /* getpid() */
41 #include "debug.h" /* ASSERT */
44 #include "input_netlist.h"
45 #include "decoder_fifo.h"
47 #include "spu_decoder.h"
52 static int InitThread ( spudec_thread_t *p_spudec );
53 static void RunThread ( spudec_thread_t *p_spudec );
54 static void ErrorThread ( spudec_thread_t *p_spudec );
55 static void EndThread ( spudec_thread_t *p_spudec );
57 /*****************************************************************************
58 * spudec_CreateThread: create a spu decoder thread
59 *****************************************************************************/
60 spudec_thread_t * spudec_CreateThread( input_thread_t * p_input )
62 spudec_thread_t * p_spudec;
64 intf_DbgMsg("spudec debug: creating spu decoder thread\n");
66 /* Allocate the memory needed to store the thread's structure */
67 if ( (p_spudec = (spudec_thread_t *)malloc( sizeof(spudec_thread_t) )) == NULL )
69 intf_ErrMsg("spudec error: not enough memory for spudec_CreateThread() to create the new thread\n");
74 * Initialize the thread properties
77 p_spudec->b_error = 0;
80 * Initialize the input properties
82 /* Initialize the decoder fifo's data lock and conditional variable and set
83 * its buffer as empty */
84 vlc_mutex_init( &p_spudec->fifo.data_lock );
85 vlc_cond_init( &p_spudec->fifo.data_wait );
86 p_spudec->fifo.i_start = 0;
87 p_spudec->fifo.i_end = 0;
88 /* Initialize the bit stream structure */
89 p_spudec->bit_stream.p_input = p_input;
90 p_spudec->bit_stream.p_decoder_fifo = &p_spudec->fifo;
91 p_spudec->bit_stream.fifo.buffer = 0;
92 p_spudec->bit_stream.fifo.i_available = 0;
94 /* Spawn the spu decoder thread */
95 if ( vlc_thread_create(&p_spudec->thread_id, "spu decoder",
96 (vlc_thread_func_t)RunThread, (void *)p_spudec) )
98 intf_ErrMsg("spudec error: can't spawn spu decoder thread\n");
103 intf_DbgMsg("spudec debug: spu decoder thread (%p) created\n", p_spudec);
107 /*****************************************************************************
108 * spudec_DestroyThread: destroy a spu decoder thread
109 *****************************************************************************
110 * Destroy and terminate thread. This function will return 0 if the thread could
111 * be destroyed, and non 0 else. The last case probably means that the thread
112 * was still active, and another try may succeed.
113 *****************************************************************************/
114 void spudec_DestroyThread( spudec_thread_t *p_spudec )
116 intf_DbgMsg("spudec debug: requesting termination of spu decoder thread %p\n", p_spudec);
118 /* Ask thread to kill itself */
121 /* Warn the decoder that we're quitting */
122 vlc_mutex_lock( &p_spudec->fifo.data_lock );
123 vlc_cond_signal( &p_spudec->fifo.data_wait );
124 vlc_mutex_unlock( &p_spudec->fifo.data_lock );
126 /* Waiting for the decoder thread to exit */
127 /* Remove this as soon as the "status" flag is implemented */
128 vlc_thread_join( p_spudec->thread_id );
131 /* following functions are local */
133 /*****************************************************************************
134 * InitThread: initialize spu decoder thread
135 *****************************************************************************
136 * This function is called from RunThread and performs the second step of the
137 * initialization. It returns 0 on success. Note that the thread's flag are not
138 * modified inside this function.
139 *****************************************************************************/
140 static int InitThread( spudec_thread_t *p_spudec )
142 intf_DbgMsg("spudec debug: initializing spu decoder thread %p\n", p_spudec);
144 /* Our first job is to initialize the bit stream structure with the
145 * beginning of the input stream */
146 vlc_mutex_lock( &p_spudec->fifo.data_lock );
147 while ( DECODER_FIFO_ISEMPTY(p_spudec->fifo) )
149 if ( p_spudec->b_die )
151 vlc_mutex_unlock( &p_spudec->fifo.data_lock );
154 vlc_cond_wait( &p_spudec->fifo.data_wait, &p_spudec->fifo.data_lock );
157 p_spudec->bit_stream.p_ts = DECODER_FIFO_START( p_spudec->fifo )->p_first_ts;
158 p_spudec->bit_stream.p_byte = p_spudec->bit_stream.p_ts->buffer + p_spudec->bit_stream.p_ts->i_payload_start;
159 p_spudec->bit_stream.p_end = p_spudec->bit_stream.p_ts->buffer + p_spudec->bit_stream.p_ts->i_payload_end;
160 vlc_mutex_unlock( &p_spudec->fifo.data_lock );
162 /* Mark thread as running and return */
163 intf_DbgMsg( "spudec debug: InitThread(%p) succeeded\n", p_spudec );
167 /*****************************************************************************
168 * RunThread: spu decoder thread
169 *****************************************************************************
170 * spu decoder thread. This function does only return when the thread is
172 *****************************************************************************/
173 static void RunThread( spudec_thread_t *p_spudec )
175 intf_DbgMsg("spudec debug: running spu decoder thread (%p) (pid == %i)\n",
179 * Initialize thread and free configuration
181 p_spudec->b_error = InitThread( p_spudec );
186 * Main loop - it is not executed if an error occured during
189 vlc_mutex_lock( &p_spudec->fifo.data_lock );
190 while( (!p_spudec->b_die) && (!p_spudec->b_error) )
192 /* Trash all received PES packets */
193 while( !DECODER_FIFO_ISEMPTY(p_spudec->fifo) )
195 input_NetlistFreePES( p_spudec->bit_stream.p_input, DECODER_FIFO_START(p_spudec->fifo) );
196 DECODER_FIFO_INCSTART( p_spudec->fifo );
198 /* Waiting for the input thread to put new PES packets in the fifo */
199 vlc_cond_wait( &p_spudec->fifo.data_wait, &p_spudec->fifo.data_lock );
201 vlc_mutex_unlock( &p_spudec->fifo.data_lock );
206 if( p_spudec->b_error )
208 ErrorThread( p_spudec );
214 EndThread( p_spudec );
217 /*****************************************************************************
218 * ErrorThread: RunThread() error loop
219 *****************************************************************************
220 * This function is called when an error occured during thread main's loop. The
221 * thread can still receive feed, but must be ready to terminate as soon as
223 *****************************************************************************/
224 static void ErrorThread( spudec_thread_t *p_spudec )
226 /* We take the lock, because we are going to read/write the start/end
227 * indexes of the decoder fifo */
228 vlc_mutex_lock( &p_spudec->fifo.data_lock );
230 /* Wait until a `die' order is sent */
231 while( !p_spudec->b_die )
233 /* Trash all received PES packets */
234 while( !DECODER_FIFO_ISEMPTY(p_spudec->fifo) )
236 input_NetlistFreePES( p_spudec->bit_stream.p_input, DECODER_FIFO_START(p_spudec->fifo) );
237 DECODER_FIFO_INCSTART( p_spudec->fifo );
240 /* Waiting for the input thread to put new PES packets in the fifo */
241 vlc_cond_wait( &p_spudec->fifo.data_wait, &p_spudec->fifo.data_lock );
244 /* We can release the lock before leaving */
245 vlc_mutex_unlock( &p_spudec->fifo.data_lock );
248 /*****************************************************************************
249 * EndThread: thread destruction
250 *****************************************************************************
251 * This function is called when the thread ends after a sucessfull
253 *****************************************************************************/
254 static void EndThread( spudec_thread_t *p_spudec )
256 intf_DbgMsg( "spudec debug: destroying spu decoder thread %p\n", p_spudec );
258 intf_DbgMsg( "spudec debug: spu decoder thread %p destroyed\n", p_spudec);