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