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