]> git.sesse.net Git - vlc/blob - src/spu_decoder/spu_decoder.c
Encore un commit venu tout droit des abysses de l'enfer, d�sol� pour
[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 <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() */
34
35 #include "config.h"
36 #include "common.h"
37 #include "mtime.h"
38 #include "threads.h"
39
40 #include "intf_msg.h"
41 #include "debug.h"                                                 /* ASSERT */
42
43 #include "input.h"
44 #include "input_netlist.h"
45 #include "decoder_fifo.h"
46
47 #include "spu_decoder.h"
48
49 /*
50  * Local prototypes
51  */
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 );
56
57 /*****************************************************************************
58  * spudec_CreateThread: create a spu decoder thread
59  *****************************************************************************/
60 spudec_thread_t * spudec_CreateThread( input_thread_t * p_input )
61 {
62     spudec_thread_t *     p_spudec;
63
64     intf_DbgMsg("spudec debug: creating spu decoder thread\n");
65
66     /* Allocate the memory needed to store the thread's structure */
67     if ( (p_spudec = (spudec_thread_t *)malloc( sizeof(spudec_thread_t) )) == NULL )
68     {
69         intf_ErrMsg("spudec error: not enough memory for spudec_CreateThread() to create the new thread\n");
70         return( NULL );
71     }
72
73     /*
74      * Initialize the thread properties
75      */
76     p_spudec->b_die = 0;
77     p_spudec->b_error = 0;
78
79     /*
80      * Initialize the input properties
81      */
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;
93
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) )
97     {
98         intf_ErrMsg("spudec error: can't spawn spu decoder thread\n");
99         free( p_spudec );
100         return( NULL );
101     }
102
103     intf_DbgMsg("spudec debug: spu decoder thread (%p) created\n", p_spudec);
104     return( p_spudec );
105 }
106
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 )
115 {
116     intf_DbgMsg("spudec debug: requesting termination of spu decoder thread %p\n", p_spudec);
117
118     /* Ask thread to kill itself */
119     p_spudec->b_die = 1;
120
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 );
125
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 );
129 }
130
131 /* following functions are local */
132
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 )
141 {
142     intf_DbgMsg("spudec debug: initializing spu decoder thread %p\n", p_spudec);
143
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) )
148     {
149         if ( p_spudec->b_die )
150         {
151             vlc_mutex_unlock( &p_spudec->fifo.data_lock );
152             return( 1 );
153         }
154         vlc_cond_wait( &p_spudec->fifo.data_wait, &p_spudec->fifo.data_lock );
155     }
156
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 );
161
162     /* Mark thread as running and return */
163     intf_DbgMsg( "spudec debug: InitThread(%p) succeeded\n", p_spudec );
164     return( 0 );
165 }
166
167 /*****************************************************************************
168  * RunThread: spu decoder thread
169  *****************************************************************************
170  * spu decoder thread. This function does only return when the thread is
171  * terminated.
172  *****************************************************************************/
173 static void RunThread( spudec_thread_t *p_spudec )
174 {
175     intf_DbgMsg("spudec debug: running spu decoder thread (%p) (pid == %i)\n",
176         p_spudec, getpid());
177
178     /*
179      * Initialize thread and free configuration
180      */
181     p_spudec->b_error = InitThread( p_spudec );
182
183     p_spudec->b_run = 1;
184
185     /*
186      * Main loop - it is not executed if an error occured during
187      * initialization
188      */
189     vlc_mutex_lock( &p_spudec->fifo.data_lock );
190     while( (!p_spudec->b_die) && (!p_spudec->b_error) )
191     {
192         /* Trash all received PES packets */
193         while( !DECODER_FIFO_ISEMPTY(p_spudec->fifo) )
194         {
195             input_NetlistFreePES( p_spudec->bit_stream.p_input, DECODER_FIFO_START(p_spudec->fifo) );
196             DECODER_FIFO_INCSTART( p_spudec->fifo );
197         }
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 );
200     }
201     vlc_mutex_unlock( &p_spudec->fifo.data_lock );
202
203     /*
204      * Error loop
205      */
206     if( p_spudec->b_error )
207     {
208         ErrorThread( p_spudec );
209     }
210
211     p_spudec->b_run = 0;
212
213     /* End of thread */
214     EndThread( p_spudec );
215 }
216
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
222  * possible.
223  *****************************************************************************/
224 static void ErrorThread( spudec_thread_t *p_spudec )
225 {
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 );
229
230     /* Wait until a `die' order is sent */
231     while( !p_spudec->b_die )
232     {
233         /* Trash all received PES packets */
234         while( !DECODER_FIFO_ISEMPTY(p_spudec->fifo) )
235         {
236             input_NetlistFreePES( p_spudec->bit_stream.p_input, DECODER_FIFO_START(p_spudec->fifo) );
237             DECODER_FIFO_INCSTART( p_spudec->fifo );
238         }
239
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 );
242     }
243
244     /* We can release the lock before leaving */
245     vlc_mutex_unlock( &p_spudec->fifo.data_lock );
246 }
247
248 /*****************************************************************************
249  * EndThread: thread destruction
250  *****************************************************************************
251  * This function is called when the thread ends after a sucessfull
252  * initialization.
253  *****************************************************************************/
254 static void EndThread( spudec_thread_t *p_spudec )
255 {
256     intf_DbgMsg( "spudec debug: destroying spu decoder thread %p\n", p_spudec );
257     free( p_spudec );
258     intf_DbgMsg( "spudec debug: spu decoder thread %p destroyed\n", p_spudec);
259 }