]> git.sesse.net Git - vlc/blob - src/video_parser/video_parser.c
More stats.
[vlc] / src / video_parser / video_parser.c
1 /*****************************************************************************
2  * video_parser.c : video parser thread
3  *****************************************************************************
4  * Copyright (C) 1999, 2000 VideoLAN
5  *
6  * Authors: Christophe Massiot <massiot@via.ecp.fr>
7  *          Samuel Hocevar <sam@via.ecp.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  * 
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /* FIXME: passer en terminate/destroy avec les signaux supplĂ©mentaires ?? */
25
26 /*****************************************************************************
27  * Preamble
28  *****************************************************************************/
29 #include "defs.h"
30
31 #include <stdlib.h>                                      /* malloc(), free() */
32 #include <unistd.h>                                              /* getpid() */
33 #include <sys/types.h>                        /* on BSD, uio.h needs types.h */
34 #include <sys/uio.h>                                            /* "input.h" */
35 #include <errno.h>
36 #include <string.h>
37
38 #include "config.h"
39 #include "common.h"
40 #include "threads.h"
41 #include "mtime.h"
42 #include "plugins.h"
43
44 #include "intf_msg.h"
45 #include "debug.h"                 /* XXX?? temporaire, requis par netlist.h */
46
47 #include "input.h"
48 #include "input_netlist.h"
49 #include "decoder_fifo.h"
50 #include "video.h"
51 #include "video_output.h"
52
53 #include "vdec_idct.h"
54 #include "video_decoder.h"
55 #include "vdec_motion.h"
56
57 #include "vpar_blocks.h"
58 #include "vpar_headers.h"
59 #include "vpar_synchro.h"
60 #include "video_parser.h"
61 #include "video_fifo.h"
62
63 /*
64  * Local prototypes
65  */
66 //static int      CheckConfiguration  ( video_cfg_t *p_cfg );
67 static int      InitThread          ( vpar_thread_t *p_vpar );
68 static void     RunThread           ( vpar_thread_t *p_vpar );
69 static void     ErrorThread         ( vpar_thread_t *p_vpar );
70 static void     EndThread           ( vpar_thread_t *p_vpar );
71
72 /*****************************************************************************
73  * vpar_CreateThread: create a generic parser thread
74  *****************************************************************************
75  * This function creates a new video parser thread, and returns a pointer
76  * to its description. On error, it returns NULL.
77  * Following configuration properties are used:
78  * XXX??
79  *****************************************************************************/
80 #include "main.h"
81 #include "interface.h"
82 extern main_t *     p_main;
83
84 vpar_thread_t * vpar_CreateThread( /* video_cfg_t *p_cfg, */ input_thread_t *p_input /*,
85                                    vout_thread_t *p_vout, int *pi_status */ )
86 {
87     vpar_thread_t *     p_vpar;
88
89     intf_DbgMsg( "vpar debug: creating video parser thread\n" );
90
91     /* Allocate the memory needed to store the thread's structure */
92     if ( (p_vpar = (vpar_thread_t *)malloc( sizeof(vpar_thread_t) )) == NULL )
93     {
94         intf_ErrMsg( "vpar error: not enough memory "
95                      "for vpar_CreateThread() to create the new thread\n");
96         return( NULL );
97     }
98
99     /*
100      * Initialize the thread properties
101      */
102     p_vpar->b_die = 0;
103     p_vpar->b_error = 0;
104
105     /*
106      * Initialize the input properties
107      */
108     /* Initialize the decoder fifo's data lock and conditional variable
109      * and set its buffer as empty */
110     vlc_mutex_init( &p_vpar->fifo.data_lock );
111     vlc_cond_init( &p_vpar->fifo.data_wait );
112     p_vpar->fifo.i_start = 0;
113     p_vpar->fifo.i_end = 0;
114     /* Initialize the bit stream structure */
115     p_vpar->bit_stream.p_input = p_input;
116     p_vpar->bit_stream.p_decoder_fifo = &p_vpar->fifo;
117     p_vpar->bit_stream.fifo.buffer = 0;
118     p_vpar->bit_stream.fifo.i_available = 0;
119
120     /* FIXME !!!!?? */
121     p_vpar->p_vout = p_main->p_intf->p_vout;
122
123     /* Spawn the video parser thread */
124     if ( vlc_thread_create( &p_vpar->thread_id, "video parser",
125                             (vlc_thread_func_t)RunThread, (void *)p_vpar ) )
126     {
127         intf_ErrMsg("vpar error: can't spawn video parser thread\n");
128         free( p_vpar );
129         return( NULL );
130     }
131
132     intf_DbgMsg("vpar debug: video parser thread (%p) created\n", p_vpar);
133     return( p_vpar );
134 }
135
136 /*****************************************************************************
137  * vpar_DestroyThread: destroy a generic parser thread
138  *****************************************************************************
139  * Destroy a terminated thread. This function will return 0 if the thread could
140  * be destroyed, and non 0 else. The last case probably means that the thread
141  * was still active, and another try may succeed.
142  *****************************************************************************/
143 void vpar_DestroyThread( vpar_thread_t *p_vpar /*, int *pi_status */ )
144 {
145     intf_DbgMsg( "vpar debug: requesting termination of "
146                  "video parser thread %p\n", p_vpar);
147
148     /* Ask thread to kill itself */
149     p_vpar->b_die = 1;
150     /* Make sure the parser thread leaves the GetByte() function */
151     vlc_mutex_lock( &(p_vpar->fifo.data_lock) );
152     vlc_cond_signal( &(p_vpar->fifo.data_wait) );
153     vlc_mutex_unlock( &(p_vpar->fifo.data_lock) );
154
155     /* Waiting for the parser thread to exit */
156     /* Remove this as soon as the "status" flag is implemented */
157     vlc_thread_join( p_vpar->thread_id );
158 }
159
160 /* following functions are local */
161
162 /*****************************************************************************
163  * CheckConfiguration: check vpar_CreateThread() configuration
164  *****************************************************************************
165  * Set default parameters where required. In DEBUG mode, check if configuration
166  * is valid.
167  *****************************************************************************/
168 #if 0
169 static int CheckConfiguration( video_cfg_t *p_cfg )
170 {
171     /* XXX?? */
172
173     return( 0 );
174 }
175 #endif
176
177 /*****************************************************************************
178  * InitThread: initialize vpar output thread
179  *****************************************************************************
180  * This function is called from RunThread and performs the second step of the
181  * initialization. It returns 0 on success. Note that the thread's flag are not
182  * modified inside this function.
183  *****************************************************************************/
184 static int InitThread( vpar_thread_t *p_vpar )
185 {
186 #ifdef VDEC_SMP
187     int i_dummy;
188 #endif
189
190     intf_DbgMsg("vpar debug: initializing video parser thread %p\n", p_vpar);
191
192     /* Our first job is to initialize the bit stream structure with the
193      * beginning of the input stream */
194     vlc_mutex_lock( &p_vpar->fifo.data_lock );
195     while ( DECODER_FIFO_ISEMPTY(p_vpar->fifo) )
196     {
197         if ( p_vpar->b_die )
198         {
199             vlc_mutex_unlock( &p_vpar->fifo.data_lock );
200             return( 1 );
201         }
202         vlc_cond_wait( &p_vpar->fifo.data_wait, &p_vpar->fifo.data_lock );
203     }
204     p_vpar->bit_stream.p_ts = DECODER_FIFO_START( p_vpar->fifo )->p_first_ts;
205     p_vpar->bit_stream.p_byte = p_vpar->bit_stream.p_ts->buffer
206                                 + p_vpar->bit_stream.p_ts->i_payload_start;
207     p_vpar->bit_stream.p_end = p_vpar->bit_stream.p_ts->buffer
208                                + p_vpar->bit_stream.p_ts->i_payload_end;
209     vlc_mutex_unlock( &p_vpar->fifo.data_lock );
210
211     /* Initialize parsing data */
212     p_vpar->sequence.p_forward = NULL;
213     p_vpar->sequence.p_backward = NULL;
214     p_vpar->sequence.intra_quant.b_allocated = 0;
215     p_vpar->sequence.nonintra_quant.b_allocated = 0;
216     p_vpar->sequence.chroma_intra_quant.b_allocated = 0;
217     p_vpar->sequence.chroma_nonintra_quant.b_allocated = 0;
218
219     /* Initialize copyright information */
220     p_vpar->sequence.b_copyright_flag = 0;
221     p_vpar->sequence.b_original = 0;
222     p_vpar->sequence.i_copyright_id = 0;
223     p_vpar->sequence.i_copyright_nb = 0;
224
225     p_vpar->picture.p_picture = NULL;
226     p_vpar->picture.i_current_structure = 0;
227
228     /* Initialize other properties */
229 #ifdef STATS
230     p_vpar->c_loops = 0;
231     p_vpar->c_sequences = 0;
232     memset(p_vpar->pc_pictures, 0, sizeof(p_vpar->pc_pictures));
233     memset(p_vpar->pc_decoded_pictures, 0, sizeof(p_vpar->pc_decoded_pictures));
234     memset(p_vpar->pc_malformed_pictures, 0,
235            sizeof(p_vpar->pc_malformed_pictures));
236 #endif
237
238     /* Initialize video FIFO */
239     vpar_InitFIFO( p_vpar );
240
241     memset( p_vpar->pp_vdec, 0, NB_VDEC*sizeof(vdec_thread_t *) );
242
243 #ifdef VDEC_SMP
244     /* Spawn video_decoder threads */
245     /* FIXME: modify the number of vdecs at runtime ?? */
246     for( i_dummy = 0; i_dummy < NB_VDEC; i_dummy++ )
247     {
248         if( (p_vpar->pp_vdec[i_dummy] = vdec_CreateThread( p_vpar )) == NULL )
249         {
250             return( 1 );
251         }
252     }
253 #else
254     /* Fake a video_decoder thread */
255     if( (p_vpar->pp_vdec[0] = (vdec_thread_t *)malloc(sizeof( vdec_thread_t )))
256          == NULL || vdec_InitThread( p_vpar->pp_vdec[0] ) )
257     {
258         return( 1 );
259     }
260     p_vpar->pp_vdec[0]->b_die = 0;
261     p_vpar->pp_vdec[0]->b_error = 0;
262     p_vpar->pp_vdec[0]->p_vpar = p_vpar;
263
264     /* Re-nice ourself */
265     if( nice(VDEC_NICE) == -1 )
266     {
267         intf_WarnMsg( 2, "vpar warning : couldn't nice() (%s)\n",
268                       strerror(errno) );
269     }
270 #endif
271
272     /* Initialize lookup tables */
273 #if defined(MPEG2_COMPLIANT) && !defined(VDEC_DFT)
274     vpar_InitCrop( p_vpar );
275 #endif
276     vpar_InitMbAddrInc( p_vpar );
277     vpar_InitDCTTables( p_vpar );
278     vpar_InitPMBType( p_vpar );
279     vpar_InitBMBType( p_vpar );
280     vpar_InitDCTTables( p_vpar );
281
282     /*
283      * Initialize the synchro properties
284      */
285     vpar_SynchroInit( p_vpar );
286
287     /* Mark thread as running and return */
288     intf_DbgMsg("vpar debug: InitThread(%p) succeeded\n", p_vpar);
289     return( 0 );
290 }
291
292 /*****************************************************************************
293  * RunThread: generic parser thread
294  *****************************************************************************
295  * Video parser thread. This function only returns when the thread is
296  * terminated.
297  *****************************************************************************/
298 static void RunThread( vpar_thread_t *p_vpar )
299 {
300     intf_DbgMsg("vpar debug: running video parser thread (%p) (pid == %i)\n", p_vpar, getpid());
301
302     /*
303      * Initialize thread
304      */
305     p_vpar->b_error = InitThread( p_vpar );
306
307     p_vpar->b_run = 1;
308
309     /*
310      * Main loop - it is not executed if an error occured during
311      * initialization
312      */
313     while( (!p_vpar->b_die) && (!p_vpar->b_error) )
314     {
315         /* Find the next sequence header in the stream */
316         p_vpar->b_error = vpar_NextSequenceHeader( p_vpar );
317
318         while( (!p_vpar->b_die) && (!p_vpar->b_error) )
319         {
320 #ifdef STATS
321             p_vpar->c_loops++;
322 #endif
323             /* Parse the next sequence, group or picture header */
324             if( vpar_ParseHeader( p_vpar ) )
325             {
326                 /* End of sequence */
327                 break;
328             };
329         }
330     }
331
332     /*
333      * Error loop
334      */
335     if( p_vpar->b_error )
336     {
337         ErrorThread( p_vpar );
338     }
339
340     p_vpar->b_run = 0;
341
342     /* End of thread */
343     EndThread( p_vpar );
344 }
345
346 /*****************************************************************************
347  * ErrorThread: RunThread() error loop
348  *****************************************************************************
349  * This function is called when an error occured during thread main's loop. The
350  * thread can still receive feed, but must be ready to terminate as soon as
351  * possible.
352  *****************************************************************************/
353 static void ErrorThread( vpar_thread_t *p_vpar )
354 {
355     /* We take the lock, because we are going to read/write the start/end
356      * indexes of the decoder fifo */
357     vlc_mutex_lock( &p_vpar->fifo.data_lock );
358
359     /* Wait until a `die' order is sent */
360     while( !p_vpar->b_die )
361     {
362         /* Trash all received PES packets */
363         while( !DECODER_FIFO_ISEMPTY(p_vpar->fifo) )
364         {
365             input_NetlistFreePES( p_vpar->bit_stream.p_input,
366                                   DECODER_FIFO_START(p_vpar->fifo) );
367             DECODER_FIFO_INCSTART( p_vpar->fifo );
368         }
369
370         /* Waiting for the input thread to put new PES packets in the fifo */
371         vlc_cond_wait( &p_vpar->fifo.data_wait, &p_vpar->fifo.data_lock );
372     }
373
374     /* We can release the lock before leaving */
375     vlc_mutex_unlock( &p_vpar->fifo.data_lock );
376 }
377
378 /*****************************************************************************
379  * EndThread: thread destruction
380  *****************************************************************************
381  * This function is called when the thread ends after a sucessful
382  * initialization.
383  *****************************************************************************/
384 static void EndThread( vpar_thread_t *p_vpar )
385 {
386 #ifdef VDEC_SMP
387     int i_dummy;
388 #endif
389
390     intf_DbgMsg("vpar debug: destroying video parser thread %p\n", p_vpar);
391
392 #ifdef DEBUG
393     /* Check for remaining PES packets */
394     /* XXX?? */
395 #endif
396
397 #ifdef STATS
398     intf_Msg("vpar stats: %d loops among %d sequence(s)\n",
399              p_vpar->c_loops, p_vpar->c_sequences);
400     intf_Msg("vpar stats: Read %d frames/fields (I %d/P %d/B %d)\n",
401              p_vpar->pc_pictures[I_CODING_TYPE]
402              + p_vpar->pc_pictures[P_CODING_TYPE]
403              + p_vpar->pc_pictures[B_CODING_TYPE],
404              p_vpar->pc_pictures[I_CODING_TYPE],
405              p_vpar->pc_pictures[P_CODING_TYPE],
406              p_vpar->pc_pictures[B_CODING_TYPE]);
407     intf_Msg("vpar stats: Decoded %d frames/fields (I %d/P %d/B %d)\n",
408              p_vpar->pc_decoded_pictures[I_CODING_TYPE]
409              + p_vpar->pc_decoded_pictures[P_CODING_TYPE]
410              + p_vpar->pc_decoded_pictures[B_CODING_TYPE],
411              p_vpar->pc_decoded_pictures[I_CODING_TYPE],
412              p_vpar->pc_decoded_pictures[P_CODING_TYPE],
413              p_vpar->pc_decoded_pictures[B_CODING_TYPE]);
414     intf_Msg("vpar stats: Read %d malformed frames/fields (I %d/P %d/B %d)\n",
415              p_vpar->pc_malformed_pictures[I_CODING_TYPE]
416              + p_vpar->pc_malformed_pictures[P_CODING_TYPE]
417              + p_vpar->pc_malformed_pictures[B_CODING_TYPE],
418              p_vpar->pc_malformed_pictures[I_CODING_TYPE],
419              p_vpar->pc_malformed_pictures[P_CODING_TYPE],
420              p_vpar->pc_malformed_pictures[B_CODING_TYPE]);
421 #define S   p_vpar->sequence
422     intf_Msg("vpar info: %s stream (%dx%d), %d/1001 pi/s\n",
423              S.b_mpeg2 ? "MPEG-2" : "MPEG-1",
424              S.i_width, S.i_height, S.i_frame_rate);
425     intf_Msg("vpar info: %s, %s, matrix_coeff: %d\n",
426              S.b_progressive ? "Progressive" : "Non-progressive",
427              S.i_scalable_mode ? "scalable" : "non-scalable",
428              S.i_matrix_coefficients);
429 #endif
430
431     /* Destroy thread structures allocated by InitThread */
432 //    vout_DestroyStream( p_vpar->p_vout, p_vpar->i_stream );
433     /* XXX?? */
434
435     /* Dispose of matrices if they have been allocated. */
436     if( p_vpar->sequence.intra_quant.b_allocated )
437     {
438         free( p_vpar->sequence.intra_quant.pi_matrix );
439     }
440     if( p_vpar->sequence.nonintra_quant.b_allocated )
441     {
442         free( p_vpar->sequence.nonintra_quant.pi_matrix) ;
443     }
444     if( p_vpar->sequence.chroma_intra_quant.b_allocated )
445     {
446         free( p_vpar->sequence.chroma_intra_quant.pi_matrix );
447     }
448     if( p_vpar->sequence.chroma_nonintra_quant.b_allocated )
449     {
450         free( p_vpar->sequence.chroma_nonintra_quant.pi_matrix );
451     }
452
453 #ifdef VDEC_SMP
454     /* Destroy vdec threads */
455     for( i_dummy = 0; i_dummy < NB_VDEC; i_dummy++ )
456     {
457         if( p_vpar->pp_vdec[i_dummy] != NULL )
458             vdec_DestroyThread( p_vpar->pp_vdec[i_dummy] );
459         else
460             break;
461     }
462 #else
463     free( p_vpar->pp_vdec[0] );
464 #endif
465
466     free( p_vpar );
467
468     intf_DbgMsg("vpar debug: EndThread(%p)\n", p_vpar);
469 }