1 /*****************************************************************************
2 * video_parser.c : video parser thread
3 *****************************************************************************
4 * Copyright (C) 1999-2001 VideoLAN
5 * $Id: parser.c,v 1.2 2002/08/04 18:39:41 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>
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 );
59 /*****************************************************************************
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 " \
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.")
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.")
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.")
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 );
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
105 *****************************************************************************/
106 static int OpenDecoder( vlc_object_t *p_this )
108 decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
110 if( p_fifo->i_fourcc == VLC_FOURCC('m','p','g','v') )
112 p_fifo->pf_run = RunDecoder;
119 /*****************************************************************************
120 * RunDecoder: this function is called just after the thread is created
121 *****************************************************************************/
122 static int RunDecoder ( decoder_fifo_t * p_fifo )
124 vpar_thread_t * p_vpar;
127 /* Allocate the memory needed to store the thread's structure */
128 if ( (p_vpar = (vpar_thread_t *)malloc( sizeof(vpar_thread_t) )) == NULL )
130 msg_Err( p_fifo, "out of memory" );
131 DecoderError( p_fifo );
136 * Initialize the thread properties
138 p_vpar->p_fifo = p_fifo;
139 p_vpar->p_vout = NULL;
144 p_vpar->p_fifo->b_error = InitThread( p_vpar );
147 * Main loop - it is not executed if an error occured during
150 while( (!p_vpar->p_fifo->b_die) && (!p_vpar->p_fifo->b_error) )
152 /* Find the next sequence header in the stream */
153 p_vpar->p_fifo->b_error = vpar_NextSequenceHeader( p_vpar );
155 while( (!p_vpar->p_fifo->b_die) && (!p_vpar->p_fifo->b_error) )
159 /* Parse the next sequence, group or picture header */
160 if( vpar_ParseHeader( p_vpar ) )
162 /* End of sequence */
171 if( ( b_error = p_vpar->p_fifo->b_error ) )
173 DecoderError( p_vpar->p_fifo );
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 )
200 * Choose the best motion compensation module
202 psz_name = config_GetPsz( p_vpar->p_fifo, "mpeg-motion" );
204 module_Need( p_vpar->p_fifo, "motion compensation", psz_name );
205 if( psz_name ) free( psz_name );
207 if( p_vpar->p_motion == NULL )
209 msg_Err( p_vpar->p_fifo, "no suitable motion compensation module" );
214 memcpy( p_vpar->pool.ppppf_motion,
215 p_vpar->p_fifo->p_private, sizeof(void *) * 16 );
218 * Choose the best IDCT module
220 psz_name = config_GetPsz( p_vpar->p_fifo, "mpeg-idct" );
221 p_vpar->p_idct = module_Need( p_vpar->p_fifo, "idct", psz_name );
222 if( psz_name ) free( psz_name );
224 if( p_vpar->p_idct == NULL )
226 msg_Err( p_vpar->p_fifo, "no suitable IDCT module" );
227 module_Unneed( p_vpar->p_fifo, p_vpar->p_motion );
232 p_vpar->pool.pf_idct_init = ((void**)p_vpar->p_fifo->p_private)[0];
233 p_vpar->pf_norm_scan = ((void**)p_vpar->p_fifo->p_private)[1];
234 p_vpar->pf_sparse_idct_add = ((void**)p_vpar->p_fifo->p_private)[2];
235 p_vpar->pf_sparse_idct_copy = ((void**)p_vpar->p_fifo->p_private)[3];
236 p_vpar->pf_idct_add = ((void**)p_vpar->p_fifo->p_private)[4];
237 p_vpar->pf_idct_copy = ((void**)p_vpar->p_fifo->p_private)[5];
239 /* Initialize input bitstream */
240 InitBitstream( &p_vpar->bit_stream, p_vpar->p_fifo,
241 BitstreamCallback, (void *)p_vpar );
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;
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;
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;
268 p_vpar->picture.p_picture = NULL;
269 p_vpar->picture.i_current_structure = 0;
271 /* Initialize other properties */
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 );
281 * Initialize the synchro properties
283 vpar_SynchroInit( p_vpar );
285 /* Spawn optional video decoder threads */
286 vpar_InitPool( p_vpar );
288 /* Mark thread as running and return */
292 /*****************************************************************************
293 * EndThread: thread destruction
294 *****************************************************************************
295 * This function is called when the thread ends after a sucessful
297 *****************************************************************************/
298 static void EndThread( vpar_thread_t *p_vpar )
300 #ifdef HAVE_SYS_TIMES_H
301 struct tms cpu_usage;
305 if( p_vpar->p_vout != NULL )
307 /* Release used video buffers. */
308 if( p_vpar->sequence.p_forward != NULL )
310 vout_UnlinkPicture( p_vpar->p_vout, p_vpar->sequence.p_forward );
312 if( p_vpar->sequence.p_backward != NULL )
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 );
318 if( p_vpar->picture.p_picture != NULL )
320 vout_DestroyPicture( p_vpar->p_vout, p_vpar->picture.p_picture );
323 /* We are about to die. Reattach video output to p_vlc. */
324 vlc_object_detach( p_vpar->p_vout, p_vpar->p_fifo );
325 vlc_object_attach( p_vpar->p_vout, p_vpar->p_fifo->p_vlc );
328 msg_Dbg( p_vpar->p_fifo, "%d loops among %d sequence(s)",
329 p_vpar->c_loops, p_vpar->c_sequences );
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 );
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 );
369 /* Dispose of matrices if they have been allocated. */
370 if( p_vpar->sequence.intra_quant.b_allocated )
372 free( p_vpar->sequence.intra_quant.pi_matrix );
374 if( p_vpar->sequence.nonintra_quant.b_allocated )
376 free( p_vpar->sequence.nonintra_quant.pi_matrix) ;
378 if( p_vpar->sequence.chroma_intra_quant.b_allocated )
380 free( p_vpar->sequence.chroma_intra_quant.pi_matrix );
382 if( p_vpar->sequence.chroma_nonintra_quant.b_allocated )
384 free( p_vpar->sequence.chroma_nonintra_quant.pi_matrix );
387 vpar_EndPool( p_vpar );
389 module_Unneed( p_vpar->p_fifo, p_vpar->p_idct );
390 module_Unneed( p_vpar->p_fifo, p_vpar->p_motion );
395 /*****************************************************************************
396 * BitstreamCallback: Import parameters from the new data/PES packet
397 *****************************************************************************
398 * This function is called by input's NextDataPacket.
399 *****************************************************************************/
400 static void BitstreamCallback ( bit_stream_t * p_bit_stream,
401 vlc_bool_t b_new_pes )
403 vpar_thread_t * p_vpar = (vpar_thread_t *)p_bit_stream->p_callback_arg;
407 p_vpar->sequence.i_current_rate =
408 p_bit_stream->p_decoder_fifo->p_first->i_rate;
410 if( p_bit_stream->p_decoder_fifo->p_first->b_discontinuity )
412 /* Escape the current picture and reset the picture predictors. */
413 p_vpar->sequence.b_expect_discontinuity = 1;
414 p_vpar->picture.b_error = 1;
418 if( p_bit_stream->p_data->b_discard_payload )
420 /* 1 packet messed up, trash the slice. */
421 p_vpar->picture.b_error = 1;