]> git.sesse.net Git - vlc/blob - src/video_decoder/video_decoder.c
* Fixed the BeOS compile typo.
[vlc] / src / video_decoder / video_decoder.c
1 /*****************************************************************************
2  * video_decoder.c : video decoder thread
3  *****************************************************************************
4  * Copyright (C) 1999, 2000 VideoLAN
5  * $Id: video_decoder.c,v 1.50 2001/05/30 17:03:12 sam Exp $
6  *
7  * Authors: Christophe Massiot <massiot@via.ecp.fr>
8  *          GaĆ«l Hendryckx <jimmy@via.ecp.fr>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  * 
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include "defs.h"
29
30 #include <unistd.h>                                              /* getpid() */
31
32 #include <stdlib.h>                                                /* free() */
33 #include <string.h>                                    /* memcpy(), memset() */
34 #include <errno.h>                                                  /* errno */
35
36 #include "config.h"
37 #include "common.h"
38 #include "threads.h"
39 #include "mtime.h"
40
41 #include "intf_msg.h"
42
43 #include "stream_control.h"
44 #include "input_ext-dec.h"
45
46 #include "video.h"
47 #include "video_output.h"
48
49 #include "vdec_motion.h"
50 #include "video_decoder.h"
51
52 #include "vpar_blocks.h"
53 #include "vpar_headers.h"
54 #include "vpar_synchro.h"
55 #include "video_parser.h"
56 #include "video_fifo.h"
57
58 /*
59  * Local prototypes
60  */
61 #ifdef VDEC_SMP
62 static int      vdec_InitThread     ( vdec_thread_t *p_vdec );
63 #endif
64 static void     RunThread           ( vdec_thread_t *p_vdec );
65 static void     ErrorThread         ( vdec_thread_t *p_vdec );
66 static void     EndThread           ( vdec_thread_t *p_vdec );
67
68 /*****************************************************************************
69  * vdec_CreateThread: create a video decoder thread
70  *****************************************************************************
71  * This function creates a new video decoder thread, and returns a pointer
72  * to its description. On error, it returns NULL.
73  * Following configuration properties are used:
74  * XXX??
75  *****************************************************************************/
76 vdec_thread_t * vdec_CreateThread( vpar_thread_t *p_vpar /*, int *pi_status */ )
77 {
78     vdec_thread_t *     p_vdec;
79
80     intf_DbgMsg("vdec debug: creating video decoder thread");
81
82     /* Allocate the memory needed to store the thread's structure */
83     if ( (p_vdec = (vdec_thread_t *)malloc( sizeof(vdec_thread_t) )) == NULL )
84     {
85         intf_ErrMsg("vdec error: not enough memory for vdec_CreateThread() to create the new thread");
86         return( NULL );
87     }
88
89     /*
90      * Initialize the thread properties
91      */
92     p_vdec->b_die = 0;
93     p_vdec->b_error = 0;
94
95     /*
96      * Initialize the parser properties
97      */
98     p_vdec->p_vpar = p_vpar;
99
100     /* Spawn the video decoder thread */
101     if ( vlc_thread_create(&p_vdec->thread_id, "video decoder",
102          (vlc_thread_func_t)RunThread, (void *)p_vdec) )
103     {
104         intf_ErrMsg("vdec error: can't spawn video decoder thread");
105         free( p_vdec );
106         return( NULL );
107     }
108
109     intf_DbgMsg("vdec debug: video decoder thread (%p) created", p_vdec);
110     return( p_vdec );
111 }
112
113 /*****************************************************************************
114  * vdec_DestroyThread: destroy a video decoder thread
115  *****************************************************************************
116  * Destroy and terminate thread. This function will return 0 if the thread could
117  * be destroyed, and non 0 else. The last case probably means that the thread
118  * was still active, and another try may succeed.
119  *****************************************************************************/
120 void vdec_DestroyThread( vdec_thread_t *p_vdec /*, int *pi_status */ )
121 {
122     intf_DbgMsg("vdec debug: requesting termination of video decoder thread %p", p_vdec);
123
124     /* Ask thread to kill itself */
125     p_vdec->b_die = 1;
126
127 #ifdef VDEC_SMP
128     /* Make sure the decoder thread leaves the vpar_GetMacroblock() function */
129     vlc_mutex_lock( &(p_vdec->p_vpar->vfifo.lock) );
130     vlc_cond_signal( &(p_vdec->p_vpar->vfifo.wait) );
131     vlc_mutex_unlock( &(p_vdec->p_vpar->vfifo.lock) );
132 #endif
133
134     /* Waiting for the decoder thread to exit */
135     /* Remove this as soon as the "status" flag is implemented */
136     vlc_thread_join( p_vdec->thread_id );
137 }
138
139 /* following functions are local */
140
141 /*****************************************************************************
142  * vdec_InitThread: initialize video decoder thread
143  *****************************************************************************
144  * This function is called from RunThread and performs the second step of the
145  * initialization. It returns 0 on success. Note that the thread's flag are not
146  * modified inside this function.
147  *****************************************************************************/
148 #ifdef VDEC_SMP
149 static int vdec_InitThread( vdec_thread_t *p_vdec )
150 #else
151 int vdec_InitThread( vdec_thread_t *p_vdec )
152 #endif
153 {
154     intf_DbgMsg("vdec debug: initializing video decoder thread %p", p_vdec);
155
156     p_vdec->pf_decode_init  = p_vdec->p_vpar->pf_decode_init;
157     p_vdec->pf_decode_mb_c  = p_vdec->p_vpar->pf_decode_mb_c;
158     p_vdec->pf_decode_mb_bw = p_vdec->p_vpar->pf_decode_mb_bw;
159
160     p_vdec->pf_decode_init( p_vdec );
161
162 #ifdef VDEC_SMP
163     /* Re-nice ourself */
164     if( nice(VDEC_NICE) == -1 )
165     {
166         intf_WarnMsg( 2, "vdec warning : couldn't nice() (%s)",
167                       strerror(errno) );
168     }
169 #endif
170
171     /* Mark thread as running and return */
172     intf_DbgMsg("vdec debug: InitThread(%p) succeeded", p_vdec);
173     return( 0 );
174 }
175
176 /*****************************************************************************
177  * ErrorThread: RunThread() error loop
178  *****************************************************************************
179  * This function is called when an error occured during thread main's loop. The
180  * thread can still receive feed, but must be ready to terminate as soon as
181  * possible.
182  *****************************************************************************/
183 static void ErrorThread( vdec_thread_t *p_vdec )
184 {
185     macroblock_t *       p_mb;
186
187     /* Wait until a `die' order */
188     while( !p_vdec->b_die )
189     {
190         p_mb = vpar_GetMacroblock( &p_vdec->p_vpar->vfifo );
191         vpar_DestroyMacroblock( &p_vdec->p_vpar->vfifo, p_mb );
192     }
193 }
194
195 /*****************************************************************************
196  * EndThread: thread destruction
197  *****************************************************************************
198  * This function is called when the thread ends after a sucessful
199  * initialization.
200  *****************************************************************************/
201 static void EndThread( vdec_thread_t *p_vdec )
202 {
203     intf_DbgMsg("vdec debug: EndThread(%p)", p_vdec);
204 }
205
206 /*****************************************************************************
207  * RunThread: video decoder thread
208  *****************************************************************************
209  * Video decoder thread. This function does only return when the thread is
210  * terminated.
211  *****************************************************************************/
212 static void RunThread( vdec_thread_t *p_vdec )
213 {
214     intf_DbgMsg("vdec debug: running video decoder thread (%p) (pid == %i)",
215                 p_vdec, getpid());
216
217     /*
218      * Initialize thread and free configuration
219      */
220     p_vdec->b_error = vdec_InitThread( p_vdec );
221     if( p_vdec->b_error )
222     {
223         return;
224     }
225     p_vdec->b_run = 1;
226
227     /*
228      * Main loop - it is not executed if an error occured during
229      * initialization
230      */
231     while( (!p_vdec->b_die) && (!p_vdec->b_error) )
232     {
233         macroblock_t *          p_mb;
234
235         if( (p_mb = vpar_GetMacroblock( &p_vdec->p_vpar->vfifo )) != NULL )
236         {
237             p_vdec->pf_decode_mb_c( p_vdec, p_mb );
238         }
239     }
240
241     /*
242      * Error loop
243      */
244     if( p_vdec->b_error )
245     {
246         ErrorThread( p_vdec );
247     }
248
249     /* End of thread */
250     EndThread( p_vdec );
251     p_vdec->b_run = 0;
252 }
253