]> git.sesse.net Git - vlc/blob - plugins/mpeg_vdec/video_parser.c
Don`t use long long, use u64/s64 (int_types.h).
[vlc] / plugins / mpeg_vdec / video_parser.c
1 /*****************************************************************************
2  * video_parser.c : video parser thread
3  *****************************************************************************
4  * Copyright (C) 1999, 2000 VideoLAN
5  * $Id: video_parser.c,v 1.3 2001/11/21 22:33:03 jlj Exp $
6  *
7  * Authors: Christophe Massiot <massiot@via.ecp.fr>
8  *          Samuel Hocevar <sam@via.ecp.fr>
9  *
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.
14  * 
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.
19  *
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  *****************************************************************************/
24
25 #define MODULE_NAME mpeg_vdec
26 #include "modules_inner.h"
27
28 /*****************************************************************************
29  * Preamble
30  *****************************************************************************/
31 #include "defs.h"
32
33 #include <stdlib.h>                                      /* malloc(), free() */
34
35 #ifdef HAVE_UNISTD_H
36 #include <unistd.h>                                              /* getpid() */
37 #endif
38
39 #include <errno.h>
40 #include <string.h>
41
42 #ifdef HAVE_SYS_TIMES_H
43 #   include <sys/times.h>
44 #endif
45
46 #include "config.h"
47 #include "common.h"
48 #include "threads.h"
49 #include "mtime.h"
50 #include "modules.h"
51 #include "intf_msg.h"
52
53 #include "main.h"
54
55 #include "video.h"
56 #include "video_output.h"
57
58 #include "modules_export.h"
59 #include "stream_control.h"
60 #include "input_ext-dec.h"
61
62
63 #include "vdec_ext-plugins.h"
64 #include "vpar_pool.h"
65 #include "video_parser.h"
66
67
68 /*
69  * Local prototypes
70  */
71 static int      mpeg_vdec_Probe         ( probedata_t * );
72 static int      mpeg_vdec_Run           ( decoder_config_t * );
73 static int      mpeg_vdec_Init          ( vpar_thread_t * );
74 static void     mpeg_vdec_ErrorThread   ( vpar_thread_t * );
75 static void     mpeg_vdec_EndThread     ( vpar_thread_t * );
76 static void     BitstreamCallback       ( bit_stream_t *, boolean_t );
77
78 /*****************************************************************************
79  * Capabilities
80  *****************************************************************************/
81 void _M( vdec_getfunctions )( function_list_t * p_function_list )
82 {
83     p_function_list->pf_probe = mpeg_vdec_Probe;
84     p_function_list->functions.dec.pf_RunThread = mpeg_vdec_Run;
85 }
86
87 /*****************************************************************************
88  * Build configuration tree.
89  *****************************************************************************/
90 MODULE_CONFIG_START
91 ADD_WINDOW( "Configuration for MPEG video decoder module" )
92     ADD_COMMENT( "Nothing to configure" )
93 MODULE_CONFIG_STOP
94
95 MODULE_INIT_START
96     p_module->i_capabilities = MODULE_CAPABILITY_DEC;
97     p_module->psz_longname = "MPEG I/II video decoder module";
98 MODULE_INIT_STOP
99
100 MODULE_ACTIVATE_START
101     _M( vdec_getfunctions )( &p_module->p_functions->dec );
102 MODULE_ACTIVATE_STOP
103
104 MODULE_DEACTIVATE_START
105 MODULE_DEACTIVATE_STOP
106
107
108 /*****************************************************************************
109  * mpeg_vdec_Probe: probe the decoder and return score
110  *****************************************************************************
111  * Tries to launch a decoder and return score so that the interface is able 
112  * to chose.
113  *****************************************************************************/
114 static int mpeg_vdec_Probe( probedata_t *p_data )
115 {
116     if( p_data->i_type == MPEG1_VIDEO_ES || p_data->i_type == MPEG2_VIDEO_ES )
117         return( 50 );
118     else
119         return( 0 );
120 }
121
122 /*****************************************************************************
123  * mpeg_vdec_Run: this function is called just after the thread is created
124  *****************************************************************************/
125 static int mpeg_vdec_Run ( decoder_config_t * p_config )
126 {
127     vpar_thread_t *     p_vpar;
128     boolean_t           b_error;
129
130     intf_DbgMsg( "vpar debug: video parser thread created. Initializing..." );
131
132     /* Allocate the memory needed to store the thread's structure */
133     if ( (p_vpar = (vpar_thread_t *)malloc( sizeof(vpar_thread_t) )) == NULL )
134     {
135         intf_ErrMsg( "vpar error: not enough memory "
136                      "for vpar_CreateThread() to create the new thread");
137         return( -1 );
138     }
139
140     /*
141      * Initialize the thread properties
142      */
143     p_vpar->p_fifo = p_config->p_decoder_fifo;
144     p_vpar->p_config = p_config;
145     p_vpar->p_vout = NULL;
146
147     /*
148      * Initialize thread
149      */
150     p_vpar->p_fifo->b_error = mpeg_vdec_Init( p_vpar );
151      
152     /*
153      * Main loop - it is not executed if an error occured during
154      * initialization
155      */
156     while( (!p_vpar->p_fifo->b_die) && (!p_vpar->p_fifo->b_error) )
157     {
158         /* Find the next sequence header in the stream */
159         p_vpar->p_fifo->b_error = vpar_NextSequenceHeader( p_vpar );
160
161         while( (!p_vpar->p_fifo->b_die) && (!p_vpar->p_fifo->b_error) )
162         {
163             p_vpar->c_loops++;
164
165             /* Parse the next sequence, group or picture header */
166             if( vpar_ParseHeader( p_vpar ) )
167             {
168                 /* End of sequence */
169                 break;
170             }
171         }
172     }
173
174     /*
175      * Error loop
176      */
177     if( ( b_error = p_vpar->p_fifo->b_error ) )
178     {
179         mpeg_vdec_ErrorThread( p_vpar );
180     }
181
182     /* End of thread */
183     mpeg_vdec_EndThread( p_vpar );
184
185     if( b_error )
186     {
187         return( -1 );
188     }
189    
190     return( 0 );
191     
192
193
194 /*****************************************************************************
195  * mpeg_vdec_Init: initialize vpar output thread
196  *****************************************************************************
197  * This function is called from mpeg_vdec_Run and performs the second step 
198  * of the initialization. It returns 0 on success. Note that the thread's 
199  * flag are not modified inside this function.
200  *****************************************************************************/
201 static int mpeg_vdec_Init( vpar_thread_t *p_vpar )
202 {
203     /*
204      * Choose the best motion compensation module
205      */
206     p_vpar->p_motion_module = module_Need( MODULE_CAPABILITY_MOTION, NULL );
207
208     if( p_vpar->p_motion_module == NULL )
209     {
210         intf_ErrMsg( "vpar error: no suitable motion compensation module" );
211         free( p_vpar );
212         return( -1 );
213     }
214
215 #define f ( p_vpar->p_motion_module->p_functions->motion.functions.motion )
216     memcpy( p_vpar->pool.ppppf_motion, f.ppppf_motion, sizeof(void *) * 16 );
217 #undef f
218
219     /*
220      * Choose the best IDCT module
221      */
222     p_vpar->p_idct_module = module_Need( MODULE_CAPABILITY_IDCT, NULL );
223
224     if( p_vpar->p_idct_module == NULL )
225     {
226         intf_ErrMsg( "vpar error: no suitable IDCT module" );
227         module_Unneed( p_vpar->p_motion_module );
228         free( p_vpar );
229         return( -1 );
230     }
231
232 #define f p_vpar->p_idct_module->p_functions->idct.functions.idct
233     p_vpar->pool.pf_idct_init   = f.pf_idct_init;
234     p_vpar->pf_sparse_idct_add  = f.pf_sparse_idct_add;
235     p_vpar->pf_idct_add         = f.pf_idct_add;
236     p_vpar->pf_sparse_idct_copy = f.pf_sparse_idct_copy;
237     p_vpar->pf_idct_copy        = f.pf_idct_copy;
238     p_vpar->pf_norm_scan        = f.pf_norm_scan;
239 #undef f
240
241     /* Initialize input bitstream */
242     p_vpar->p_config->pf_init_bit_stream( &p_vpar->bit_stream,
243         p_vpar->p_config->p_decoder_fifo, BitstreamCallback,
244         (void *)p_vpar );
245
246     /* Initialize parsing data */
247     p_vpar->sequence.p_forward = NULL;
248     p_vpar->sequence.p_backward = NULL;
249     p_vpar->sequence.intra_quant.b_allocated = 0;
250     p_vpar->sequence.nonintra_quant.b_allocated = 0;
251     p_vpar->sequence.chroma_intra_quant.b_allocated = 0;
252     p_vpar->sequence.chroma_nonintra_quant.b_allocated = 0;
253     p_vpar->sequence.i_matrix_coefficients = 1;
254     p_vpar->sequence.next_pts = p_vpar->sequence.next_dts = 0;
255     p_vpar->sequence.b_expect_discontinuity = 0;
256
257     /* Initialize copyright information */
258     p_vpar->sequence.b_copyright_flag = 0;
259     p_vpar->sequence.b_original = 0;
260     p_vpar->sequence.i_copyright_id = 0;
261     p_vpar->sequence.i_copyright_nb = 0;
262
263     p_vpar->picture.p_picture = NULL;
264     p_vpar->picture.i_current_structure = 0;
265
266     /* Initialize other properties */
267     p_vpar->c_loops = 0;
268     p_vpar->c_sequences = 0;
269     memset(p_vpar->pc_pictures, 0, sizeof(p_vpar->pc_pictures));
270     memset(p_vpar->pc_decoded_pictures, 0, sizeof(p_vpar->pc_decoded_pictures));
271     memset(p_vpar->pc_malformed_pictures, 0,
272            sizeof(p_vpar->pc_malformed_pictures));
273     vpar_InitScanTable( p_vpar );
274
275     /*
276      * Initialize the synchro properties
277      */
278     vpar_SynchroInit( p_vpar );
279
280     /* Spawn optional video decoder threads */
281     vpar_InitPool( p_vpar );
282
283     /* Mark thread as running and return */
284     intf_DbgMsg("vpar debug: mpeg_vdec_Init(%p) succeeded", p_vpar);
285     return( 0 );
286 }
287
288 /*****************************************************************************
289  * mpeg_vdec_ErrorThread: RunThread() error loop
290  *****************************************************************************
291  * This function is called when an error occured during thread main's loop. The
292  * thread can still receive feed, but must be ready to terminate as soon as
293  * possible.
294  *****************************************************************************/
295 static void mpeg_vdec_ErrorThread( vpar_thread_t *p_vpar )
296 {
297     /* We take the lock, because we are going to read/write the start/end
298      * indexes of the decoder fifo */
299     vlc_mutex_lock( &p_vpar->p_fifo->data_lock );
300
301     /* Wait until a `die' order is sent */
302     while( !p_vpar->p_fifo->b_die )
303     {
304         /* Trash all received PES packets */
305         while( !DECODER_FIFO_ISEMPTY(*p_vpar->p_fifo) )
306         {
307             p_vpar->p_fifo->pf_delete_pes( p_vpar->p_fifo->p_packets_mgt,
308                                   DECODER_FIFO_START(*p_vpar->p_fifo) );
309             DECODER_FIFO_INCSTART( *p_vpar->p_fifo );
310         }
311
312         /* Waiting for the input thread to put new PES packets in the fifo */
313         vlc_cond_wait( &p_vpar->p_fifo->data_wait, &p_vpar->p_fifo->data_lock );
314     }
315
316     /* We can release the lock before leaving */
317     vlc_mutex_unlock( &p_vpar->p_fifo->data_lock );
318 }
319
320 /*****************************************************************************
321  * mpeg_vdec_EndThread: thread destruction
322  *****************************************************************************
323  * This function is called when the thread ends after a sucessful
324  * initialization.
325  *****************************************************************************/
326 static void mpeg_vdec_EndThread( vpar_thread_t *p_vpar )
327 {
328     intf_DbgMsg("vpar debug: destroying video parser thread %p", p_vpar);
329
330     /* Release used video buffers. */
331     if( p_vpar->sequence.p_forward != NULL )
332     {
333         vout_UnlinkPicture( p_vpar->p_vout, p_vpar->sequence.p_forward );
334     }
335     if( p_vpar->sequence.p_backward != NULL )
336     {
337         vout_DatePicture( p_vpar->p_vout, p_vpar->sequence.p_backward,
338                           vpar_SynchroDate( p_vpar ) );
339         vout_UnlinkPicture( p_vpar->p_vout, p_vpar->sequence.p_backward );
340     }
341     if( p_vpar->picture.p_picture != NULL )
342     {
343         vout_DestroyPicture( p_vpar->p_vout, p_vpar->picture.p_picture );
344     }
345
346     if( p_main->b_stats )
347     {
348 #ifdef HAVE_SYS_TIMES_H
349         struct tms cpu_usage;
350         times( &cpu_usage );
351 #endif
352
353         intf_StatMsg( "vpar stats: %d loops among %d sequence(s)",
354                       p_vpar->c_loops, p_vpar->c_sequences );
355
356 #ifdef HAVE_SYS_TIMES_H
357         intf_StatMsg( "vpar stats: cpu usage (user: %d, system: %d)",
358                       cpu_usage.tms_utime, cpu_usage.tms_stime );
359 #endif
360
361         intf_StatMsg( "vpar stats: Read %d frames/fields (I %d/P %d/B %d)",
362                       p_vpar->pc_pictures[I_CODING_TYPE]
363                       + p_vpar->pc_pictures[P_CODING_TYPE]
364                       + p_vpar->pc_pictures[B_CODING_TYPE],
365                       p_vpar->pc_pictures[I_CODING_TYPE],
366                       p_vpar->pc_pictures[P_CODING_TYPE],
367                       p_vpar->pc_pictures[B_CODING_TYPE] );
368         intf_StatMsg( "vpar stats: Decoded %d frames/fields (I %d/P %d/B %d)",
369                       p_vpar->pc_decoded_pictures[I_CODING_TYPE]
370                       + p_vpar->pc_decoded_pictures[P_CODING_TYPE]
371                       + p_vpar->pc_decoded_pictures[B_CODING_TYPE],
372                       p_vpar->pc_decoded_pictures[I_CODING_TYPE],
373                       p_vpar->pc_decoded_pictures[P_CODING_TYPE],
374                       p_vpar->pc_decoded_pictures[B_CODING_TYPE] );
375         intf_StatMsg( "vpar stats: Read %d malformed frames/fields (I %d/P %d/B %d)",
376                       p_vpar->pc_malformed_pictures[I_CODING_TYPE]
377                       + p_vpar->pc_malformed_pictures[P_CODING_TYPE]
378                       + p_vpar->pc_malformed_pictures[B_CODING_TYPE],
379                       p_vpar->pc_malformed_pictures[I_CODING_TYPE],
380                       p_vpar->pc_malformed_pictures[P_CODING_TYPE],
381                       p_vpar->pc_malformed_pictures[B_CODING_TYPE] );
382 #define S   p_vpar->sequence
383         intf_StatMsg( "vpar info: %s stream (%dx%d), %d.%d pi/s",
384                       S.b_mpeg2 ? "MPEG-2" : "MPEG-1",
385                       S.i_width, S.i_height, S.i_frame_rate/1001,
386                       S.i_frame_rate % 1001 );
387         intf_StatMsg( "vpar info: %s, %s, matrix_coeff: %d",
388                       S.b_progressive ? "Progressive" : "Non-progressive",
389                       S.i_scalable_mode ? "scalable" : "non-scalable",
390                       S.i_matrix_coefficients );
391 #undef S
392     }
393
394     /* Dispose of matrices if they have been allocated. */
395     if( p_vpar->sequence.intra_quant.b_allocated )
396     {
397         free( p_vpar->sequence.intra_quant.pi_matrix );
398     }
399     if( p_vpar->sequence.nonintra_quant.b_allocated )
400     {
401         free( p_vpar->sequence.nonintra_quant.pi_matrix) ;
402     }
403     if( p_vpar->sequence.chroma_intra_quant.b_allocated )
404     {
405         free( p_vpar->sequence.chroma_intra_quant.pi_matrix );
406     }
407     if( p_vpar->sequence.chroma_nonintra_quant.b_allocated )
408     {
409         free( p_vpar->sequence.chroma_nonintra_quant.pi_matrix );
410     }
411
412     vpar_EndPool( p_vpar );
413
414     module_Unneed( p_vpar->p_idct_module );
415     module_Unneed( p_vpar->p_motion_module );
416
417     free( p_vpar );
418
419     intf_DbgMsg("vpar debug: EndThread(%p)", p_vpar);
420 }
421
422 /*****************************************************************************
423  * BitstreamCallback: Import parameters from the new data/PES packet
424  *****************************************************************************
425  * This function is called by input's NextDataPacket.
426  *****************************************************************************/
427 static void BitstreamCallback ( bit_stream_t * p_bit_stream,
428                                 boolean_t b_new_pes )
429 {
430     vpar_thread_t * p_vpar = (vpar_thread_t *)p_bit_stream->p_callback_arg;
431
432     if( b_new_pes )
433     {
434         p_vpar->sequence.next_pts =
435             DECODER_FIFO_START( *p_bit_stream->p_decoder_fifo )->i_pts;
436         p_vpar->sequence.next_dts =
437             DECODER_FIFO_START( *p_bit_stream->p_decoder_fifo )->i_dts;
438         p_vpar->sequence.i_current_rate =
439             DECODER_FIFO_START( *p_bit_stream->p_decoder_fifo )->i_rate;
440
441         if( DECODER_FIFO_START( *p_bit_stream->p_decoder_fifo )->b_discontinuity )
442         {
443 #ifdef TRACE_VPAR
444             intf_DbgMsg( "Discontinuity in BitstreamCallback" );
445 #endif
446             /* Escape the current picture and reset the picture predictors. */
447             p_vpar->sequence.b_expect_discontinuity = 1;
448             p_vpar->picture.b_error = 1;
449         }
450     }
451
452     if( p_bit_stream->p_data->b_discard_payload )
453     {
454 #ifdef TRACE_VPAR
455         intf_DbgMsg( "Discard payload in BitstreamCallback" );
456 #endif
457         /* 1 packet messed up, trash the slice. */
458         p_vpar->picture.b_error = 1;
459     }
460 }