]> git.sesse.net Git - vlc/blob - plugins/mpeg_vdec/video_parser.c
ac307c25adf48a457c9cb7b1da996b8d0e24d3dc
[vlc] / plugins / mpeg_vdec / video_parser.c
1 /*****************************************************************************
2  * video_parser.c : video parser thread
3  *****************************************************************************
4  * Copyright (C) 1999-2001 VideoLAN
5  * $Id: video_parser.c,v 1.20 2002/05/19 12:57:32 gbazin Exp $
6  *
7  * Authors: Christophe Massiot <massiot@via.ecp.fr>
8  *          Samuel Hocevar <sam@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 <stdlib.h>                                      /* malloc(), free() */
29
30 #include <videolan/vlc.h>
31
32 #ifdef HAVE_UNISTD_H
33 #include <unistd.h>                                              /* getpid() */
34 #endif
35
36 #include <errno.h>
37 #include <string.h>
38
39 #ifdef HAVE_SYS_TIMES_H
40 #   include <sys/times.h>
41 #endif
42
43 #include "video.h"
44 #include "video_output.h"
45
46 #include "stream_control.h"
47 #include "input_ext-dec.h"
48
49 #include "vdec_ext-plugins.h"
50 #include "vpar_pool.h"
51 #include "video_parser.h"
52
53 /*
54  * Local prototypes
55  */
56 static int      decoder_Probe     ( u8 * );
57 static int      decoder_Run       ( decoder_config_t * );
58 static int      InitThread        ( vpar_thread_t * );
59 static void     EndThread         ( vpar_thread_t * );
60 static void     BitstreamCallback ( bit_stream_t *, boolean_t );
61
62 /*****************************************************************************
63  * Capabilities
64  *****************************************************************************/
65 void _M( vdec_getfunctions )( function_list_t * p_function_list )
66 {
67     p_function_list->functions.dec.pf_probe = decoder_Probe;
68     p_function_list->functions.dec.pf_run   = decoder_Run;
69 }
70
71 /*****************************************************************************
72  * Build configuration tree.
73  *****************************************************************************/
74 #define VDEC_IDCT_TEXT N_("IDCT module")
75 #define VDEC_IDCT_LONGTEXT N_( \
76     "This option allows you to select the IDCT module used by this video " \
77     "decoder.\n" \
78     "Note that the default behavior is to automatically select the best " \
79     "module available.")
80
81 #define VDEC_MOTION_TEXT N_("motion compensation module")
82 #define VDEC_MOTION_LONGTEXT N_( \
83     "This option allows you to select the motion compensation module used by "\
84     "this video decoder.\n" \
85     "Note that the default behavior is to automatically select the best " \
86     "module available.")
87
88 #define VDEC_SMP_TEXT N_("use additional processors")
89 #define VDEC_SMP_LONGTEXT N_( \
90     "This video decoder can benefit from a multiprocessor computer. If you " \
91     "have one, you can specify the number of processors here.")
92
93 #define VPAR_SYNCHRO_TEXT N_("force synchro algorithm {I|I+|IP|IP+|IPB}")
94 #define VPAR_SYNCHRO_LONGTEXT N_( \
95     "This allows you to force the synchro algorithm, by directly selecting " \
96     "the types of picture you want to decode. Please bear in mind that if " \
97     "you select more pictures than what your CPU is capable to decode, " \
98     "you won't get anything.")
99
100 MODULE_CONFIG_START
101 ADD_CATEGORY_HINT( N_("Miscellaneous"), NULL)
102 ADD_MODULE  ( "mpeg-idct", MODULE_CAPABILITY_IDCT, NULL, NULL,
103               VDEC_IDCT_TEXT, VDEC_IDCT_LONGTEXT )
104 ADD_MODULE  ( "mpeg-motion", MODULE_CAPABILITY_MOTION, NULL, NULL,
105               VDEC_MOTION_TEXT, VDEC_IDCT_LONGTEXT )
106 ADD_INTEGER ( "vdec-smp", 0, NULL, VDEC_SMP_TEXT, VDEC_SMP_LONGTEXT )
107 ADD_STRING  ( "vpar-synchro", NULL, NULL, VPAR_SYNCHRO_TEXT,
108               VPAR_SYNCHRO_LONGTEXT )
109 MODULE_CONFIG_STOP
110
111 MODULE_INIT_START
112     SET_DESCRIPTION( _("MPEG I/II video decoder module") )
113     ADD_CAPABILITY( DECODER, 50 )
114 MODULE_INIT_STOP
115
116 MODULE_ACTIVATE_START
117     _M( vdec_getfunctions )( &p_module->p_functions->dec );
118 MODULE_ACTIVATE_STOP
119
120 MODULE_DEACTIVATE_START
121 MODULE_DEACTIVATE_STOP
122
123
124 /*****************************************************************************
125  * decoder_Probe: probe the decoder and return score
126  *****************************************************************************
127  * Tries to launch a decoder and return score so that the interface is able 
128  * to chose.
129  *****************************************************************************/
130 static int decoder_Probe( u8 *pi_type )
131 {
132     return( ( *pi_type == MPEG1_VIDEO_ES
133                || *pi_type == MPEG2_VIDEO_ES ) ? 0 : -1 );
134 }
135
136 /*****************************************************************************
137  * decoder_Run: this function is called just after the thread is created
138  *****************************************************************************/
139 static int decoder_Run ( decoder_config_t * p_config )
140 {
141     vpar_thread_t *     p_vpar;
142     boolean_t           b_error;
143
144     /* Allocate the memory needed to store the thread's structure */
145     if ( (p_vpar = (vpar_thread_t *)malloc( sizeof(vpar_thread_t) )) == NULL )
146     {
147         intf_ErrMsg( "vpar error: not enough memory "
148                      "for vpar_CreateThread() to create the new thread");
149         DecoderError( p_config->p_decoder_fifo );
150         return( -1 );
151     }
152
153     /*
154      * Initialize the thread properties
155      */
156     p_vpar->p_fifo = p_config->p_decoder_fifo;
157     p_vpar->p_config = p_config;
158     p_vpar->p_vout = NULL;
159
160     /*
161      * Initialize thread
162      */
163     p_vpar->p_fifo->b_error = InitThread( p_vpar );
164      
165     /*
166      * Main loop - it is not executed if an error occured during
167      * initialization
168      */
169     while( (!p_vpar->p_fifo->b_die) && (!p_vpar->p_fifo->b_error) )
170     {
171         /* Find the next sequence header in the stream */
172         p_vpar->p_fifo->b_error = vpar_NextSequenceHeader( p_vpar );
173
174         while( (!p_vpar->p_fifo->b_die) && (!p_vpar->p_fifo->b_error) )
175         {
176             p_vpar->c_loops++;
177
178             /* Parse the next sequence, group or picture header */
179             if( vpar_ParseHeader( p_vpar ) )
180             {
181                 /* End of sequence */
182                 break;
183             }
184         }
185     }
186
187     /*
188      * Error loop
189      */
190     if( ( b_error = p_vpar->p_fifo->b_error ) )
191     {
192         DecoderError( p_vpar->p_fifo );
193     }
194
195     /* End of thread */
196     EndThread( p_vpar );
197
198     if( b_error )
199     {
200         return( -1 );
201     }
202    
203     return( 0 );
204     
205
206
207 /*****************************************************************************
208  * InitThread: initialize vpar output thread
209  *****************************************************************************
210  * This function is called from decoder_Run and performs the second step 
211  * of the initialization. It returns 0 on success. Note that the thread's 
212  * flag are not modified inside this function.
213  *****************************************************************************/
214 static int InitThread( vpar_thread_t *p_vpar )
215 {
216     char *psz_name;
217
218     /*
219      * Choose the best motion compensation module
220      */
221     psz_name = config_GetPszVariable( "mpeg-motion" );
222     p_vpar->p_motion_module = module_Need( MODULE_CAPABILITY_MOTION, psz_name,
223                                            NULL );
224     if( psz_name ) free( psz_name );
225
226     if( p_vpar->p_motion_module == NULL )
227     {
228         intf_ErrMsg( "vpar error: no suitable motion compensation module" );
229         free( p_vpar );
230         return( -1 );
231     }
232
233 #define f ( p_vpar->p_motion_module->p_functions->motion.functions.motion )
234     memcpy( p_vpar->pool.ppppf_motion, f.ppppf_motion, sizeof(void *) * 16 );
235 #undef f
236
237     /*
238      * Choose the best IDCT module
239      */
240     psz_name = config_GetPszVariable( "mpeg-idct" );
241     p_vpar->p_idct_module = module_Need( MODULE_CAPABILITY_IDCT, psz_name,
242                                          NULL );
243     if( psz_name ) free( psz_name );
244
245     if( p_vpar->p_idct_module == NULL )
246     {
247         intf_ErrMsg( "vpar error: no suitable IDCT module" );
248         module_Unneed( p_vpar->p_motion_module );
249         free( p_vpar );
250         return( -1 );
251     }
252
253 #define f p_vpar->p_idct_module->p_functions->idct.functions.idct
254     p_vpar->pool.pf_idct_init   = f.pf_idct_init;
255     p_vpar->pf_sparse_idct_add  = f.pf_sparse_idct_add;
256     p_vpar->pf_idct_add         = f.pf_idct_add;
257     p_vpar->pf_sparse_idct_copy = f.pf_sparse_idct_copy;
258     p_vpar->pf_idct_copy        = f.pf_idct_copy;
259     p_vpar->pf_norm_scan        = f.pf_norm_scan;
260 #undef f
261
262     /* Initialize input bitstream */
263     InitBitstream( &p_vpar->bit_stream, p_vpar->p_config->p_decoder_fifo,
264                    BitstreamCallback, (void *)p_vpar );
265
266     /* Initialize parsing data */
267     p_vpar->sequence.p_forward = NULL;
268     p_vpar->sequence.p_backward = NULL;
269     p_vpar->sequence.intra_quant.b_allocated = 0;
270     p_vpar->sequence.nonintra_quant.b_allocated = 0;
271     p_vpar->sequence.chroma_intra_quant.b_allocated = 0;
272     p_vpar->sequence.chroma_nonintra_quant.b_allocated = 0;
273     p_vpar->sequence.i_matrix_coefficients = 1;
274     p_vpar->sequence.next_pts = p_vpar->sequence.next_dts = 0;
275     p_vpar->sequence.b_expect_discontinuity = 0;
276
277     /* Initialize copyright information */
278     p_vpar->sequence.b_copyright_flag = 0;
279     p_vpar->sequence.b_original = 0;
280     p_vpar->sequence.i_copyright_id = 0;
281     p_vpar->sequence.i_copyright_nb = 0;
282
283     p_vpar->picture.p_picture = NULL;
284     p_vpar->picture.i_current_structure = 0;
285
286     /* Initialize other properties */
287     p_vpar->c_loops = 0;
288     p_vpar->c_sequences = 0;
289     memset(p_vpar->pc_pictures, 0, sizeof(p_vpar->pc_pictures));
290     memset(p_vpar->pc_decoded_pictures, 0, sizeof(p_vpar->pc_decoded_pictures));
291     memset(p_vpar->pc_malformed_pictures, 0,
292            sizeof(p_vpar->pc_malformed_pictures));
293     vpar_InitScanTable( p_vpar );
294
295     /*
296      * Initialize the synchro properties
297      */
298     vpar_SynchroInit( p_vpar );
299
300     /* Spawn optional video decoder threads */
301     vpar_InitPool( p_vpar );
302
303     /* Mark thread as running and return */
304     return( 0 );
305 }
306
307 /*****************************************************************************
308  * EndThread: thread destruction
309  *****************************************************************************
310  * This function is called when the thread ends after a sucessful
311  * initialization.
312  *****************************************************************************/
313 static void EndThread( vpar_thread_t *p_vpar )
314 {
315     /* Release used video buffers. */
316     if( p_vpar->sequence.p_forward != NULL )
317     {
318         vout_UnlinkPicture( p_vpar->p_vout, p_vpar->sequence.p_forward );
319     }
320     if( p_vpar->sequence.p_backward != NULL )
321     {
322         vout_DatePicture( p_vpar->p_vout, p_vpar->sequence.p_backward,
323                           vpar_SynchroDate( p_vpar ) );
324         vout_UnlinkPicture( p_vpar->p_vout, p_vpar->sequence.p_backward );
325     }
326     if( p_vpar->picture.p_picture != NULL )
327     {
328         vout_DestroyPicture( p_vpar->p_vout, p_vpar->picture.p_picture );
329     }
330
331     if( p_main->b_stats )
332     {
333 #ifdef HAVE_SYS_TIMES_H
334         struct tms cpu_usage;
335         times( &cpu_usage );
336 #endif
337
338         intf_StatMsg( "vpar stats: %d loops among %d sequence(s)",
339                       p_vpar->c_loops, p_vpar->c_sequences );
340
341 #ifdef HAVE_SYS_TIMES_H
342         intf_StatMsg( "vpar stats: cpu usage (user: %d, system: %d)",
343                       cpu_usage.tms_utime, cpu_usage.tms_stime );
344 #endif
345
346         intf_StatMsg( "vpar stats: Read %d frames/fields (I %d/P %d/B %d)",
347                       p_vpar->pc_pictures[I_CODING_TYPE]
348                       + p_vpar->pc_pictures[P_CODING_TYPE]
349                       + p_vpar->pc_pictures[B_CODING_TYPE],
350                       p_vpar->pc_pictures[I_CODING_TYPE],
351                       p_vpar->pc_pictures[P_CODING_TYPE],
352                       p_vpar->pc_pictures[B_CODING_TYPE] );
353         intf_StatMsg( "vpar stats: Decoded %d frames/fields (I %d/P %d/B %d)",
354                       p_vpar->pc_decoded_pictures[I_CODING_TYPE]
355                       + p_vpar->pc_decoded_pictures[P_CODING_TYPE]
356                       + p_vpar->pc_decoded_pictures[B_CODING_TYPE],
357                       p_vpar->pc_decoded_pictures[I_CODING_TYPE],
358                       p_vpar->pc_decoded_pictures[P_CODING_TYPE],
359                       p_vpar->pc_decoded_pictures[B_CODING_TYPE] );
360         intf_StatMsg( "vpar stats: Read %d malformed frames/fields (I %d/P %d/B %d)",
361                       p_vpar->pc_malformed_pictures[I_CODING_TYPE]
362                       + p_vpar->pc_malformed_pictures[P_CODING_TYPE]
363                       + p_vpar->pc_malformed_pictures[B_CODING_TYPE],
364                       p_vpar->pc_malformed_pictures[I_CODING_TYPE],
365                       p_vpar->pc_malformed_pictures[P_CODING_TYPE],
366                       p_vpar->pc_malformed_pictures[B_CODING_TYPE] );
367 #define S   p_vpar->sequence
368         intf_StatMsg( "vpar info: %s stream (%dx%d), %d.%d pi/s",
369                       S.b_mpeg2 ? "MPEG-2" : "MPEG-1",
370                       S.i_width, S.i_height, S.i_frame_rate/1001,
371                       S.i_frame_rate % 1001 );
372         intf_StatMsg( "vpar info: %s, %s, matrix_coeff: %d",
373                       S.b_progressive ? "Progressive" : "Non-progressive",
374                       S.i_scalable_mode ? "scalable" : "non-scalable",
375                       S.i_matrix_coefficients );
376 #undef S
377     }
378
379     /* Dispose of matrices if they have been allocated. */
380     if( p_vpar->sequence.intra_quant.b_allocated )
381     {
382         free( p_vpar->sequence.intra_quant.pi_matrix );
383     }
384     if( p_vpar->sequence.nonintra_quant.b_allocated )
385     {
386         free( p_vpar->sequence.nonintra_quant.pi_matrix) ;
387     }
388     if( p_vpar->sequence.chroma_intra_quant.b_allocated )
389     {
390         free( p_vpar->sequence.chroma_intra_quant.pi_matrix );
391     }
392     if( p_vpar->sequence.chroma_nonintra_quant.b_allocated )
393     {
394         free( p_vpar->sequence.chroma_nonintra_quant.pi_matrix );
395     }
396
397     vpar_EndPool( p_vpar );
398
399     module_Unneed( p_vpar->p_idct_module );
400     module_Unneed( p_vpar->p_motion_module );
401
402     free( p_vpar );
403 }
404
405 /*****************************************************************************
406  * BitstreamCallback: Import parameters from the new data/PES packet
407  *****************************************************************************
408  * This function is called by input's NextDataPacket.
409  *****************************************************************************/
410 static void BitstreamCallback ( bit_stream_t * p_bit_stream,
411                                 boolean_t b_new_pes )
412 {
413     vpar_thread_t * p_vpar = (vpar_thread_t *)p_bit_stream->p_callback_arg;
414
415     if( b_new_pes )
416     {
417         p_vpar->sequence.i_current_rate =
418             p_bit_stream->p_decoder_fifo->p_first->i_rate;
419
420         if( p_bit_stream->p_decoder_fifo->p_first->b_discontinuity )
421         {
422             /* Escape the current picture and reset the picture predictors. */
423             p_vpar->sequence.b_expect_discontinuity = 1;
424             p_vpar->picture.b_error = 1;
425         }
426     }
427
428     if( p_bit_stream->p_data->b_discard_payload )
429     {
430         /* 1 packet messed up, trash the slice. */
431         p_vpar->picture.b_error = 1;
432     }
433 }