1 /*****************************************************************************
2 * video_parser.c : video parser thread
3 *****************************************************************************
4 * Copyright (C) 1999-2001 VideoLAN
5 * $Id: parser.c,v 1.7 2002/11/20 13:37:35 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() */
38 #ifdef HAVE_SYS_TIMES_H
39 # include <sys/times.h>
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 );
56 /*****************************************************************************
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 " \
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.")
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.")
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.")
84 add_category_hint( N_("Miscellaneous"), NULL );
85 add_module ( "mpeg-idct", "idct", NULL, NULL,
86 VDEC_IDCT_TEXT, VDEC_IDCT_LONGTEXT );
87 add_module ( "mpeg-motion", "motion compensation", NULL, NULL,
88 VDEC_MOTION_TEXT, VDEC_MOTION_LONGTEXT );
89 add_integer ( "vdec-smp", 0, NULL, VDEC_SMP_TEXT, VDEC_SMP_LONGTEXT );
90 add_string ( "vpar-synchro", NULL, NULL, VPAR_SYNCHRO_TEXT,
91 VPAR_SYNCHRO_LONGTEXT );
92 set_description( _("MPEG I/II video decoder module") );
93 set_capability( "decoder", 50 );
94 set_callbacks( OpenDecoder, NULL );
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
102 *****************************************************************************/
103 static int OpenDecoder( vlc_object_t *p_this )
105 decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
107 if( p_fifo->i_fourcc == VLC_FOURCC('m','p','g','v') )
109 p_fifo->pf_run = RunDecoder;
116 /*****************************************************************************
117 * RunDecoder: this function is called just after the thread is created
118 *****************************************************************************/
119 static int RunDecoder ( decoder_fifo_t * p_fifo )
121 vpar_thread_t * p_vpar;
124 /* Allocate the memory needed to store the thread's structure */
125 if ( (p_vpar = (vpar_thread_t *)malloc( sizeof(vpar_thread_t) )) == NULL )
127 msg_Err( p_fifo, "out of memory" );
128 DecoderError( p_fifo );
133 * Initialize the thread properties
135 p_vpar->p_fifo = p_fifo;
136 p_vpar->p_vout = NULL;
141 p_vpar->p_fifo->b_error = InitThread( p_vpar );
144 * Main loop - it is not executed if an error occured during
147 while( (!p_vpar->p_fifo->b_die) && (!p_vpar->p_fifo->b_error) )
149 /* Find the next sequence header in the stream */
150 p_vpar->p_fifo->b_error = vpar_NextSequenceHeader( p_vpar );
152 while( (!p_vpar->p_fifo->b_die) && (!p_vpar->p_fifo->b_error) )
156 /* Parse the next sequence, group or picture header */
157 if( vpar_ParseHeader( p_vpar ) )
159 /* End of sequence */
168 if( ( b_error = p_vpar->p_fifo->b_error ) )
170 DecoderError( p_vpar->p_fifo );
185 /*****************************************************************************
186 * InitThread: initialize vpar output thread
187 *****************************************************************************
188 * This function is called from Run and performs the second step
189 * of the initialization. It returns 0 on success. Note that the thread's
190 * flag are not modified inside this function.
191 *****************************************************************************/
192 static int InitThread( vpar_thread_t *p_vpar )
195 * Choose the best motion compensation module
198 module_Need( p_vpar->p_fifo, "motion compensation", "$mpeg-motion" );
200 if( p_vpar->p_motion == NULL )
202 msg_Err( p_vpar->p_fifo, "no suitable motion compensation module" );
207 memcpy( p_vpar->pool.ppppf_motion,
208 p_vpar->p_fifo->p_private, sizeof(void *) * 16 );
211 * Choose the best IDCT module
213 p_vpar->p_idct = module_Need( p_vpar->p_fifo, "idct", "$mpeg-idct" );
215 if( p_vpar->p_idct == NULL )
217 msg_Err( p_vpar->p_fifo, "no suitable IDCT module" );
218 module_Unneed( p_vpar->p_fifo, p_vpar->p_motion );
223 p_vpar->pool.pf_idct_init = ((void**)p_vpar->p_fifo->p_private)[0];
224 p_vpar->pf_norm_scan = ((void**)p_vpar->p_fifo->p_private)[1];
225 p_vpar->pf_sparse_idct_add = ((void**)p_vpar->p_fifo->p_private)[2];
226 p_vpar->pf_sparse_idct_copy = ((void**)p_vpar->p_fifo->p_private)[3];
227 p_vpar->pf_idct_add = ((void**)p_vpar->p_fifo->p_private)[4];
228 p_vpar->pf_idct_copy = ((void**)p_vpar->p_fifo->p_private)[5];
230 /* Initialize input bitstream */
231 if( InitBitstream( &p_vpar->bit_stream, p_vpar->p_fifo,
232 BitstreamCallback, (void *)p_vpar ) != VLC_SUCCESS )
234 msg_Err( p_vpar->p_fifo, "cannot initialize bitstream" );
235 module_Unneed( p_vpar->p_fifo, p_vpar->p_motion );
240 /* Initialize parsing data */
241 p_vpar->sequence.p_forward = NULL;
242 p_vpar->sequence.p_backward = NULL;
243 p_vpar->sequence.intra_quant.b_allocated = 0;
244 p_vpar->sequence.nonintra_quant.b_allocated = 0;
245 p_vpar->sequence.chroma_intra_quant.b_allocated = 0;
246 p_vpar->sequence.chroma_nonintra_quant.b_allocated = 0;
247 p_vpar->sequence.i_matrix_coefficients = 1;
248 p_vpar->sequence.next_pts = p_vpar->sequence.next_dts = 0;
249 p_vpar->sequence.b_expect_discontinuity = 0;
251 p_vpar->sequence.i_width = 0;
252 p_vpar->sequence.i_height = 0;
253 p_vpar->sequence.i_frame_rate = 0;
254 p_vpar->sequence.i_scalable_mode = 0;
255 p_vpar->sequence.i_matrix_coefficients = 0;
256 p_vpar->sequence.b_mpeg2 = 0;
257 p_vpar->sequence.b_progressive = 0;
259 /* Initialize copyright information */
260 p_vpar->sequence.b_copyright_flag = 0;
261 p_vpar->sequence.b_original = 0;
262 p_vpar->sequence.i_copyright_id = 0;
263 p_vpar->sequence.i_copyright_nb = 0;
265 p_vpar->picture.p_picture = NULL;
266 p_vpar->picture.i_current_structure = 0;
268 /* Initialize other properties */
270 p_vpar->c_sequences = 0;
271 memset(p_vpar->pc_pictures, 0, sizeof(p_vpar->pc_pictures));
272 memset(p_vpar->pc_decoded_pictures, 0, sizeof(p_vpar->pc_decoded_pictures));
273 memset(p_vpar->pc_malformed_pictures, 0,
274 sizeof(p_vpar->pc_malformed_pictures));
275 vpar_InitScanTable( p_vpar );
278 * Initialize the synchro properties
280 vpar_SynchroInit( p_vpar );
282 /* Spawn optional video decoder threads */
283 vpar_InitPool( p_vpar );
285 /* Mark thread as running and return */
289 /*****************************************************************************
290 * EndThread: thread destruction
291 *****************************************************************************
292 * This function is called when the thread ends after a sucessful
294 *****************************************************************************/
295 static void EndThread( vpar_thread_t *p_vpar )
297 #ifdef HAVE_SYS_TIMES_H
298 struct tms cpu_usage;
302 if( p_vpar->p_vout != NULL )
304 /* Release used video buffers. */
305 if( p_vpar->sequence.p_forward != NULL )
307 vout_UnlinkPicture( p_vpar->p_vout, p_vpar->sequence.p_forward );
309 if( p_vpar->sequence.p_backward != NULL )
311 vout_DatePicture( p_vpar->p_vout, p_vpar->sequence.p_backward,
312 vpar_SynchroDate( p_vpar ) );
313 vout_UnlinkPicture( p_vpar->p_vout, p_vpar->sequence.p_backward );
315 if( p_vpar->picture.p_picture != NULL )
317 vout_DestroyPicture( p_vpar->p_vout, p_vpar->picture.p_picture );
320 /* We are about to die. Reattach video output to p_vlc. */
321 vlc_object_detach( p_vpar->p_vout );
322 vlc_object_attach( p_vpar->p_vout, p_vpar->p_fifo->p_vlc );
325 msg_Dbg( p_vpar->p_fifo, "%d loops among %d sequence(s)",
326 p_vpar->c_loops, p_vpar->c_sequences );
328 #ifdef HAVE_SYS_TIMES_H
329 msg_Dbg( p_vpar->p_fifo, "cpu usage (user: %d, system: %d)",
330 cpu_usage.tms_utime, cpu_usage.tms_stime );
333 msg_Dbg( p_vpar->p_fifo, "read %d frames/fields (I %d/P %d/B %d)",
334 p_vpar->pc_pictures[I_CODING_TYPE]
335 + p_vpar->pc_pictures[P_CODING_TYPE]
336 + p_vpar->pc_pictures[B_CODING_TYPE],
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 msg_Dbg( p_vpar->p_fifo, "decoded %d frames/fields (I %d/P %d/B %d)",
341 p_vpar->pc_decoded_pictures[I_CODING_TYPE]
342 + p_vpar->pc_decoded_pictures[P_CODING_TYPE]
343 + p_vpar->pc_decoded_pictures[B_CODING_TYPE],
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 msg_Dbg( p_vpar->p_fifo,
348 "read %d malformed frames/fields (I %d/P %d/B %d)",
349 p_vpar->pc_malformed_pictures[I_CODING_TYPE]
350 + p_vpar->pc_malformed_pictures[P_CODING_TYPE]
351 + p_vpar->pc_malformed_pictures[B_CODING_TYPE],
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 #define S p_vpar->sequence
356 msg_Dbg( p_vpar->p_fifo, "%s stream (%dx%d), %d.%d pi/s",
357 S.b_mpeg2 ? "MPEG-2" : "MPEG-1",
358 S.i_width, S.i_height, S.i_frame_rate/1001,
359 S.i_frame_rate % 1001 );
360 msg_Dbg( p_vpar->p_fifo, "%s, %s, matrix_coeff: %d",
361 S.b_progressive ? "Progressive" : "Non-progressive",
362 S.i_scalable_mode ? "scalable" : "non-scalable",
363 S.i_matrix_coefficients );
366 /* Dispose of matrices if they have been allocated. */
367 if( p_vpar->sequence.intra_quant.b_allocated )
369 free( p_vpar->sequence.intra_quant.pi_matrix );
371 if( p_vpar->sequence.nonintra_quant.b_allocated )
373 free( p_vpar->sequence.nonintra_quant.pi_matrix) ;
375 if( p_vpar->sequence.chroma_intra_quant.b_allocated )
377 free( p_vpar->sequence.chroma_intra_quant.pi_matrix );
379 if( p_vpar->sequence.chroma_nonintra_quant.b_allocated )
381 free( p_vpar->sequence.chroma_nonintra_quant.pi_matrix );
384 vpar_EndPool( p_vpar );
386 module_Unneed( p_vpar->p_fifo, p_vpar->p_idct );
387 module_Unneed( p_vpar->p_fifo, p_vpar->p_motion );
389 CloseBitstream( &p_vpar->bit_stream );
393 /*****************************************************************************
394 * BitstreamCallback: Import parameters from the new data/PES packet
395 *****************************************************************************
396 * This function is called by input's NextDataPacket.
397 *****************************************************************************/
398 static void BitstreamCallback ( bit_stream_t * p_bit_stream,
399 vlc_bool_t b_new_pes )
401 vpar_thread_t * p_vpar = (vpar_thread_t *)p_bit_stream->p_callback_arg;
405 p_vpar->sequence.i_current_rate =
406 p_bit_stream->p_pes->i_rate;
408 if( p_bit_stream->p_pes->b_discontinuity )
410 /* Escape the current picture and reset the picture predictors. */
411 p_vpar->sequence.b_expect_discontinuity = 1;
412 p_vpar->picture.b_error = 1;
416 if( p_bit_stream->p_data->b_discard_payload )
418 /* 1 packet messed up, trash the slice. */
419 p_vpar->picture.b_error = 1;