1 /*****************************************************************************
2 * video_parser.c : video parser thread
3 *****************************************************************************
4 * Copyright (C) 1999, 2000 VideoLAN
6 * Authors: Christophe Massiot <massiot@via.ecp.fr>
7 * Samuel Hocevar <sam@via.ecp.fr>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
22 *****************************************************************************/
24 /* FIXME: passer en terminate/destroy avec les signaux supplémentaires ?? */
26 /*****************************************************************************
28 *****************************************************************************/
31 #include <stdlib.h> /* malloc(), free() */
32 #include <unistd.h> /* getpid() */
33 #include <sys/types.h> /* on BSD, uio.h needs types.h */
34 #include <sys/uio.h> /* "input.h" */
45 #include "debug.h" /* XXX?? temporaire, requis par netlist.h */
48 #include "input_netlist.h"
49 #include "decoder_fifo.h"
51 #include "video_output.h"
53 #include "vdec_idct.h"
54 #include "video_decoder.h"
55 #include "vdec_motion.h"
57 #include "vpar_blocks.h"
58 #include "vpar_headers.h"
59 #include "vpar_synchro.h"
60 #include "video_parser.h"
61 #include "video_fifo.h"
66 //static int CheckConfiguration ( video_cfg_t *p_cfg );
67 static int InitThread ( vpar_thread_t *p_vpar );
68 static void RunThread ( vpar_thread_t *p_vpar );
69 static void ErrorThread ( vpar_thread_t *p_vpar );
70 static void EndThread ( vpar_thread_t *p_vpar );
72 /*****************************************************************************
73 * vpar_CreateThread: create a generic parser thread
74 *****************************************************************************
75 * This function creates a new video parser thread, and returns a pointer
76 * to its description. On error, it returns NULL.
77 * Following configuration properties are used:
79 *****************************************************************************/
81 #include "interface.h"
82 extern main_t * p_main;
84 vpar_thread_t * vpar_CreateThread( /* video_cfg_t *p_cfg, */ input_thread_t *p_input /*,
85 vout_thread_t *p_vout, int *pi_status */ )
87 vpar_thread_t * p_vpar;
89 intf_DbgMsg( "vpar debug: creating video parser thread\n" );
91 /* Allocate the memory needed to store the thread's structure */
92 if ( (p_vpar = (vpar_thread_t *)malloc( sizeof(vpar_thread_t) )) == NULL )
94 intf_ErrMsg( "vpar error: not enough memory "
95 "for vpar_CreateThread() to create the new thread\n");
100 * Initialize the thread properties
106 * Initialize the input properties
108 /* Initialize the decoder fifo's data lock and conditional variable
109 * and set its buffer as empty */
110 vlc_mutex_init( &p_vpar->fifo.data_lock );
111 vlc_cond_init( &p_vpar->fifo.data_wait );
112 p_vpar->fifo.i_start = 0;
113 p_vpar->fifo.i_end = 0;
114 /* Initialize the bit stream structure */
115 p_vpar->bit_stream.p_input = p_input;
116 p_vpar->bit_stream.p_decoder_fifo = &p_vpar->fifo;
117 p_vpar->bit_stream.fifo.buffer = 0;
118 p_vpar->bit_stream.fifo.i_available = 0;
121 p_vpar->p_vout = p_main->p_intf->p_vout;
123 /* Spawn the video parser thread */
124 if ( vlc_thread_create( &p_vpar->thread_id, "video parser",
125 (vlc_thread_func_t)RunThread, (void *)p_vpar ) )
127 intf_ErrMsg("vpar error: can't spawn video parser thread\n");
132 intf_DbgMsg("vpar debug: video parser thread (%p) created\n", p_vpar);
136 /*****************************************************************************
137 * vpar_DestroyThread: destroy a generic parser thread
138 *****************************************************************************
139 * Destroy a terminated thread. This function will return 0 if the thread could
140 * be destroyed, and non 0 else. The last case probably means that the thread
141 * was still active, and another try may succeed.
142 *****************************************************************************/
143 void vpar_DestroyThread( vpar_thread_t *p_vpar /*, int *pi_status */ )
145 intf_DbgMsg( "vpar debug: requesting termination of "
146 "video parser thread %p\n", p_vpar);
148 /* Ask thread to kill itself */
150 /* Make sure the parser thread leaves the GetByte() function */
151 vlc_mutex_lock( &(p_vpar->fifo.data_lock) );
152 vlc_cond_signal( &(p_vpar->fifo.data_wait) );
153 vlc_mutex_unlock( &(p_vpar->fifo.data_lock) );
155 /* Waiting for the parser thread to exit */
156 /* Remove this as soon as the "status" flag is implemented */
157 vlc_thread_join( p_vpar->thread_id );
160 /* following functions are local */
162 /*****************************************************************************
163 * CheckConfiguration: check vpar_CreateThread() configuration
164 *****************************************************************************
165 * Set default parameters where required. In DEBUG mode, check if configuration
167 *****************************************************************************/
169 static int CheckConfiguration( video_cfg_t *p_cfg )
177 /*****************************************************************************
178 * InitThread: initialize vpar output thread
179 *****************************************************************************
180 * This function is called from RunThread and performs the second step of the
181 * initialization. It returns 0 on success. Note that the thread's flag are not
182 * modified inside this function.
183 *****************************************************************************/
184 static int InitThread( vpar_thread_t *p_vpar )
190 intf_DbgMsg("vpar debug: initializing video parser thread %p\n", p_vpar);
192 /* Our first job is to initialize the bit stream structure with the
193 * beginning of the input stream */
194 vlc_mutex_lock( &p_vpar->fifo.data_lock );
195 while ( DECODER_FIFO_ISEMPTY(p_vpar->fifo) )
199 vlc_mutex_unlock( &p_vpar->fifo.data_lock );
202 vlc_cond_wait( &p_vpar->fifo.data_wait, &p_vpar->fifo.data_lock );
204 p_vpar->bit_stream.p_ts = DECODER_FIFO_START( p_vpar->fifo )->p_first_ts;
205 p_vpar->bit_stream.p_byte = p_vpar->bit_stream.p_ts->buffer
206 + p_vpar->bit_stream.p_ts->i_payload_start;
207 p_vpar->bit_stream.p_end = p_vpar->bit_stream.p_ts->buffer
208 + p_vpar->bit_stream.p_ts->i_payload_end;
209 vlc_mutex_unlock( &p_vpar->fifo.data_lock );
211 /* Initialize parsing data */
212 p_vpar->sequence.p_forward = NULL;
213 p_vpar->sequence.p_backward = NULL;
214 p_vpar->sequence.intra_quant.b_allocated = 0;
215 p_vpar->sequence.nonintra_quant.b_allocated = 0;
216 p_vpar->sequence.chroma_intra_quant.b_allocated = 0;
217 p_vpar->sequence.chroma_nonintra_quant.b_allocated = 0;
219 /* Initialize copyright information */
220 p_vpar->sequence.b_copyright_flag = 0;
221 p_vpar->sequence.b_original = 0;
222 p_vpar->sequence.i_copyright_id = 0;
223 p_vpar->sequence.i_copyright_nb = 0;
225 p_vpar->picture.p_picture = NULL;
226 p_vpar->picture.i_current_structure = 0;
228 /* Initialize other properties */
231 p_vpar->c_sequences = 0;
232 memset(p_vpar->pc_pictures, 0, sizeof(p_vpar->pc_pictures));
233 memset(p_vpar->pc_decoded_pictures, 0, sizeof(p_vpar->pc_decoded_pictures));
234 memset(p_vpar->pc_malformed_pictures, 0,
235 sizeof(p_vpar->pc_malformed_pictures));
238 /* Initialize video FIFO */
239 vpar_InitFIFO( p_vpar );
241 memset( p_vpar->pp_vdec, 0, NB_VDEC*sizeof(vdec_thread_t *) );
244 /* Spawn video_decoder threads */
245 /* FIXME: modify the number of vdecs at runtime ?? */
246 for( i_dummy = 0; i_dummy < NB_VDEC; i_dummy++ )
248 if( (p_vpar->pp_vdec[i_dummy] = vdec_CreateThread( p_vpar )) == NULL )
254 /* Fake a video_decoder thread */
255 if( (p_vpar->pp_vdec[0] = (vdec_thread_t *)malloc(sizeof( vdec_thread_t )))
256 == NULL || vdec_InitThread( p_vpar->pp_vdec[0] ) )
260 p_vpar->pp_vdec[0]->b_die = 0;
261 p_vpar->pp_vdec[0]->b_error = 0;
262 p_vpar->pp_vdec[0]->p_vpar = p_vpar;
264 /* Re-nice ourself */
265 if( nice(VDEC_NICE) == -1 )
267 intf_WarnMsg( 2, "vpar warning : couldn't nice() (%s)\n",
272 /* Initialize lookup tables */
273 #if defined(MPEG2_COMPLIANT) && !defined(VDEC_DFT)
274 vpar_InitCrop( p_vpar );
276 vpar_InitMbAddrInc( p_vpar );
277 vpar_InitDCTTables( p_vpar );
278 vpar_InitPMBType( p_vpar );
279 vpar_InitBMBType( p_vpar );
280 vpar_InitDCTTables( p_vpar );
283 * Initialize the synchro properties
285 vpar_SynchroInit( p_vpar );
287 /* Mark thread as running and return */
288 intf_DbgMsg("vpar debug: InitThread(%p) succeeded\n", p_vpar);
292 /*****************************************************************************
293 * RunThread: generic parser thread
294 *****************************************************************************
295 * Video parser thread. This function only returns when the thread is
297 *****************************************************************************/
298 static void RunThread( vpar_thread_t *p_vpar )
300 intf_DbgMsg("vpar debug: running video parser thread (%p) (pid == %i)\n", p_vpar, getpid());
305 p_vpar->b_error = InitThread( p_vpar );
310 * Main loop - it is not executed if an error occured during
313 while( (!p_vpar->b_die) && (!p_vpar->b_error) )
315 /* Find the next sequence header in the stream */
316 p_vpar->b_error = vpar_NextSequenceHeader( p_vpar );
318 while( (!p_vpar->b_die) && (!p_vpar->b_error) )
323 /* Parse the next sequence, group or picture header */
324 if( vpar_ParseHeader( p_vpar ) )
326 /* End of sequence */
335 if( p_vpar->b_error )
337 ErrorThread( p_vpar );
346 /*****************************************************************************
347 * ErrorThread: RunThread() error loop
348 *****************************************************************************
349 * This function is called when an error occured during thread main's loop. The
350 * thread can still receive feed, but must be ready to terminate as soon as
352 *****************************************************************************/
353 static void ErrorThread( vpar_thread_t *p_vpar )
355 /* We take the lock, because we are going to read/write the start/end
356 * indexes of the decoder fifo */
357 vlc_mutex_lock( &p_vpar->fifo.data_lock );
359 /* Wait until a `die' order is sent */
360 while( !p_vpar->b_die )
362 /* Trash all received PES packets */
363 while( !DECODER_FIFO_ISEMPTY(p_vpar->fifo) )
365 input_NetlistFreePES( p_vpar->bit_stream.p_input,
366 DECODER_FIFO_START(p_vpar->fifo) );
367 DECODER_FIFO_INCSTART( p_vpar->fifo );
370 /* Waiting for the input thread to put new PES packets in the fifo */
371 vlc_cond_wait( &p_vpar->fifo.data_wait, &p_vpar->fifo.data_lock );
374 /* We can release the lock before leaving */
375 vlc_mutex_unlock( &p_vpar->fifo.data_lock );
378 /*****************************************************************************
379 * EndThread: thread destruction
380 *****************************************************************************
381 * This function is called when the thread ends after a sucessful
383 *****************************************************************************/
384 static void EndThread( vpar_thread_t *p_vpar )
390 intf_DbgMsg("vpar debug: destroying video parser thread %p\n", p_vpar);
393 /* Check for remaining PES packets */
398 intf_Msg("vpar stats: %d loops among %d sequence(s)\n",
399 p_vpar->c_loops, p_vpar->c_sequences);
400 intf_Msg("vpar stats: Read %d frames/fields (I %d/P %d/B %d)\n",
401 p_vpar->pc_pictures[I_CODING_TYPE]
402 + p_vpar->pc_pictures[P_CODING_TYPE]
403 + p_vpar->pc_pictures[B_CODING_TYPE],
404 p_vpar->pc_pictures[I_CODING_TYPE],
405 p_vpar->pc_pictures[P_CODING_TYPE],
406 p_vpar->pc_pictures[B_CODING_TYPE]);
407 intf_Msg("vpar stats: Decoded %d frames/fields (I %d/P %d/B %d)\n",
408 p_vpar->pc_decoded_pictures[I_CODING_TYPE]
409 + p_vpar->pc_decoded_pictures[P_CODING_TYPE]
410 + p_vpar->pc_decoded_pictures[B_CODING_TYPE],
411 p_vpar->pc_decoded_pictures[I_CODING_TYPE],
412 p_vpar->pc_decoded_pictures[P_CODING_TYPE],
413 p_vpar->pc_decoded_pictures[B_CODING_TYPE]);
414 intf_Msg("vpar stats: Read %d malformed frames/fields (I %d/P %d/B %d)\n",
415 p_vpar->pc_malformed_pictures[I_CODING_TYPE]
416 + p_vpar->pc_malformed_pictures[P_CODING_TYPE]
417 + p_vpar->pc_malformed_pictures[B_CODING_TYPE],
418 p_vpar->pc_malformed_pictures[I_CODING_TYPE],
419 p_vpar->pc_malformed_pictures[P_CODING_TYPE],
420 p_vpar->pc_malformed_pictures[B_CODING_TYPE]);
423 /* Destroy thread structures allocated by InitThread */
424 // vout_DestroyStream( p_vpar->p_vout, p_vpar->i_stream );
427 /* Dispose of matrices if they have been allocated. */
428 if( p_vpar->sequence.intra_quant.b_allocated )
430 free( p_vpar->sequence.intra_quant.pi_matrix );
432 if( p_vpar->sequence.nonintra_quant.b_allocated )
434 free( p_vpar->sequence.nonintra_quant.pi_matrix) ;
436 if( p_vpar->sequence.chroma_intra_quant.b_allocated )
438 free( p_vpar->sequence.chroma_intra_quant.pi_matrix );
440 if( p_vpar->sequence.chroma_nonintra_quant.b_allocated )
442 free( p_vpar->sequence.chroma_nonintra_quant.pi_matrix );
446 /* Destroy vdec threads */
447 for( i_dummy = 0; i_dummy < NB_VDEC; i_dummy++ )
449 if( p_vpar->pp_vdec[i_dummy] != NULL )
450 vdec_DestroyThread( p_vpar->pp_vdec[i_dummy] );
455 free( p_vpar->pp_vdec[0] );
460 intf_DbgMsg("vpar debug: EndThread(%p)\n", p_vpar);