1 /*****************************************************************************
2 * video_parser.c : video parser thread
3 *****************************************************************************
4 * Copyright (C) 1999-2001 VideoLAN
5 * $Id: parser.c,v 1.8 2002/11/28 17:35:00 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 /* Release used video buffers. */
303 if( p_vpar->sequence.p_forward != NULL )
305 vout_UnlinkPicture( p_vpar->p_vout, p_vpar->sequence.p_forward );
307 if( p_vpar->sequence.p_backward != NULL )
309 vout_DatePicture( p_vpar->p_vout, p_vpar->sequence.p_backward,
310 vpar_SynchroDate( p_vpar ) );
311 vout_UnlinkPicture( p_vpar->p_vout, p_vpar->sequence.p_backward );
313 if( p_vpar->picture.p_picture != NULL )
315 vout_DestroyPicture( p_vpar->p_vout, p_vpar->picture.p_picture );
318 vout_Request( p_vpar->p_fifo, p_vpar->p_vout, 0, 0, 0, 0 );
320 msg_Dbg( p_vpar->p_fifo, "%d loops among %d sequence(s)",
321 p_vpar->c_loops, p_vpar->c_sequences );
323 #ifdef HAVE_SYS_TIMES_H
324 msg_Dbg( p_vpar->p_fifo, "cpu usage (user: %d, system: %d)",
325 cpu_usage.tms_utime, cpu_usage.tms_stime );
328 msg_Dbg( p_vpar->p_fifo, "read %d frames/fields (I %d/P %d/B %d)",
329 p_vpar->pc_pictures[I_CODING_TYPE]
330 + p_vpar->pc_pictures[P_CODING_TYPE]
331 + p_vpar->pc_pictures[B_CODING_TYPE],
332 p_vpar->pc_pictures[I_CODING_TYPE],
333 p_vpar->pc_pictures[P_CODING_TYPE],
334 p_vpar->pc_pictures[B_CODING_TYPE] );
335 msg_Dbg( p_vpar->p_fifo, "decoded %d frames/fields (I %d/P %d/B %d)",
336 p_vpar->pc_decoded_pictures[I_CODING_TYPE]
337 + p_vpar->pc_decoded_pictures[P_CODING_TYPE]
338 + p_vpar->pc_decoded_pictures[B_CODING_TYPE],
339 p_vpar->pc_decoded_pictures[I_CODING_TYPE],
340 p_vpar->pc_decoded_pictures[P_CODING_TYPE],
341 p_vpar->pc_decoded_pictures[B_CODING_TYPE] );
342 msg_Dbg( p_vpar->p_fifo,
343 "read %d malformed frames/fields (I %d/P %d/B %d)",
344 p_vpar->pc_malformed_pictures[I_CODING_TYPE]
345 + p_vpar->pc_malformed_pictures[P_CODING_TYPE]
346 + p_vpar->pc_malformed_pictures[B_CODING_TYPE],
347 p_vpar->pc_malformed_pictures[I_CODING_TYPE],
348 p_vpar->pc_malformed_pictures[P_CODING_TYPE],
349 p_vpar->pc_malformed_pictures[B_CODING_TYPE] );
350 #define S p_vpar->sequence
351 msg_Dbg( p_vpar->p_fifo, "%s stream (%dx%d), %d.%d pi/s",
352 S.b_mpeg2 ? "MPEG-2" : "MPEG-1",
353 S.i_width, S.i_height, S.i_frame_rate/1001,
354 S.i_frame_rate % 1001 );
355 msg_Dbg( p_vpar->p_fifo, "%s, %s, matrix_coeff: %d",
356 S.b_progressive ? "Progressive" : "Non-progressive",
357 S.i_scalable_mode ? "scalable" : "non-scalable",
358 S.i_matrix_coefficients );
361 /* Dispose of matrices if they have been allocated. */
362 if( p_vpar->sequence.intra_quant.b_allocated )
364 free( p_vpar->sequence.intra_quant.pi_matrix );
366 if( p_vpar->sequence.nonintra_quant.b_allocated )
368 free( p_vpar->sequence.nonintra_quant.pi_matrix) ;
370 if( p_vpar->sequence.chroma_intra_quant.b_allocated )
372 free( p_vpar->sequence.chroma_intra_quant.pi_matrix );
374 if( p_vpar->sequence.chroma_nonintra_quant.b_allocated )
376 free( p_vpar->sequence.chroma_nonintra_quant.pi_matrix );
379 vpar_EndPool( p_vpar );
381 module_Unneed( p_vpar->p_fifo, p_vpar->p_idct );
382 module_Unneed( p_vpar->p_fifo, p_vpar->p_motion );
384 CloseBitstream( &p_vpar->bit_stream );
388 /*****************************************************************************
389 * BitstreamCallback: Import parameters from the new data/PES packet
390 *****************************************************************************
391 * This function is called by input's NextDataPacket.
392 *****************************************************************************/
393 static void BitstreamCallback ( bit_stream_t * p_bit_stream,
394 vlc_bool_t b_new_pes )
396 vpar_thread_t * p_vpar = (vpar_thread_t *)p_bit_stream->p_callback_arg;
400 p_vpar->sequence.i_current_rate =
401 p_bit_stream->p_pes->i_rate;
403 if( p_bit_stream->p_pes->b_discontinuity )
405 /* Escape the current picture and reset the picture predictors. */
406 p_vpar->sequence.b_expect_discontinuity = 1;
407 p_vpar->picture.b_error = 1;
411 if( p_bit_stream->p_data->b_discard_payload )
413 /* 1 packet messed up, trash the slice. */
414 p_vpar->picture.b_error = 1;