]> git.sesse.net Git - vlc/blob - src/video_decoder/video_decoder.c
A tout kass�.
[vlc] / src / video_decoder / video_decoder.c
1 /*******************************************************************************
2  * video_decoder.c : video decoder thread
3  * (c)1999 VideoLAN
4  *******************************************************************************/
5
6 /* ?? passer en terminate/destroy avec les signaux supplémentaires */
7
8 /*******************************************************************************
9  * Preamble
10  *******************************************************************************/
11 #include "vlc.h"
12
13 /*#include <errno.h>
14 #include <pthread.h>
15 #include <errno.h>
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <unistd.h>
19 #include <string.h>
20 #include <sys/uio.h>
21 #include <X11/Xlib.h>
22 #include <X11/extensions/XShm.h>
23
24 #include "config.h"
25 #include "common.h"
26 #include "mtime.h"
27 #include "vlc_thread.h"
28
29 #include "intf_msg.h"
30 #include "debug.h"                    
31
32 #include "input.h"
33 #include "input_netlist.h"
34 #include "decoder_fifo.h"
35 #include "video.h"
36 #include "video_output.h"
37 #include "video_decoder.h"*/
38
39
40 #include "vdec_idct.h"
41 #include "video_decoder.h"
42 #include "vdec_motion.h"
43
44 #include "vpar_blocks.h"
45 #include "vpar_headers.h"
46 #include "video_fifo.h"
47 #include "vpar_synchro.h"
48 #include "video_parser.h"
49
50 /*
51  * Local prototypes
52  */
53 static int      InitThread          ( vdec_thread_t *p_vdec );
54 static void     RunThread           ( vdec_thread_t *p_vdec );
55 static void     ErrorThread         ( vdec_thread_t *p_vdec );
56 static void     EndThread           ( vdec_thread_t *p_vdec );
57 static void     DecodeMacroblock    ( vdec_thread_t *p_vdec,
58                                       macroblock_t * p_mb );
59
60 /*******************************************************************************
61  * vdec_CreateThread: create a video decoder thread
62  *******************************************************************************
63  * This function creates a new video decoder thread, and returns a pointer
64  * to its description. On error, it returns NULL.
65  * Following configuration properties are used:
66  * ??
67  *******************************************************************************/
68 vdec_thread_t * vdec_CreateThread( vpar_thread_t *p_vpar /*, int *pi_status */ )
69 {
70     vdec_thread_t *     p_vdec;
71
72     intf_DbgMsg("vdec debug: creating video decoder thread\n");
73
74     /* Allocate the memory needed to store the thread's structure */
75     if ( (p_vdec = (vdec_thread_t *)malloc( sizeof(vdec_thread_t) )) == NULL )
76     {
77         intf_ErrMsg("vdec error: not enough memory for vdec_CreateThread() to create the new thread\n");
78         return( NULL );
79     }
80
81     /*
82      * Initialize the thread properties
83      */
84     p_vdec->b_die = 0;
85     p_vdec->b_error = 0;
86
87     /*
88      * Initialize the parser properties
89      */
90     p_vdec->p_vpar = p_vpar;
91
92     /* Spawn the video decoder thread */
93     if ( vlc_thread_create(&p_vdec->thread_id, "video decoder",
94          (vlc_thread_func)RunThread, (void *)p_vdec) )
95     {
96         intf_ErrMsg("vdec error: can't spawn video decoder thread\n");
97         free( p_vdec );
98         return( NULL );
99     }
100
101     intf_DbgMsg("vdec debug: video decoder thread (%p) created\n", p_vdec);
102     return( p_vdec );
103 }
104
105 /*******************************************************************************
106  * vdec_DestroyThread: destroy a video decoder thread
107  *******************************************************************************
108  * Destroy and terminate thread. This function will return 0 if the thread could
109  * be destroyed, and non 0 else. The last case probably means that the thread
110  * was still active, and another try may succeed.
111  *******************************************************************************/
112 void vdec_DestroyThread( vdec_thread_t *p_vdec /*, int *pi_status */ )
113 {
114     intf_DbgMsg("vdec debug: requesting termination of video decoder thread %p\n", p_vdec);
115
116     /* Ask thread to kill itself */
117     p_vdec->b_die = 1;
118
119     /* Waiting for the decoder thread to exit */
120     /* Remove this as soon as the "status" flag is implemented */
121     vlc_thread_join( p_vdec->thread_id );
122 }
123
124 /* following functions are local */
125
126 /*******************************************************************************
127  * InitThread: initialize video decoder thread
128  *******************************************************************************
129  * This function is called from RunThread and performs the second step of the
130  * initialization. It returns 0 on success. Note that the thread's flag are not
131  * modified inside this function.
132  *******************************************************************************/
133 static int InitThread( vdec_thread_t *p_vdec )
134 {
135 #ifdef MPEG2_COMPLIANT
136     int i_dummy;
137 #endif
138
139     intf_DbgMsg("vdec debug: initializing video decoder thread %p\n", p_vdec);
140
141     /* Initialize other properties */
142 #ifdef STATS
143     p_vdec->c_loops = 0;    
144     p_vdec->c_idle_loops = 0;
145     p_vdec->c_decoded_pictures = 0;
146     p_vdec->c_decoded_i_pictures = 0;
147     p_vdec->c_decoded_p_pictures = 0;
148     p_vdec->c_decoded_b_pictures = 0;
149 #endif
150
151 #ifdef MPEG2_COMPLIANT
152     /* Init crop table */
153     p_vdec->pi_crop = p_vdec->pi_crop_buf + (VDEC_CROPRANGE >> 1);
154     for( i_dummy = -VDEC_CROPRANGE; i_dummy < -256; i_dummy ++ )
155     {
156         p_vdec->pi_crop[i_dummy] = -256;
157     }
158     for( ; i_dummy < 255; i_dummy ++ )
159     {
160         p_vdec->pi_crop[i_dummy] = i_dummy;
161     }
162     for( ; i_dummy < (VDEC_CROPRANGE >> 1) -1; i_dummy++ )
163     {
164         p_vdec->pi_crop[i_dummy] = 255;
165     }
166 #endif
167
168     /* Mark thread as running and return */
169     intf_DbgMsg("vdec debug: InitThread(%p) succeeded\n", p_vdec);    
170     return( 0 );    
171 }
172
173 /*******************************************************************************
174  * RunThread: video decoder thread
175  *******************************************************************************
176  * Video decoder thread. This function does only return when the thread is
177  * terminated. 
178  *******************************************************************************/
179 static void RunThread( vdec_thread_t *p_vdec )
180 {
181     intf_DbgMsg("vdec debug: running video decoder thread (%p) (pid == %i)\n",
182                 p_vdec, getpid());
183
184     /* 
185      * Initialize thread and free configuration 
186      */
187     p_vdec->b_error = InitThread( p_vdec );
188     if( p_vdec->b_error )
189     {
190         return;
191     }
192     p_vdec->b_run = 1;
193
194     /*
195      * Main loop - it is not executed if an error occured during
196      * initialization
197      */
198     while( (!p_vdec->b_die) && (!p_vdec->b_error) )
199     {
200         macroblock_t *          p_mb;
201         
202         if( (p_mb = vpar_GetMacroblock( &p_vdec->p_vpar->vfifo )) != NULL )
203         {
204             DecodeMacroblock( p_vdec, p_mb );
205         }
206     } 
207
208     /*
209      * Error loop
210      */
211     if( p_vdec->b_error )
212     {
213         ErrorThread( p_vdec );        
214     }
215
216     /* End of thread */
217     EndThread( p_vdec );
218     p_vdec->b_run = 0;
219 }
220
221 /*******************************************************************************
222  * ErrorThread: RunThread() error loop
223  *******************************************************************************
224  * This function is called when an error occured during thread main's loop. The
225  * thread can still receive feed, but must be ready to terminate as soon as
226  * possible.
227  *******************************************************************************/
228 static void ErrorThread( vdec_thread_t *p_vdec )
229 {
230     macroblock_t *       p_mb;
231
232     /* Wait until a `die' order */
233     while( !p_vdec->b_die )
234     {
235         p_mb = vpar_GetMacroblock( &p_vdec->p_vpar->vfifo );
236         vpar_DestroyMacroblock( &p_vdec->p_vpar->vfifo, p_mb );
237
238         /* Sleep a while */
239         msleep( VDEC_IDLE_SLEEP );                
240     }
241 }
242
243 /*******************************************************************************
244  * EndThread: thread destruction
245  *******************************************************************************
246  * This function is called when the thread ends after a sucessfull 
247  * initialization.
248  *******************************************************************************/
249 static void EndThread( vdec_thread_t *p_vdec )
250 {
251     intf_DbgMsg("vdec debug: EndThread(%p)\n", p_vdec);
252 }
253
254 /*******************************************************************************
255  * DecodeMacroblock : decode a macroblock of a picture
256  *******************************************************************************/
257 static void DecodeMacroblock( vdec_thread_t *p_vdec, macroblock_t * p_mb )
258 {
259     int             i_b;
260
261     /*
262      * Motion Compensation (ISO/IEC 13818-2 section 7.6)
263      */
264     (*p_mb->pf_motion)( p_mb );
265
266     /* luminance */
267     for( i_b = 0; i_b < 4; i_b++ )
268     {
269         /*
270          * Inverse DCT (ISO/IEC 13818-2 section Annex A)
271          */
272         (p_mb->pf_idct[i_b])( p_vdec, p_mb->ppi_blocks[i_b],
273                               p_mb->pi_sparse_pos[i_b] );
274
275         /*
276          * Adding prediction and coefficient data (ISO/IEC 13818-2 section 7.6.8)
277          */
278         (p_mb->pf_addb[i_b])( p_mb->ppi_blocks[i_b],
279                                p_mb->p_data[i_b], p_mb->i_l_stride );
280     }
281
282     /* chrominance */
283     for( i_b = 4; i_b < 4 + 2*p_mb->i_chroma_nb_blocks; i_b++ )
284     {
285         /*
286          * Inverse DCT (ISO/IEC 13818-2 section Annex A)
287          */
288         (p_mb->pf_idct[i_b])( p_vdec, p_mb->ppi_blocks[i_b],
289                               p_mb->pi_sparse_pos[i_b] );
290
291         /*
292          * Adding prediction and coefficient data (ISO/IEC 13818-2 section 7.6.8)
293          */
294         (p_mb->pf_addb[i_b])( p_mb->ppi_blocks[i_b],
295                                p_mb->p_data[i_b], p_mb->i_c_stride );
296     }
297
298     /*
299      * Decoding is finished, release the macroblock and free
300      * unneeded memory.
301      */
302     vpar_ReleaseMacroblock( &p_vdec->p_vpar->vfifo, p_mb );
303 }
304
305 /*******************************************************************************
306  * vdec_AddBlock : add a block
307  *******************************************************************************/
308 void vdec_AddBlock( vdec_thread_t * p_vdec, elem_t * p_block, data_t * p_data,
309                     int i_incr )
310 {
311     int i_x, i_y;
312     
313     for( i_y = 0; i_y < 8; i_y++ )
314     {
315         for( i_x = 0; i_x < 8; i_x++ )
316         {
317 #ifdef MPEG2_COMPLIANT
318             *p_data = p_vdec->pi_clip[*p_data + *p_block++];
319             p_data++;
320 #else
321             *p_data++ += *p_block++;
322 #endif
323         }
324         p_data += i_incr;
325     }
326 }
327
328 /*******************************************************************************
329  * vdec_CopyBlock : copy a block
330  *******************************************************************************/
331 void vdec_CopyBlock( vdec_thread_t * p_vdec, elem_t * p_block, data_t * p_data,
332                      int i_incr )
333 {
334     int i_x, i_y;
335     
336     for( i_y = 0; i_y < 8; i_y++ )
337     {
338 #ifndef VDEC_DFT
339         /* elem_t and data_t are the same */
340         memcopy( p_data, p_block, 8*sizeof(data_t) );
341         p_data += i_incr+8;
342         p_block += 8;
343 #else
344         for( i_x = 0; i_x < 8; i_x++ )
345         {
346             /* ??? Need clip to be MPEG-2 compliant */
347             /* ??? Why does the reference decoder add 128 ??? */
348             *p_data++ = *p_block++;
349         }
350         p_data += i_incr;
351 #endif
352     }
353 }
354
355 /*******************************************************************************
356  * vdec_DummyBlock : dummy function that does nothing
357  *******************************************************************************/
358 void vdec_DummyBlock( vdec_thread_t * p_vdec, elem_t * p_block, data_t * p_data,
359                       int i_incr )
360 {
361 }