]> git.sesse.net Git - vlc/blob - plugins/mpeg_vdec/video_parser.c
All decoders (audio, video, subtitles) are now modules.
[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.1 2001/11/13 12:09:18 henri 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
129     intf_DbgMsg( "vpar debug: video parser thread created. Initializing..." );
130
131     /* Allocate the memory needed to store the thread's structure */
132     if ( (p_vpar = (vpar_thread_t *)malloc( sizeof(vpar_thread_t) )) == NULL )
133     {
134         intf_ErrMsg( "vpar error: not enough memory "
135                      "for vpar_CreateThread() to create the new thread");
136         return( -1 );
137     }
138
139     /*
140      * Initialize the thread properties
141      */
142     p_vpar->p_fifo = p_config->p_decoder_fifo;
143     p_vpar->p_config = p_config;
144     p_vpar->p_vout = NULL;
145
146     /*
147      * Initialize thread
148      */
149     p_vpar->p_fifo->b_error = mpeg_vdec_Init( p_vpar );
150      
151     /*
152      * Main loop - it is not executed if an error occured during
153      * initialization
154      */
155     while( (!p_vpar->p_fifo->b_die) && (!p_vpar->p_fifo->b_error) )
156     {
157         /* Find the next sequence header in the stream */
158         p_vpar->p_fifo->b_error = vpar_NextSequenceHeader( p_vpar );
159
160         while( (!p_vpar->p_fifo->b_die) && (!p_vpar->p_fifo->b_error) )
161         {
162             p_vpar->c_loops++;
163
164             /* Parse the next sequence, group or picture header */
165             if( vpar_ParseHeader( p_vpar ) )
166             {
167                 /* End of sequence */
168                 break;
169             }
170         }
171     }
172
173     /*
174      * Error loop
175      */
176     if( p_vpar->p_fifo->b_error )
177     {
178         mpeg_vdec_ErrorThread( p_vpar );
179     }
180
181     /* End of thread */
182     mpeg_vdec_EndThread( p_vpar );
183
184     if( p_vpar->p_fifo->b_error )
185     {
186         return( -1 );
187     }
188    
189     return( 0 );
190     
191
192
193 /*****************************************************************************
194  * mpeg_vdec_Init: initialize vpar output thread
195  *****************************************************************************
196  * This function is called from mpeg_vdec_Run and performs the second step 
197  * of the initialization. It returns 0 on success. Note that the thread's 
198  * flag are not modified inside this function.
199  *****************************************************************************/
200 static int mpeg_vdec_Init( vpar_thread_t *p_vpar )
201 {
202     /*
203      * Choose the best motion compensation module
204      */
205     p_vpar->p_motion_module = module_Need( MODULE_CAPABILITY_MOTION, NULL );
206
207     if( p_vpar->p_motion_module == NULL )
208     {
209         intf_ErrMsg( "vpar error: no suitable motion compensation module" );
210         free( p_vpar );
211         return( -1 );
212     }
213
214 #define f ( p_vpar->p_motion_module->p_functions->motion.functions.motion )
215     memcpy( p_vpar->pool.ppppf_motion, f.ppppf_motion, sizeof(void *) * 16 );
216 #undef f
217
218     /*
219      * Choose the best IDCT module
220      */
221     p_vpar->p_idct_module = module_Need( MODULE_CAPABILITY_IDCT, NULL );
222
223     if( p_vpar->p_idct_module == NULL )
224     {
225         intf_ErrMsg( "vpar error: no suitable IDCT module" );
226         module_Unneed( p_vpar->p_motion_module );
227         free( p_vpar );
228         return( -1 );
229     }
230
231 #define f p_vpar->p_idct_module->p_functions->idct.functions.idct
232     p_vpar->pool.pf_idct_init   = f.pf_idct_init;
233     p_vpar->pf_sparse_idct_add  = f.pf_sparse_idct_add;
234     p_vpar->pf_idct_add         = f.pf_idct_add;
235     p_vpar->pf_sparse_idct_copy = f.pf_sparse_idct_copy;
236     p_vpar->pf_idct_copy        = f.pf_idct_copy;
237     p_vpar->pf_norm_scan        = f.pf_norm_scan;
238 #undef f
239
240     /* Initialize input bitstream */
241     p_vpar->p_config->pf_init_bit_stream( &p_vpar->bit_stream,
242         p_vpar->p_config->p_decoder_fifo, BitstreamCallback,
243         (void *)p_vpar );
244
245     /* Initialize parsing data */
246     p_vpar->sequence.p_forward = NULL;
247     p_vpar->sequence.p_backward = NULL;
248     p_vpar->sequence.intra_quant.b_allocated = 0;
249     p_vpar->sequence.nonintra_quant.b_allocated = 0;
250     p_vpar->sequence.chroma_intra_quant.b_allocated = 0;
251     p_vpar->sequence.chroma_nonintra_quant.b_allocated = 0;
252     p_vpar->sequence.i_matrix_coefficients = 1;
253     p_vpar->sequence.next_pts = p_vpar->sequence.next_dts = 0;
254     p_vpar->sequence.b_expect_discontinuity = 0;
255
256     /* Initialize copyright information */
257     p_vpar->sequence.b_copyright_flag = 0;
258     p_vpar->sequence.b_original = 0;
259     p_vpar->sequence.i_copyright_id = 0;
260     p_vpar->sequence.i_copyright_nb = 0;
261
262     p_vpar->picture.p_picture = NULL;
263     p_vpar->picture.i_current_structure = 0;
264
265     /* Initialize other properties */
266     p_vpar->c_loops = 0;
267     p_vpar->c_sequences = 0;
268     memset(p_vpar->pc_pictures, 0, sizeof(p_vpar->pc_pictures));
269     memset(p_vpar->pc_decoded_pictures, 0, sizeof(p_vpar->pc_decoded_pictures));
270     memset(p_vpar->pc_malformed_pictures, 0,
271            sizeof(p_vpar->pc_malformed_pictures));
272     vpar_InitScanTable( p_vpar );
273
274     /*
275      * Initialize the synchro properties
276      */
277     vpar_SynchroInit( p_vpar );
278
279     /* Spawn optional video decoder threads */
280     vpar_InitPool( p_vpar );
281
282     /* Mark thread as running and return */
283     intf_DbgMsg("vpar debug: mpeg_vdec_Init(%p) succeeded", p_vpar);
284     return( 0 );
285 }
286
287 /*****************************************************************************
288  * mpeg_vdec_ErrorThread: RunThread() error loop
289  *****************************************************************************
290  * This function is called when an error occured during thread main's loop. The
291  * thread can still receive feed, but must be ready to terminate as soon as
292  * possible.
293  *****************************************************************************/
294 static void mpeg_vdec_ErrorThread( vpar_thread_t *p_vpar )
295 {
296     /* We take the lock, because we are going to read/write the start/end
297      * indexes of the decoder fifo */
298     vlc_mutex_lock( &p_vpar->p_fifo->data_lock );
299
300     /* Wait until a `die' order is sent */
301     while( !p_vpar->p_fifo->b_die )
302     {
303         /* Trash all received PES packets */
304         while( !DECODER_FIFO_ISEMPTY(*p_vpar->p_fifo) )
305         {
306             p_vpar->p_fifo->pf_delete_pes( p_vpar->p_fifo->p_packets_mgt,
307                                   DECODER_FIFO_START(*p_vpar->p_fifo) );
308             DECODER_FIFO_INCSTART( *p_vpar->p_fifo );
309         }
310
311         /* Waiting for the input thread to put new PES packets in the fifo */
312         vlc_cond_wait( &p_vpar->p_fifo->data_wait, &p_vpar->p_fifo->data_lock );
313     }
314
315     /* We can release the lock before leaving */
316     vlc_mutex_unlock( &p_vpar->p_fifo->data_lock );
317 }
318
319 /*****************************************************************************
320  * mpeg_vdec_EndThread: thread destruction
321  *****************************************************************************
322  * This function is called when the thread ends after a sucessful
323  * initialization.
324  *****************************************************************************/
325 static void mpeg_vdec_EndThread( vpar_thread_t *p_vpar )
326 {
327     intf_DbgMsg("vpar debug: destroying video parser thread %p", p_vpar);
328
329     /* Release used video buffers. */
330     if( p_vpar->sequence.p_forward != NULL )
331     {
332         vout_UnlinkPicture( p_vpar->p_vout, p_vpar->sequence.p_forward );
333     }
334     if( p_vpar->sequence.p_backward != NULL )
335     {
336         vout_DatePicture( p_vpar->p_vout, p_vpar->sequence.p_backward,
337                           vpar_SynchroDate( p_vpar ) );
338         vout_UnlinkPicture( p_vpar->p_vout, p_vpar->sequence.p_backward );
339     }
340     if( p_vpar->picture.p_picture != NULL )
341     {
342         vout_DestroyPicture( p_vpar->p_vout, p_vpar->picture.p_picture );
343     }
344
345     if( p_main->b_stats )
346     {
347 #ifdef HAVE_SYS_TIMES_H
348         struct tms cpu_usage;
349         times( &cpu_usage );
350 #endif
351
352         intf_StatMsg( "vpar stats: %d loops among %d sequence(s)",
353                       p_vpar->c_loops, p_vpar->c_sequences );
354
355 #ifdef HAVE_SYS_TIMES_H
356         intf_StatMsg( "vpar stats: cpu usage (user: %d, system: %d)",
357                       cpu_usage.tms_utime, cpu_usage.tms_stime );
358 #endif
359
360         intf_StatMsg( "vpar stats: Read %d frames/fields (I %d/P %d/B %d)",
361                       p_vpar->pc_pictures[I_CODING_TYPE]
362                       + p_vpar->pc_pictures[P_CODING_TYPE]
363                       + p_vpar->pc_pictures[B_CODING_TYPE],
364                       p_vpar->pc_pictures[I_CODING_TYPE],
365                       p_vpar->pc_pictures[P_CODING_TYPE],
366                       p_vpar->pc_pictures[B_CODING_TYPE] );
367         intf_StatMsg( "vpar stats: Decoded %d frames/fields (I %d/P %d/B %d)",
368                       p_vpar->pc_decoded_pictures[I_CODING_TYPE]
369                       + p_vpar->pc_decoded_pictures[P_CODING_TYPE]
370                       + p_vpar->pc_decoded_pictures[B_CODING_TYPE],
371                       p_vpar->pc_decoded_pictures[I_CODING_TYPE],
372                       p_vpar->pc_decoded_pictures[P_CODING_TYPE],
373                       p_vpar->pc_decoded_pictures[B_CODING_TYPE] );
374         intf_StatMsg( "vpar stats: Read %d malformed frames/fields (I %d/P %d/B %d)",
375                       p_vpar->pc_malformed_pictures[I_CODING_TYPE]
376                       + p_vpar->pc_malformed_pictures[P_CODING_TYPE]
377                       + p_vpar->pc_malformed_pictures[B_CODING_TYPE],
378                       p_vpar->pc_malformed_pictures[I_CODING_TYPE],
379                       p_vpar->pc_malformed_pictures[P_CODING_TYPE],
380                       p_vpar->pc_malformed_pictures[B_CODING_TYPE] );
381 #define S   p_vpar->sequence
382         intf_StatMsg( "vpar info: %s stream (%dx%d), %d.%d pi/s",
383                       S.b_mpeg2 ? "MPEG-2" : "MPEG-1",
384                       S.i_width, S.i_height, S.i_frame_rate/1001,
385                       S.i_frame_rate % 1001 );
386         intf_StatMsg( "vpar info: %s, %s, matrix_coeff: %d",
387                       S.b_progressive ? "Progressive" : "Non-progressive",
388                       S.i_scalable_mode ? "scalable" : "non-scalable",
389                       S.i_matrix_coefficients );
390 #undef S
391     }
392
393     /* Dispose of matrices if they have been allocated. */
394     if( p_vpar->sequence.intra_quant.b_allocated )
395     {
396         free( p_vpar->sequence.intra_quant.pi_matrix );
397     }
398     if( p_vpar->sequence.nonintra_quant.b_allocated )
399     {
400         free( p_vpar->sequence.nonintra_quant.pi_matrix) ;
401     }
402     if( p_vpar->sequence.chroma_intra_quant.b_allocated )
403     {
404         free( p_vpar->sequence.chroma_intra_quant.pi_matrix );
405     }
406     if( p_vpar->sequence.chroma_nonintra_quant.b_allocated )
407     {
408         free( p_vpar->sequence.chroma_nonintra_quant.pi_matrix );
409     }
410
411     vpar_EndPool( p_vpar );
412
413     free( p_vpar->p_config );
414
415     module_Unneed( p_vpar->p_idct_module );
416     module_Unneed( p_vpar->p_motion_module );
417
418     free( p_vpar );
419
420     intf_DbgMsg("vpar debug: EndThread(%p)", p_vpar);
421 }
422
423 /*****************************************************************************
424  * BitstreamCallback: Import parameters from the new data/PES packet
425  *****************************************************************************
426  * This function is called by input's NextDataPacket.
427  *****************************************************************************/
428 static void BitstreamCallback ( bit_stream_t * p_bit_stream,
429                                 boolean_t b_new_pes )
430 {
431     vpar_thread_t * p_vpar = (vpar_thread_t *)p_bit_stream->p_callback_arg;
432
433     if( b_new_pes )
434     {
435         p_vpar->sequence.next_pts =
436             DECODER_FIFO_START( *p_bit_stream->p_decoder_fifo )->i_pts;
437         p_vpar->sequence.next_dts =
438             DECODER_FIFO_START( *p_bit_stream->p_decoder_fifo )->i_dts;
439         p_vpar->sequence.i_current_rate =
440             DECODER_FIFO_START( *p_bit_stream->p_decoder_fifo )->i_rate;
441
442         if( DECODER_FIFO_START( *p_bit_stream->p_decoder_fifo )->b_discontinuity )
443         {
444 #ifdef TRACE_VPAR
445             intf_DbgMsg( "Discontinuity in BitstreamCallback" );
446 #endif
447             /* Escape the current picture and reset the picture predictors. */
448             p_vpar->sequence.b_expect_discontinuity = 1;
449             p_vpar->picture.b_error = 1;
450         }
451     }
452
453     if( p_bit_stream->p_data->b_discard_payload )
454     {
455 #ifdef TRACE_VPAR
456         intf_DbgMsg( "Discard payload in BitstreamCallback" );
457 #endif
458         /* 1 packet messed up, trash the slice. */
459         p_vpar->picture.b_error = 1;
460     }
461 }