1 /*****************************************************************************
2 * video_parser.c : video parser thread
3 *****************************************************************************
4 * Copyright (C) 1999-2001 VideoLAN
5 * $Id: parser.c,v 1.11 2003/02/20 01:52:46 sigmunau 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, 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 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 vpar_ParseHeader( p_vpar );
164 if( ( b_error = p_vpar->p_fifo->b_error ) )
166 DecoderError( p_vpar->p_fifo );
181 /*****************************************************************************
182 * InitThread: initialize vpar output thread
183 *****************************************************************************
184 * This function is called from Run and performs the second step
185 * of the initialization. It returns 0 on success. Note that the thread's
186 * flag are not modified inside this function.
187 *****************************************************************************/
188 static int InitThread( vpar_thread_t *p_vpar )
191 * Choose the best motion compensation module
194 module_Need( p_vpar->p_fifo, "motion compensation", "$mpeg-motion" );
196 if( p_vpar->p_motion == NULL )
198 msg_Err( p_vpar->p_fifo, "no suitable motion compensation module" );
203 memcpy( p_vpar->pool.ppppf_motion,
204 p_vpar->p_fifo->p_private, sizeof(void *) * 16 );
207 * Choose the best IDCT module
209 p_vpar->p_idct = module_Need( p_vpar->p_fifo, "idct", "$mpeg-idct" );
211 if( p_vpar->p_idct == NULL )
213 msg_Err( p_vpar->p_fifo, "no suitable IDCT module" );
214 module_Unneed( p_vpar->p_fifo, p_vpar->p_motion );
219 p_vpar->pool.pf_idct_init = ((void**)p_vpar->p_fifo->p_private)[0];
220 p_vpar->pf_norm_scan = ((void**)p_vpar->p_fifo->p_private)[1];
221 p_vpar->pf_sparse_idct_add = ((void**)p_vpar->p_fifo->p_private)[2];
222 p_vpar->pf_sparse_idct_copy = ((void**)p_vpar->p_fifo->p_private)[3];
223 p_vpar->pf_idct_add = ((void**)p_vpar->p_fifo->p_private)[4];
224 p_vpar->pf_idct_copy = ((void**)p_vpar->p_fifo->p_private)[5];
226 /* Initialize input bitstream */
227 if( InitBitstream( &p_vpar->bit_stream, p_vpar->p_fifo,
228 BitstreamCallback, (void *)p_vpar ) != VLC_SUCCESS )
230 msg_Err( p_vpar->p_fifo, "cannot initialize bitstream" );
231 module_Unneed( p_vpar->p_fifo, p_vpar->p_motion );
236 /* Initialize parsing data */
237 p_vpar->sequence.p_forward = NULL;
238 p_vpar->sequence.p_backward = NULL;
239 p_vpar->sequence.intra_quant.b_allocated = 0;
240 p_vpar->sequence.nonintra_quant.b_allocated = 0;
241 p_vpar->sequence.chroma_intra_quant.b_allocated = 0;
242 p_vpar->sequence.chroma_nonintra_quant.b_allocated = 0;
243 p_vpar->sequence.i_matrix_coefficients = 1;
244 p_vpar->sequence.next_pts = p_vpar->sequence.next_dts = 0;
245 p_vpar->sequence.b_expect_discontinuity = 0;
247 p_vpar->sequence.i_width = 0;
248 p_vpar->sequence.i_height = 0;
249 p_vpar->sequence.i_frame_rate = 0;
250 p_vpar->sequence.i_scalable_mode = 0;
251 p_vpar->sequence.i_matrix_coefficients = 0;
252 p_vpar->sequence.b_mpeg2 = 0;
253 p_vpar->sequence.b_progressive = 0;
255 /* Initialize copyright information */
256 p_vpar->sequence.b_copyright_flag = 0;
257 p_vpar->sequence.b_original = 0;
258 p_vpar->sequence.i_copyright_id = 0;
259 p_vpar->sequence.i_copyright_nb = 0;
261 p_vpar->picture.p_picture = NULL;
262 p_vpar->picture.i_current_structure = 0;
264 /* Initialize other properties */
266 p_vpar->c_sequences = 0;
267 memset(p_vpar->pc_pictures, 0, sizeof(p_vpar->pc_pictures));
268 memset(p_vpar->pc_decoded_pictures, 0, sizeof(p_vpar->pc_decoded_pictures));
269 memset(p_vpar->pc_malformed_pictures, 0,
270 sizeof(p_vpar->pc_malformed_pictures));
271 vpar_InitScanTable( p_vpar );
274 * Initialize the synchro properties
276 vpar_SynchroInit( p_vpar );
278 /* Spawn optional video decoder threads */
279 vpar_InitPool( p_vpar );
281 /* Mark thread as running and return */
285 /*****************************************************************************
286 * EndThread: thread destruction
287 *****************************************************************************
288 * This function is called when the thread ends after a sucessful
290 *****************************************************************************/
291 static void EndThread( vpar_thread_t *p_vpar )
293 #ifdef HAVE_SYS_TIMES_H
294 struct tms cpu_usage;
298 /* Release used video buffers. */
299 if( p_vpar->sequence.p_forward != NULL )
301 vout_UnlinkPicture( p_vpar->p_vout, p_vpar->sequence.p_forward );
303 if( p_vpar->sequence.p_backward != NULL )
305 vout_DatePicture( p_vpar->p_vout, p_vpar->sequence.p_backward,
306 vpar_SynchroDate( p_vpar ) );
307 vout_UnlinkPicture( p_vpar->p_vout, p_vpar->sequence.p_backward );
309 if( p_vpar->picture.p_picture != NULL )
311 vout_DestroyPicture( p_vpar->p_vout, p_vpar->picture.p_picture );
314 vout_Request( p_vpar->p_fifo, p_vpar->p_vout, 0, 0, 0, 0 );
316 msg_Dbg( p_vpar->p_fifo, "%ld loops among %ld sequence(s)",
317 p_vpar->c_loops, p_vpar->c_sequences );
319 #ifdef HAVE_SYS_TIMES_H
320 msg_Dbg( p_vpar->p_fifo, "cpu usage (user: %ld, system: %ld)",
321 cpu_usage.tms_utime, cpu_usage.tms_stime );
324 msg_Dbg( p_vpar->p_fifo, "read %ld frames/fields (I %ld/P %ld/B %ld)",
325 p_vpar->pc_pictures[I_CODING_TYPE]
326 + p_vpar->pc_pictures[P_CODING_TYPE]
327 + p_vpar->pc_pictures[B_CODING_TYPE],
328 p_vpar->pc_pictures[I_CODING_TYPE],
329 p_vpar->pc_pictures[P_CODING_TYPE],
330 p_vpar->pc_pictures[B_CODING_TYPE] );
331 msg_Dbg( p_vpar->p_fifo, "decoded %ld frames/fields (I %ld/P %ld/B %ld)",
332 p_vpar->pc_decoded_pictures[I_CODING_TYPE]
333 + p_vpar->pc_decoded_pictures[P_CODING_TYPE]
334 + p_vpar->pc_decoded_pictures[B_CODING_TYPE],
335 p_vpar->pc_decoded_pictures[I_CODING_TYPE],
336 p_vpar->pc_decoded_pictures[P_CODING_TYPE],
337 p_vpar->pc_decoded_pictures[B_CODING_TYPE] );
338 msg_Dbg( p_vpar->p_fifo,
339 "read %ld malformed frames/fields (I %ld/P %ld/B %ld)",
340 p_vpar->pc_malformed_pictures[I_CODING_TYPE]
341 + p_vpar->pc_malformed_pictures[P_CODING_TYPE]
342 + p_vpar->pc_malformed_pictures[B_CODING_TYPE],
343 p_vpar->pc_malformed_pictures[I_CODING_TYPE],
344 p_vpar->pc_malformed_pictures[P_CODING_TYPE],
345 p_vpar->pc_malformed_pictures[B_CODING_TYPE] );
346 #define S p_vpar->sequence
347 msg_Dbg( p_vpar->p_fifo, "%s stream (%dx%d), %d.%d pi/s",
348 S.b_mpeg2 ? "MPEG-2" : "MPEG-1",
349 S.i_width, S.i_height, S.i_frame_rate/1001,
350 S.i_frame_rate % 1001 );
351 msg_Dbg( p_vpar->p_fifo, "%s, %s, matrix_coeff: %d",
352 S.b_progressive ? "Progressive" : "Non-progressive",
353 S.i_scalable_mode ? "scalable" : "non-scalable",
354 S.i_matrix_coefficients );
357 /* Dispose of matrices if they have been allocated. */
358 if( p_vpar->sequence.intra_quant.b_allocated )
360 free( p_vpar->sequence.intra_quant.pi_matrix );
362 if( p_vpar->sequence.nonintra_quant.b_allocated )
364 free( p_vpar->sequence.nonintra_quant.pi_matrix) ;
366 if( p_vpar->sequence.chroma_intra_quant.b_allocated )
368 free( p_vpar->sequence.chroma_intra_quant.pi_matrix );
370 if( p_vpar->sequence.chroma_nonintra_quant.b_allocated )
372 free( p_vpar->sequence.chroma_nonintra_quant.pi_matrix );
375 vpar_EndPool( p_vpar );
377 module_Unneed( p_vpar->p_fifo, p_vpar->p_idct );
378 module_Unneed( p_vpar->p_fifo, p_vpar->p_motion );
380 CloseBitstream( &p_vpar->bit_stream );
384 /*****************************************************************************
385 * BitstreamCallback: Import parameters from the new data/PES packet
386 *****************************************************************************
387 * This function is called by input's NextDataPacket.
388 *****************************************************************************/
389 static void BitstreamCallback ( bit_stream_t * p_bit_stream,
390 vlc_bool_t b_new_pes )
392 vpar_thread_t * p_vpar = (vpar_thread_t *)p_bit_stream->p_callback_arg;
396 p_vpar->sequence.i_current_rate =
397 p_bit_stream->p_pes->i_rate;
399 if( p_bit_stream->p_pes->b_discontinuity )
401 /* Escape the current picture and reset the picture predictors. */
402 p_vpar->sequence.b_expect_discontinuity = 1;
403 p_vpar->picture.b_error = 1;
407 if( p_bit_stream->p_data->b_discard_payload )
409 /* 1 packet messed up, trash the slice. */
410 p_vpar->picture.b_error = 1;