]> git.sesse.net Git - vlc/blob - src/spu_decoder/spu_decoder.c
. normalement on devrait se prendre 1 seul mail par commit gr�ce aux
[vlc] / src / spu_decoder / spu_decoder.c
1 /*****************************************************************************
2  * spu_decoder.c : spu decoder thread
3  *****************************************************************************
4  * Copyright (C) 2000 VideoLAN
5  *
6  * Authors:
7  *
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.
12  *
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.
17  *
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  *****************************************************************************/
23
24 /* repompé sur video_decoder.c
25  * FIXME: passer en terminate/destroy avec les signaux supplémentaires ?? */
26
27 /*****************************************************************************
28  * Preamble
29  *****************************************************************************/
30 #include "defs.h"
31
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() */
36
37 #include "config.h"
38 #include "common.h"
39 #include "threads.h"
40 #include "mtime.h"
41
42 #include "intf_msg.h"
43 #include "debug.h"                                                 /* ASSERT */
44
45 #include "input.h"
46 #include "input_netlist.h"
47 #include "decoder_fifo.h"
48
49 #include "spu_decoder.h"
50
51 /*
52  * Local prototypes
53  */
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 );
58
59 /*****************************************************************************
60  * spudec_CreateThread: create a spu decoder thread
61  *****************************************************************************/
62 spudec_thread_t * spudec_CreateThread( input_thread_t * p_input )
63 {
64     spudec_thread_t *     p_spudec;
65
66     intf_DbgMsg("spudec debug: creating spu decoder thread\n");
67
68     /* Allocate the memory needed to store the thread's structure */
69     if ( (p_spudec = (spudec_thread_t *)malloc( sizeof(spudec_thread_t) )) == NULL )
70     {
71         intf_ErrMsg("spudec error: not enough memory for spudec_CreateThread() to create the new thread\n");
72         return( NULL );
73     }
74
75     /*
76      * Initialize the thread properties
77      */
78     p_spudec->b_die = 0;
79     p_spudec->b_error = 0;
80
81     /*
82      * Initialize the input properties
83      */
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;
95
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) )
99     {
100         intf_ErrMsg("spudec error: can't spawn spu decoder thread\n");
101         free( p_spudec );
102         return( NULL );
103     }
104
105     intf_DbgMsg("spudec debug: spu decoder thread (%p) created\n", p_spudec);
106     return( p_spudec );
107 }
108
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 )
117 {
118     intf_DbgMsg("spudec debug: requesting termination of spu decoder thread %p\n", p_spudec);
119
120     /* Ask thread to kill itself */
121     p_spudec->b_die = 1;
122
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 );
127
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 );
131 }
132
133 /* following functions are local */
134
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 )
143 {
144     intf_DbgMsg("spudec debug: initializing spu decoder thread %p\n", p_spudec);
145
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) )
150     {
151         if ( p_spudec->b_die )
152         {
153             vlc_mutex_unlock( &p_spudec->fifo.data_lock );
154             return( 1 );
155         }
156         vlc_cond_wait( &p_spudec->fifo.data_wait, &p_spudec->fifo.data_lock );
157     }
158
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 );
163
164     /* Mark thread as running and return */
165     intf_DbgMsg( "spudec debug: InitThread(%p) succeeded\n", p_spudec );
166     return( 0 );
167 }
168
169 /*****************************************************************************
170  * RunThread: spu decoder thread
171  *****************************************************************************
172  * spu decoder thread. This function does only return when the thread is
173  * terminated.
174  *****************************************************************************/
175 static void RunThread( spudec_thread_t *p_spudec )
176 {
177     intf_DbgMsg("spudec debug: running spu decoder thread (%p) (pid == %i)\n",
178         p_spudec, getpid());
179
180     /*
181      * Initialize thread and free configuration
182      */
183     p_spudec->b_error = InitThread( p_spudec );
184
185     p_spudec->b_run = 1;
186
187     /*
188      * Main loop - it is not executed if an error occured during
189      * initialization
190      */
191     vlc_mutex_lock( &p_spudec->fifo.data_lock );
192     while( (!p_spudec->b_die) && (!p_spudec->b_error) )
193     {
194         /* Trash all received PES packets */
195         while( !DECODER_FIFO_ISEMPTY(p_spudec->fifo) )
196         {
197             input_NetlistFreePES( p_spudec->bit_stream.p_input, DECODER_FIFO_START(p_spudec->fifo) );
198             DECODER_FIFO_INCSTART( p_spudec->fifo );
199         }
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 );
202     }
203     vlc_mutex_unlock( &p_spudec->fifo.data_lock );
204
205     /*
206      * Error loop
207      */
208     if( p_spudec->b_error )
209     {
210         ErrorThread( p_spudec );
211     }
212
213     p_spudec->b_run = 0;
214
215     /* End of thread */
216     EndThread( p_spudec );
217 }
218
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
224  * possible.
225  *****************************************************************************/
226 static void ErrorThread( spudec_thread_t *p_spudec )
227 {
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 );
231
232     /* Wait until a `die' order is sent */
233     while( !p_spudec->b_die )
234     {
235         /* Trash all received PES packets */
236         while( !DECODER_FIFO_ISEMPTY(p_spudec->fifo) )
237         {
238             input_NetlistFreePES( p_spudec->bit_stream.p_input, DECODER_FIFO_START(p_spudec->fifo) );
239             DECODER_FIFO_INCSTART( p_spudec->fifo );
240         }
241
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 );
244     }
245
246     /* We can release the lock before leaving */
247     vlc_mutex_unlock( &p_spudec->fifo.data_lock );
248 }
249
250 /*****************************************************************************
251  * EndThread: thread destruction
252  *****************************************************************************
253  * This function is called when the thread ends after a sucessfull
254  * initialization.
255  *****************************************************************************/
256 static void EndThread( spudec_thread_t *p_spudec )
257 {
258     intf_DbgMsg( "spudec debug: destroying spu decoder thread %p\n", p_spudec );
259     free( p_spudec );
260     intf_DbgMsg( "spudec debug: spu decoder thread %p destroyed\n", p_spudec);
261 }