1 /*******************************************************************************
2 * spu_decoder.c : spu decoder thread
4 *******************************************************************************/
6 /* repompé sur video_decoder.c
7 * ?? passer en terminate/destroy avec les signaux supplémentaires */
9 /*******************************************************************************
11 *******************************************************************************/
24 #include "vlc_thread.h"
27 #include "debug.h" /* ?? temporaire, requis par netlist.h */
30 #include "input_netlist.h"
31 #include "decoder_fifo.h"
33 #include "spu_decoder.h"
38 static int InitThread ( spudec_thread_t *p_spudec );
39 static void RunThread ( spudec_thread_t *p_spudec );
40 static void ErrorThread ( spudec_thread_t *p_spudec );
41 static void EndThread ( spudec_thread_t *p_spudec );
43 /******************************************************************************
44 * spudec_CreateThread: create a spu decoder thread
45 ******************************************************************************/
46 spudec_thread_t * spudec_CreateThread( input_thread_t * p_input )
48 spudec_thread_t * p_spudec;
50 intf_DbgMsg("spudec debug: creating spu decoder thread\n");
52 /* Allocate the memory needed to store the thread's structure */
53 if ( (p_spudec = (spudec_thread_t *)malloc( sizeof(spudec_thread_t) )) == NULL )
55 intf_ErrMsg("spudec error: not enough memory for spudec_CreateThread() to create the new thread\n");
60 * Initialize the thread properties
63 p_spudec->b_error = 0;
66 * Initialize the input properties
68 /* Initialize the decoder fifo's data lock and conditional variable and set
69 * its buffer as empty */
70 vlc_mutex_init( &p_spudec->fifo.data_lock );
71 vlc_cond_init( &p_spudec->fifo.data_wait );
72 p_spudec->fifo.i_start = 0;
73 p_spudec->fifo.i_end = 0;
74 /* Initialize the bit stream structure */
75 p_spudec->bit_stream.p_input = p_input;
76 p_spudec->bit_stream.p_decoder_fifo = &p_spudec->fifo;
77 p_spudec->bit_stream.fifo.buffer = 0;
78 p_spudec->bit_stream.fifo.i_available = 0;
80 /* Spawn the spu decoder thread */
81 if ( vlc_thread_create(&p_spudec->thread_id, "spu decoder",
82 (vlc_thread_func_t)RunThread, (void *)p_spudec) )
84 intf_ErrMsg("spudec error: can't spawn spu decoder thread\n");
89 intf_DbgMsg("spudec debug: spu decoder thread (%p) created\n", p_spudec);
93 /*******************************************************************************
94 * spudec_DestroyThread: destroy a spu decoder thread
95 *******************************************************************************
96 * Destroy and terminate thread. This function will return 0 if the thread could
97 * be destroyed, and non 0 else. The last case probably means that the thread
98 * was still active, and another try may succeed.
99 *******************************************************************************/
100 void spudec_DestroyThread( spudec_thread_t *p_spudec )
102 intf_DbgMsg("spudec debug: requesting termination of spu decoder thread %p\n", p_spudec);
104 /* Ask thread to kill itself */
107 /* Warn the decoder that we're quitting */
108 vlc_mutex_lock( &p_spudec->fifo.data_lock );
109 vlc_cond_signal( &p_spudec->fifo.data_wait );
110 vlc_mutex_unlock( &p_spudec->fifo.data_lock );
112 /* Waiting for the decoder thread to exit */
113 /* Remove this as soon as the "status" flag is implemented */
114 vlc_thread_join( p_spudec->thread_id );
117 /* following functions are local */
119 /*******************************************************************************
120 * InitThread: initialize spu decoder thread
121 *******************************************************************************
122 * This function is called from RunThread and performs the second step of the
123 * initialization. It returns 0 on success. Note that the thread's flag are not
124 * modified inside this function.
125 *******************************************************************************/
126 static int InitThread( spudec_thread_t *p_spudec )
128 intf_DbgMsg("spudec debug: initializing spu decoder thread %p\n", p_spudec);
130 /* Our first job is to initialize the bit stream structure with the
131 * beginning of the input stream */
132 vlc_mutex_lock( &p_spudec->fifo.data_lock );
133 while ( DECODER_FIFO_ISEMPTY(p_spudec->fifo) )
135 if ( p_spudec->b_die )
137 vlc_mutex_unlock( &p_spudec->fifo.data_lock );
140 vlc_cond_wait( &p_spudec->fifo.data_wait, &p_spudec->fifo.data_lock );
143 p_spudec->bit_stream.p_ts = DECODER_FIFO_START( p_spudec->fifo )->p_first_ts;
144 p_spudec->bit_stream.i_byte = p_spudec->bit_stream.p_ts->i_payload_start;
145 vlc_mutex_unlock( &p_spudec->fifo.data_lock );
147 /* Mark thread as running and return */
148 intf_DbgMsg( "spudec debug: InitThread(%p) succeeded\n", p_spudec );
152 /*******************************************************************************
153 * RunThread: spu decoder thread
154 *******************************************************************************
155 * spu decoder thread. This function does only return when the thread is
157 *******************************************************************************/
158 static void RunThread( spudec_thread_t *p_spudec )
160 intf_DbgMsg("spudec debug: running spu decoder thread (%p) (pid == %i)\n",
164 * Initialize thread and free configuration
166 p_spudec->b_error = InitThread( p_spudec );
171 * Main loop - it is not executed if an error occured during
174 vlc_mutex_lock( &p_spudec->fifo.data_lock );
175 while( (!p_spudec->b_die) && (!p_spudec->b_error) )
177 /* Trash all received PES packets */
178 while( !DECODER_FIFO_ISEMPTY(p_spudec->fifo) )
180 input_NetlistFreePES( p_spudec->bit_stream.p_input, DECODER_FIFO_START(p_spudec->fifo) );
181 DECODER_FIFO_INCSTART( p_spudec->fifo );
183 /* Waiting for the input thread to put new PES packets in the fifo */
184 vlc_cond_wait( &p_spudec->fifo.data_wait, &p_spudec->fifo.data_lock );
186 vlc_mutex_unlock( &p_spudec->fifo.data_lock );
191 if( p_spudec->b_error )
193 ErrorThread( p_spudec );
199 EndThread( p_spudec );
202 /*******************************************************************************
203 * ErrorThread: RunThread() error loop
204 *******************************************************************************
205 * This function is called when an error occured during thread main's loop. The
206 * thread can still receive feed, but must be ready to terminate as soon as
208 *******************************************************************************/
209 static void ErrorThread( spudec_thread_t *p_spudec )
211 /* We take the lock, because we are going to read/write the start/end
212 * indexes of the decoder fifo */
213 vlc_mutex_lock( &p_spudec->fifo.data_lock );
215 /* Wait until a `die' order is sent */
216 while( !p_spudec->b_die )
218 /* Trash all received PES packets */
219 while( !DECODER_FIFO_ISEMPTY(p_spudec->fifo) )
221 input_NetlistFreePES( p_spudec->bit_stream.p_input, DECODER_FIFO_START(p_spudec->fifo) );
222 DECODER_FIFO_INCSTART( p_spudec->fifo );
225 /* Waiting for the input thread to put new PES packets in the fifo */
226 vlc_cond_wait( &p_spudec->fifo.data_wait, &p_spudec->fifo.data_lock );
229 /* We can release the lock before leaving */
230 vlc_mutex_unlock( &p_spudec->fifo.data_lock );
233 /*******************************************************************************
234 * EndThread: thread destruction
235 *******************************************************************************
236 * This function is called when the thread ends after a sucessfull
238 *******************************************************************************/
239 static void EndThread( spudec_thread_t *p_spudec )
241 intf_DbgMsg( "spudec debug: destroying spu decoder thread %p\n", p_spudec );
243 intf_DbgMsg( "spudec debug: spu decoder thread %p destroyed\n", p_spudec);