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 $
7 * Authors: Christophe Massiot <massiot@via.ecp.fr>
8 * Samuel Hocevar <sam@via.ecp.fr>
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.
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.
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 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
28 #include <stdlib.h> /* malloc(), free() */
32 #include <vlc/decoder.h>
35 #include <unistd.h> /* getpid() */
41 #ifdef HAVE_SYS_TIMES_H
42 # include <sys/times.h>
45 #include "vdec_ext-plugins.h"
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 );
60 /*****************************************************************************
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 " \
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.")
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.")
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.")
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 );
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
106 *****************************************************************************/
107 static int OpenDecoder( vlc_object_t *p_this )
109 decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
111 if( p_fifo->i_fourcc == VLC_FOURCC('m','p','g','v') )
113 p_fifo->pf_run = RunDecoder;
120 /*****************************************************************************
121 * RunDecoder: this function is called just after the thread is created
122 *****************************************************************************/
123 static int RunDecoder ( decoder_fifo_t * p_fifo )
125 vpar_thread_t * p_vpar;
128 /* Allocate the memory needed to store the thread's structure */
129 if ( (p_vpar = (vpar_thread_t *)malloc( sizeof(vpar_thread_t) )) == NULL )
131 msg_Err( p_fifo, "out of memory" );
132 DecoderError( p_fifo );
137 * Initialize the thread properties
139 p_vpar->p_fifo = p_fifo;
140 p_vpar->p_vout = NULL;
145 p_vpar->p_fifo->b_error = InitThread( p_vpar );
148 * Main loop - it is not executed if an error occured during
151 while( (!p_vpar->p_fifo->b_die) && (!p_vpar->p_fifo->b_error) )
153 /* Find the next sequence header in the stream */
154 p_vpar->p_fifo->b_error = vpar_NextSequenceHeader( p_vpar );
156 while( (!p_vpar->p_fifo->b_die) && (!p_vpar->p_fifo->b_error) )
160 /* Parse the next sequence, group or picture header */
161 if( vpar_ParseHeader( p_vpar ) )
163 /* End of sequence */
172 if( ( b_error = p_vpar->p_fifo->b_error ) )
174 DecoderError( p_vpar->p_fifo );
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 )
201 * Choose the best motion compensation module
203 psz_name = config_GetPsz( p_vpar->p_fifo, "mpeg-motion" );
205 module_Need( p_vpar->p_fifo, "motion compensation", psz_name );
206 if( psz_name ) free( psz_name );
208 if( p_vpar->p_motion == NULL )
210 msg_Err( p_vpar->p_fifo, "no suitable motion compensation module" );
215 memcpy( p_vpar->pool.ppppf_motion,
216 p_vpar->p_fifo->p_private, sizeof(void *) * 16 );
219 * Choose the best IDCT module
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 );
225 if( p_vpar->p_idct == NULL )
227 msg_Err( p_vpar->p_fifo, "no suitable IDCT module" );
228 module_Unneed( p_vpar->p_fifo, p_vpar->p_motion );
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];
240 /* Initialize input bitstream */
241 InitBitstream( &p_vpar->bit_stream, p_vpar->p_fifo,
242 BitstreamCallback, (void *)p_vpar );
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;
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;
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;
269 p_vpar->picture.p_picture = NULL;
270 p_vpar->picture.i_current_structure = 0;
272 /* Initialize other properties */
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 );
282 * Initialize the synchro properties
284 vpar_SynchroInit( p_vpar );
286 /* Spawn optional video decoder threads */
287 vpar_InitPool( p_vpar );
289 /* Mark thread as running and return */
293 /*****************************************************************************
294 * EndThread: thread destruction
295 *****************************************************************************
296 * This function is called when the thread ends after a sucessful
298 *****************************************************************************/
299 static void EndThread( vpar_thread_t *p_vpar )
301 #ifdef HAVE_SYS_TIMES_H
302 struct tms cpu_usage;
306 if( p_vpar->p_vout != NULL )
308 /* Release used video buffers. */
309 if( p_vpar->sequence.p_forward != NULL )
311 vout_UnlinkPicture( p_vpar->p_vout, p_vpar->sequence.p_forward );
313 if( p_vpar->sequence.p_backward != NULL )
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 );
319 if( p_vpar->picture.p_picture != NULL )
321 vout_DestroyPicture( p_vpar->p_vout, p_vpar->picture.p_picture );
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 );
329 msg_Dbg( p_vpar->p_fifo, "%d loops among %d sequence(s)",
330 p_vpar->c_loops, p_vpar->c_sequences );
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 );
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 );
370 /* Dispose of matrices if they have been allocated. */
371 if( p_vpar->sequence.intra_quant.b_allocated )
373 free( p_vpar->sequence.intra_quant.pi_matrix );
375 if( p_vpar->sequence.nonintra_quant.b_allocated )
377 free( p_vpar->sequence.nonintra_quant.pi_matrix) ;
379 if( p_vpar->sequence.chroma_intra_quant.b_allocated )
381 free( p_vpar->sequence.chroma_intra_quant.pi_matrix );
383 if( p_vpar->sequence.chroma_nonintra_quant.b_allocated )
385 free( p_vpar->sequence.chroma_nonintra_quant.pi_matrix );
388 vpar_EndPool( p_vpar );
390 module_Unneed( p_vpar->p_fifo, p_vpar->p_idct );
391 module_Unneed( p_vpar->p_fifo, p_vpar->p_motion );
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 )
404 vpar_thread_t * p_vpar = (vpar_thread_t *)p_bit_stream->p_callback_arg;
408 p_vpar->sequence.i_current_rate =
409 p_bit_stream->p_decoder_fifo->p_first->i_rate;
411 if( p_bit_stream->p_decoder_fifo->p_first->b_discontinuity )
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;
419 if( p_bit_stream->p_data->b_discard_payload )
421 /* 1 packet messed up, trash the slice. */
422 p_vpar->picture.b_error = 1;