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