libmpeg2.c 22.9 KB
Newer Older
gbazin's avatar
 
gbazin committed
1 2 3 4
/*****************************************************************************
 * libmpeg2.c: mpeg2 video decoder module making use of libmpeg2.
 *****************************************************************************
 * Copyright (C) 1999-2001 VideoLAN
5
 * $Id$
gbazin's avatar
 
gbazin committed
6
 *
7
 * Authors: Gildas Bazin <gbazin@videolan.org>
gbazin's avatar
 
gbazin committed
8
 *          Christophe Massiot <massiot@via.ecp.fr>
gbazin's avatar
 
gbazin committed
9 10 11 12 13
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
Sam Hocevar's avatar
Sam Hocevar committed
14
 *
gbazin's avatar
 
gbazin committed
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
#include <vlc/vlc.h>
#include <vlc/vout.h>
#include <vlc/decoder.h>

#include <mpeg2dec/mpeg2.h>

34 35
#include "vout_synchro.h"

gbazin's avatar
 
gbazin committed
36 37 38 39 40 41 42
/* Aspect ratio (ISO/IEC 13818-2 section 6.3.3, table 6-3) */
#define AR_SQUARE_PICTURE       1                           /* square pixels */
#define AR_3_4_PICTURE          2                        /* 3:4 picture (TV) */
#define AR_16_9_PICTURE         3              /* 16:9 picture (wide screen) */
#define AR_221_1_PICTURE        4                  /* 2.21:1 picture (movie) */

/*****************************************************************************
gbazin's avatar
 
gbazin committed
43
 * decoder_sys_t : libmpeg2 decoder descriptor
gbazin's avatar
 
gbazin committed
44
 *****************************************************************************/
gbazin's avatar
 
gbazin committed
45
struct decoder_sys_t
gbazin's avatar
 
gbazin committed
46 47 48 49 50 51
{
    /*
     * libmpeg2 properties
     */
    mpeg2dec_t          *p_mpeg2dec;
    const mpeg2_info_t  *p_info;
52
    vlc_bool_t          b_skip;
gbazin's avatar
 
gbazin committed
53 54 55 56 57 58

    /*
     * Input properties
     */
    mtime_t          i_previous_pts;
    mtime_t          i_current_pts;
59 60
    mtime_t          i_previous_dts;
    mtime_t          i_current_dts;
61 62
    int              i_current_rate;
    picture_t *      p_picture_to_destroy;
63 64 65 66
    vlc_bool_t       b_garbage_pic;
    vlc_bool_t       b_after_sequence_header; /* is it the next frame after
                                               * the sequence header ?    */
    vlc_bool_t       b_slice_i;             /* intra-slice refresh stream */
gbazin's avatar
 
gbazin committed
67

Laurent Aimar's avatar
Laurent Aimar committed
68 69
    vlc_bool_t      b_preroll;

gbazin's avatar
 
gbazin committed
70 71 72
    /*
     * Output properties
     */
73
    vout_synchro_t *p_synchro;
74 75
    int            i_aspect;
    mtime_t        i_last_frame_pts;
gbazin's avatar
 
gbazin committed
76

gbazin's avatar
 
gbazin committed
77
};
gbazin's avatar
 
gbazin committed
78 79 80 81

/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
gbazin's avatar
 
gbazin committed
82 83 84 85
static int  OpenDecoder( vlc_object_t * );
static void CloseDecoder( vlc_object_t * );

static picture_t *DecodeBlock( decoder_t *, block_t ** );
gbazin's avatar
 
gbazin committed
86

gbazin's avatar
 
gbazin committed
87
static picture_t *GetNewPicture( decoder_t *, uint8_t ** );
gbazin's avatar
 
gbazin committed
88

gbazin's avatar
 
gbazin committed
89 90 91 92 93
/*****************************************************************************
 * Module descriptor
 *****************************************************************************/
vlc_module_begin();
    set_description( _("MPEG I/II video decoder (using libmpeg2)") );
gbazin's avatar
 
gbazin committed
94
    set_capability( "decoder", 150 );
zorglub's avatar
zorglub committed
95 96
    set_category( CAT_INPUT );
    set_subcategory( SUBCAT_INPUT_VCODEC );
gbazin's avatar
 
gbazin committed
97
    set_callbacks( OpenDecoder, CloseDecoder );
gbazin's avatar
 
gbazin committed
98 99 100 101 102 103 104 105
    add_shortcut( "libmpeg2" );
vlc_module_end();

/*****************************************************************************
 * OpenDecoder: probe the decoder and return score
 *****************************************************************************/
static int OpenDecoder( vlc_object_t *p_this )
{
gbazin's avatar
 
gbazin committed
106
    decoder_t *p_dec = (decoder_t*)p_this;
gbazin's avatar
 
gbazin committed
107
    decoder_sys_t *p_sys;
Sam Hocevar's avatar
Sam Hocevar committed
108
    uint32_t i_accel = 0;
gbazin's avatar
 
gbazin committed
109

gbazin's avatar
 
gbazin committed
110 111
    if( p_dec->fmt_in.i_codec != VLC_FOURCC('m','p','g','v') &&
        p_dec->fmt_in.i_codec != VLC_FOURCC('m','p','g','1') &&
gbazin's avatar
 
gbazin committed
112
        /* Pinnacle hardware-mpeg1 */
gbazin's avatar
 
gbazin committed
113
        p_dec->fmt_in.i_codec != VLC_FOURCC('P','I','M','1') &&
gbazin's avatar
 
gbazin committed
114
        /* ATI Video */
gbazin's avatar
 
gbazin committed
115 116
        p_dec->fmt_in.i_codec != VLC_FOURCC('V','C','R','2') &&
        p_dec->fmt_in.i_codec != VLC_FOURCC('m','p','g','2') )
gbazin's avatar
 
gbazin committed
117 118 119 120
    {
        return VLC_EGENERIC;
    }

gbazin's avatar
 
gbazin committed
121
    /* Allocate the memory needed to store the decoder's structure */
gbazin's avatar
 
gbazin committed
122
    if( ( p_dec->p_sys = p_sys =
gbazin's avatar
 
gbazin committed
123
          (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
gbazin's avatar
 
gbazin committed
124
    {
gbazin's avatar
 
gbazin committed
125 126
        msg_Err( p_dec, "out of memory" );
        return VLC_EGENERIC;
gbazin's avatar
 
gbazin committed
127 128 129
    }

    /* Initialize the thread properties */
gbazin's avatar
 
gbazin committed
130 131 132 133 134 135
    memset( p_sys, 0, sizeof(decoder_sys_t) );
    p_sys->p_mpeg2dec = NULL;
    p_sys->p_synchro  = NULL;
    p_sys->p_info     = NULL;
    p_sys->i_current_pts  = 0;
    p_sys->i_previous_pts = 0;
136 137
    p_sys->i_current_dts  = 0;
    p_sys->i_previous_dts = 0;
gbazin's avatar
 
gbazin committed
138 139 140 141
    p_sys->p_picture_to_destroy = NULL;
    p_sys->b_garbage_pic = 0;
    p_sys->b_slice_i  = 0;
    p_sys->b_skip     = 0;
Laurent Aimar's avatar
Laurent Aimar committed
142
    p_sys->b_preroll = VLC_FALSE;
gbazin's avatar
 
gbazin committed
143

Christophe Massiot's avatar
Christophe Massiot committed
144
#if defined( __i386__ ) || defined( __x86_64__ )
Sam Hocevar's avatar
Sam Hocevar committed
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
    if( p_dec->p_libvlc->i_cpu & CPU_CAPABILITY_MMX )
    {
        i_accel |= MPEG2_ACCEL_X86_MMX;
    }

    if( p_dec->p_libvlc->i_cpu & CPU_CAPABILITY_3DNOW )
    {
        i_accel |= MPEG2_ACCEL_X86_3DNOW;
    }

    if( p_dec->p_libvlc->i_cpu & CPU_CAPABILITY_MMXEXT )
    {
        i_accel |= MPEG2_ACCEL_X86_MMXEXT;
    }

#elif defined( __powerpc__ ) || defined( SYS_DARWIN )
    if( p_dec->p_libvlc->i_cpu & CPU_CAPABILITY_ALTIVEC )
    {
        i_accel |= MPEG2_ACCEL_PPC_ALTIVEC;
    }

#else
    /* If we do not know this CPU, trust libmpeg2's feature detection */
    i_accel = MPEG2_ACCEL_DETECT;

#endif

    /* Set CPU acceleration features */
    mpeg2_accel( i_accel );

gbazin's avatar
 
gbazin committed
175
    /* Initialize decoder */
gbazin's avatar
 
gbazin committed
176 177
    p_sys->p_mpeg2dec = mpeg2_init();
    if( p_sys->p_mpeg2dec == NULL)
gbazin's avatar
 
gbazin committed
178 179
    {
        msg_Err( p_dec, "mpeg2_init() failed" );
gbazin's avatar
 
gbazin committed
180
        free( p_sys );
gbazin's avatar
 
gbazin committed
181 182
        return VLC_EGENERIC;
    }
gbazin's avatar
 
gbazin committed
183

gbazin's avatar
 
gbazin committed
184 185 186
    p_sys->p_info = mpeg2_info( p_sys->p_mpeg2dec );

    p_dec->pf_decode_video = DecodeBlock;
gbazin's avatar
 
gbazin committed
187 188 189

    return VLC_SUCCESS;
}
gbazin's avatar
 
gbazin committed
190

gbazin's avatar
 
gbazin committed
191 192 193
/*****************************************************************************
 * RunDecoder: the libmpeg2 decoder
 *****************************************************************************/
gbazin's avatar
 
gbazin committed
194
static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
gbazin's avatar
 
gbazin committed
195 196 197 198 199
{
    decoder_sys_t   *p_sys = p_dec->p_sys;
    mpeg2_state_t   state;
    picture_t       *p_pic;

gbazin's avatar
 
gbazin committed
200 201 202 203 204
    block_t *p_block;

    if( !pp_block || !*pp_block ) return NULL;

    p_block = *pp_block;
gbazin's avatar
 
gbazin committed
205 206

    while( 1 )
gbazin's avatar
 
gbazin committed
207
    {
gbazin's avatar
 
gbazin committed
208
        state = mpeg2_parse( p_sys->p_mpeg2dec );
gbazin's avatar
 
gbazin committed
209 210 211 212

        switch( state )
        {
        case STATE_BUFFER:
gbazin's avatar
 
gbazin committed
213
            if( !p_block->i_buffer )
gbazin's avatar
 
gbazin committed
214 215
            {
                block_Release( p_block );
gbazin's avatar
 
gbazin committed
216
                return NULL;
gbazin's avatar
 
gbazin committed
217 218
            }

Laurent Aimar's avatar
Laurent Aimar committed
219
            if( (p_block->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED)) &&
220
                p_sys->p_synchro &&
221 222
                p_sys->p_info->sequence &&
                p_sys->p_info->sequence->width != (unsigned)-1 )
gbazin's avatar
 
gbazin committed
223 224 225 226
            {
                vout_SynchroReset( p_sys->p_synchro );
                if( p_sys->p_info->current_fbuf != NULL
                    && p_sys->p_info->current_fbuf->id != NULL )
gbazin's avatar
 
gbazin committed
227
                {
gbazin's avatar
 
gbazin committed
228 229
                    p_sys->b_garbage_pic = 1;
                    p_pic = p_sys->p_info->current_fbuf->id;
gbazin's avatar
 
gbazin committed
230
                }
gbazin's avatar
 
gbazin committed
231 232 233 234 235 236 237 238 239 240 241
                else
                {
                    uint8_t *buf[3];
                    buf[0] = buf[1] = buf[2] = NULL;
                    if( (p_pic = GetNewPicture( p_dec, buf )) == NULL )
                        break;
                    mpeg2_set_buf( p_sys->p_mpeg2dec, buf, p_pic );
                }
                p_sys->p_picture_to_destroy = p_pic;

                if ( p_sys->b_slice_i )
242
                {
gbazin's avatar
 
gbazin committed
243 244 245 246
                    vout_SynchroNewPicture( p_sys->p_synchro,
                        I_CODING_TYPE, 2, 0, 0, p_sys->i_current_rate );
                    vout_SynchroDecode( p_sys->p_synchro );
                    vout_SynchroEnd( p_sys->p_synchro, I_CODING_TYPE, 0 );
247
                }
gbazin's avatar
 
gbazin committed
248
            }
249

Laurent Aimar's avatar
Laurent Aimar committed
250 251 252 253 254 255 256 257 258 259 260
            if( p_block->i_flags & BLOCK_FLAG_PREROLL )
            {
                p_sys->b_preroll = VLC_TRUE;
            }
            else if( p_sys->b_preroll )
            {
                p_sys->b_preroll = VLC_FALSE;
                /* Reset synchro */
                vout_SynchroReset( p_sys->p_synchro );
            }

261
#ifdef PIC_FLAG_PTS
gbazin's avatar
 
gbazin committed
262 263 264
            if( p_block->i_pts )
            {
                mpeg2_pts( p_sys->p_mpeg2dec, (uint32_t)p_block->i_pts );
gbazin's avatar
 
gbazin committed
265 266

#else /* New interface */
267 268
            if( p_block->i_pts || p_block->i_dts )
            {
gbazin's avatar
 
gbazin committed
269
                mpeg2_tag_picture( p_sys->p_mpeg2dec,
270 271
                                   (uint32_t)p_block->i_pts,
                                   (uint32_t)p_block->i_dts );
gbazin's avatar
 
gbazin committed
272
#endif
gbazin's avatar
 
gbazin committed
273 274
                p_sys->i_previous_pts = p_sys->i_current_pts;
                p_sys->i_current_pts = p_block->i_pts;
275 276
                p_sys->i_previous_dts = p_sys->i_current_dts;
                p_sys->i_current_dts = p_block->i_dts;
gbazin's avatar
 
gbazin committed
277 278
            }

gbazin's avatar
 
gbazin committed
279
            p_sys->i_current_rate = p_block->i_rate;
gbazin's avatar
 
gbazin committed
280

gbazin's avatar
 
gbazin committed
281 282 283
            mpeg2_buffer( p_sys->p_mpeg2dec, p_block->p_buffer,
                          p_block->p_buffer + p_block->i_buffer );

284
            p_block->i_buffer = 0;
gbazin's avatar
 
gbazin committed
285 286 287
            break;

        case STATE_SEQUENCE:
gbazin's avatar
 
gbazin committed
288
        {
gbazin's avatar
 
gbazin committed
289
            /* Initialize video output */
gbazin's avatar
 
gbazin committed
290
            uint8_t *buf[3];
291
            buf[0] = buf[1] = buf[2] = NULL;
gbazin's avatar
 
gbazin committed
292

gbazin's avatar
 
gbazin committed
293 294
            /* Check whether the input gave a particular aspect ratio */
            if( p_dec->fmt_in.video.i_aspect )
gbazin's avatar
 
gbazin committed
295
            {
gbazin's avatar
 
gbazin committed
296
                p_sys->i_aspect = p_dec->fmt_in.video.i_aspect;
gbazin's avatar
 
gbazin committed
297
                if( p_sys->i_aspect <= AR_221_1_PICTURE )
gbazin's avatar
 
gbazin committed
298
                switch( p_sys->i_aspect )
gbazin's avatar
 
gbazin committed
299 300
                {
                case AR_3_4_PICTURE:
gbazin's avatar
 
gbazin committed
301
                    p_sys->i_aspect = VOUT_ASPECT_FACTOR * 4 / 3;
gbazin's avatar
 
gbazin committed
302 303
                    break;
                case AR_16_9_PICTURE:
gbazin's avatar
 
gbazin committed
304
                    p_sys->i_aspect = VOUT_ASPECT_FACTOR * 16 / 9;
gbazin's avatar
 
gbazin committed
305 306
                    break;
                case AR_221_1_PICTURE:
gbazin's avatar
 
gbazin committed
307
                    p_sys->i_aspect = VOUT_ASPECT_FACTOR * 221 / 100;
gbazin's avatar
 
gbazin committed
308 309
                    break;
                case AR_SQUARE_PICTURE:
gbazin's avatar
 
gbazin committed
310
                    p_sys->i_aspect = VOUT_ASPECT_FACTOR *
gbazin's avatar
 
gbazin committed
311 312
                                   p_sys->p_info->sequence->width /
                                   p_sys->p_info->sequence->height;
gbazin's avatar
 
gbazin committed
313 314 315 316 317 318
                    break;
                }
            }
            else
            {
                /* Use the value provided in the MPEG sequence header */
319 320 321 322
                if( p_sys->p_info->sequence->pixel_height > 0 )
                {
                    p_sys->i_aspect =
                        ((uint64_t)p_sys->p_info->sequence->display_width) *
323 324
                        p_sys->p_info->sequence->pixel_width *
                        VOUT_ASPECT_FACTOR /
325 326 327 328 329
                        p_sys->p_info->sequence->display_height /
                        p_sys->p_info->sequence->pixel_height;
                }
                else
                {
330 331 332 333
                    /* Invalid aspect, assume 4:3.
                     * This shouldn't happen and if it does it is a bug
                     * in libmpeg2 (likely triggered by an invalid stream) */
                    p_sys->i_aspect = VOUT_ASPECT_FACTOR * 4 / 3;
334
                }
gbazin's avatar
 
gbazin committed
335 336
            }

gbazin's avatar
 
gbazin committed
337 338
            msg_Dbg( p_dec, "%dx%d, aspect %d, %u.%03u fps",
                     p_sys->p_info->sequence->width,
gbazin's avatar
 
gbazin committed
339
                     p_sys->p_info->sequence->height, p_sys->i_aspect,
Sam Hocevar's avatar
Sam Hocevar committed
340
                     (uint32_t)((uint64_t)1001000000 * 27 /
gbazin's avatar
 
gbazin committed
341
                         p_sys->p_info->sequence->frame_period / 1001),
Sam Hocevar's avatar
Sam Hocevar committed
342
                     (uint32_t)((uint64_t)1001000000 * 27 /
gbazin's avatar
 
gbazin committed
343
                         p_sys->p_info->sequence->frame_period % 1001) );
gbazin's avatar
 
gbazin committed
344 345

            mpeg2_custom_fbuf( p_sys->p_mpeg2dec, 1 );
gbazin's avatar
 
gbazin committed
346 347

            /* Set the first 2 reference frames */
gbazin's avatar
 
gbazin committed
348
            mpeg2_set_buf( p_sys->p_mpeg2dec, buf, NULL );
349

gbazin's avatar
 
gbazin committed
350
            if( (p_pic = GetNewPicture( p_dec, buf )) == NULL )
351 352 353 354
            {
                block_Release( p_block );
                return NULL;
            }
gbazin's avatar
 
gbazin committed
355

gbazin's avatar
 
gbazin committed
356
            mpeg2_set_buf( p_sys->p_mpeg2dec, buf, p_pic );
gbazin's avatar
 
gbazin committed
357

358
            /* This picture will never go through display_picture. */
gbazin's avatar
 
gbazin committed
359 360
            p_pic->date = 0;

361 362
            /* For some reason, libmpeg2 will put this pic twice in
             * discard_picture. This can be considered a bug in libmpeg2. */
gbazin's avatar
 
gbazin committed
363
            p_dec->pf_picture_link( p_dec, p_pic );
364

gbazin's avatar
 
gbazin committed
365
            if( p_sys->p_synchro )
366
            {
gbazin's avatar
 
gbazin committed
367
                vout_SynchroRelease( p_sys->p_synchro );
368
            }
gbazin's avatar
 
gbazin committed
369
            p_sys->p_synchro = vout_SynchroInit( p_dec,
gbazin's avatar
 
gbazin committed
370 371 372
                (uint32_t)((uint64_t)1001000000 * 27 /
                p_sys->p_info->sequence->frame_period) );
            p_sys->b_after_sequence_header = 1;
gbazin's avatar
 
gbazin committed
373 374
        }
        break;
gbazin's avatar
 
gbazin committed
375

376
        case STATE_PICTURE_2ND:
gbazin's avatar
 
gbazin committed
377 378 379
            vout_SynchroNewPicture( p_sys->p_synchro,
                p_sys->p_info->current_picture->flags & PIC_MASK_CODING_TYPE,
                p_sys->p_info->current_picture->nb_fields,
gbazin's avatar
 
gbazin committed
380
                0, 0, p_sys->i_current_rate );
381

gbazin's avatar
 
gbazin committed
382
            if( p_sys->b_skip )
383
            {
gbazin's avatar
 
gbazin committed
384
                vout_SynchroTrash( p_sys->p_synchro );
385 386 387
            }
            else
            {
gbazin's avatar
 
gbazin committed
388
                vout_SynchroDecode( p_sys->p_synchro );
389 390 391
            }
            break;

gbazin's avatar
 
gbazin committed
392 393 394
        case STATE_PICTURE:
        {
            uint8_t *buf[3];
395
            mtime_t i_pts, i_dts;
396 397
            buf[0] = buf[1] = buf[2] = NULL;

gbazin's avatar
 
gbazin committed
398 399 400
            if ( p_sys->b_after_sequence_header &&
                 ((p_sys->p_info->current_picture->flags &
                       PIC_MASK_CODING_TYPE) == PIC_FLAG_CODING_TYPE_P) )
401 402
            {
                /* Intra-slice refresh. Simulate a blank I picture. */
gbazin's avatar
 
gbazin committed
403 404 405 406 407 408
                msg_Dbg( p_dec, "intra-slice refresh stream" );
                vout_SynchroNewPicture( p_sys->p_synchro,
                    I_CODING_TYPE, 2, 0, 0, p_sys->i_current_rate );
                vout_SynchroDecode( p_sys->p_synchro );
                vout_SynchroEnd( p_sys->p_synchro, I_CODING_TYPE, 0 );
                p_sys->b_slice_i = 1;
409
            }
gbazin's avatar
 
gbazin committed
410 411
            p_sys->b_after_sequence_header = 0;

gbazin's avatar
 
gbazin committed
412
#ifdef PIC_FLAG_PTS
gbazin's avatar
 
gbazin committed
413 414 415 416
            i_pts = p_sys->p_info->current_picture->flags & PIC_FLAG_PTS ?
                ( ( p_sys->p_info->current_picture->pts ==
                    (uint32_t)p_sys->i_current_pts ) ?
                  p_sys->i_current_pts : p_sys->i_previous_pts ) : 0;
417
            i_dts = 0;
gbazin's avatar
 
gbazin committed
418

gbazin's avatar
 
gbazin committed
419 420 421 422 423 424 425 426 427 428 429 430 431
            /* Hack to handle demuxers which only have DTS timestamps */
            if( !i_pts && !p_block->i_pts && p_block->i_dts > 0 )
            {
                if( p_sys->p_info->sequence->flags & SEQ_FLAG_LOW_DELAY ||
                    (p_sys->p_info->current_picture->flags &
                      PIC_MASK_CODING_TYPE) == PIC_FLAG_CODING_TYPE_B )
                {
                    i_pts = p_block->i_dts;
                }
            }
            p_block->i_pts = p_block->i_dts = 0;
            /* End hack */

432 433 434 435 436 437 438 439 440 441 442 443
#else /* New interface */

            i_pts = p_sys->p_info->current_picture->flags & PIC_FLAG_TAGS ?
                ( ( p_sys->p_info->current_picture->tag ==
                    (uint32_t)p_sys->i_current_pts ) ?
                  p_sys->i_current_pts : p_sys->i_previous_pts ) : 0;
            i_dts = p_sys->p_info->current_picture->flags & PIC_FLAG_TAGS ?
                ( ( p_sys->p_info->current_picture->tag2 ==
                    (uint32_t)p_sys->i_current_dts ) ?
                  p_sys->i_current_dts : p_sys->i_previous_dts ) : 0;
#endif

gbazin's avatar
 
gbazin committed
444 445
            vout_SynchroNewPicture( p_sys->p_synchro,
                p_sys->p_info->current_picture->flags & PIC_MASK_CODING_TYPE,
446 447
                p_sys->p_info->current_picture->nb_fields, i_pts, i_dts,
                p_sys->i_current_rate );
gbazin's avatar
 
gbazin committed
448

Laurent Aimar's avatar
Laurent Aimar committed
449
            if( !p_dec->b_pace_control && !p_sys->b_preroll &&
450
                !(p_sys->b_slice_i
gbazin's avatar
 
gbazin committed
451
                   && ((p_sys->p_info->current_picture->flags
452
                         & PIC_MASK_CODING_TYPE) == P_CODING_TYPE))
gbazin's avatar
 
gbazin committed
453 454
                   && !vout_SynchroChoose( p_sys->p_synchro,
                              p_sys->p_info->current_picture->flags
gbazin's avatar
 
gbazin committed
455
                                & PIC_MASK_CODING_TYPE,
456
                              /*p_sys->p_vout->render_time*/ 0 /*FIXME*/ ) )
457
            {
gbazin's avatar
 
gbazin committed
458 459 460 461
                mpeg2_skip( p_sys->p_mpeg2dec, 1 );
                p_sys->b_skip = 1;
                vout_SynchroTrash( p_sys->p_synchro );
                mpeg2_set_buf( p_sys->p_mpeg2dec, buf, NULL );
462 463
            }
            else
gbazin's avatar
 
gbazin committed
464
            {
gbazin's avatar
 
gbazin committed
465 466 467
                mpeg2_skip( p_sys->p_mpeg2dec, 0 );
                p_sys->b_skip = 0;
                vout_SynchroDecode( p_sys->p_synchro );
gbazin's avatar
 
gbazin committed
468 469

                if( (p_pic = GetNewPicture( p_dec, buf )) == NULL )
470 471 472 473
                {
                    block_Release( p_block );
                    return NULL;
                }
gbazin's avatar
 
gbazin committed
474

gbazin's avatar
 
gbazin committed
475
                mpeg2_set_buf( p_sys->p_mpeg2dec, buf, p_pic );
gbazin's avatar
 
gbazin committed
476 477
            }
        }
478
        break;
gbazin's avatar
 
gbazin committed
479 480

        case STATE_END:
481
        case STATE_SLICE:
gbazin's avatar
 
gbazin committed
482
            p_pic = NULL;
gbazin's avatar
 
gbazin committed
483 484
            if( p_sys->p_info->display_fbuf
                && p_sys->p_info->display_fbuf->id )
gbazin's avatar
 
gbazin committed
485
            {
gbazin's avatar
 
gbazin committed
486
                p_pic = (picture_t *)p_sys->p_info->display_fbuf->id;
gbazin's avatar
 
gbazin committed
487

gbazin's avatar
 
gbazin committed
488 489
                vout_SynchroEnd( p_sys->p_synchro,
                            p_sys->p_info->display_picture->flags
490
                             & PIC_MASK_CODING_TYPE,
gbazin's avatar
 
gbazin committed
491 492
                            p_sys->b_garbage_pic );
                p_sys->b_garbage_pic = 0;
493

gbazin's avatar
 
gbazin committed
494
                if ( p_sys->p_picture_to_destroy != p_pic )
495
                {
gbazin's avatar
 
gbazin committed
496
                    p_pic->date = vout_SynchroDate( p_sys->p_synchro );
497 498 499
                }
                else
                {
gbazin's avatar
 
gbazin committed
500
                    p_sys->p_picture_to_destroy = NULL;
gbazin's avatar
 
gbazin committed
501
                    p_pic->date = 0;
gbazin's avatar
 
gbazin committed
502
                }
503 504
            }

gbazin's avatar
 
gbazin committed
505 506
            if( p_sys->p_info->discard_fbuf &&
                p_sys->p_info->discard_fbuf->id )
507
            {
gbazin's avatar
 
gbazin committed
508 509
                p_dec->pf_picture_unlink( p_dec,
                                          p_sys->p_info->discard_fbuf->id );
gbazin's avatar
 
gbazin committed
510
            }
gbazin's avatar
 
gbazin committed
511

512 513 514 515 516 517 518 519 520 521 522 523
            /* For still frames */
            if( state == STATE_END && p_pic ) p_pic->b_force = VLC_TRUE;

            if( p_pic )
            {
                /* Avoid frames with identical timestamps.
                 * Especially needed for still frames in DVD menus. */
                if( p_sys->i_last_frame_pts == p_pic->date ) p_pic->date++;
                p_sys->i_last_frame_pts = p_pic->date;

                return p_pic;
            }
gbazin's avatar
 
gbazin committed
524

gbazin's avatar
 
gbazin committed
525 526
            break;

527
        case STATE_INVALID:
528 529 530 531
        {
            uint8_t *buf[3];
            buf[0] = buf[1] = buf[2] = NULL;

gbazin's avatar
 
gbazin committed
532
            msg_Warn( p_dec, "invalid picture encountered" );
Sam Hocevar's avatar
Sam Hocevar committed
533
            if ( ( p_sys->p_info->current_picture == NULL ) ||
gbazin's avatar
 
gbazin committed
534
               ( ( p_sys->p_info->current_picture->flags &
535
                   PIC_MASK_CODING_TYPE) != B_CODING_TYPE ) )
536
            {
537
                if( p_sys->p_synchro ) vout_SynchroReset( p_sys->p_synchro );
538
            }
gbazin's avatar
 
gbazin committed
539 540
            mpeg2_skip( p_sys->p_mpeg2dec, 1 );
            p_sys->b_skip = 1;
541

gbazin's avatar
 
gbazin committed
542 543
            if( p_sys->p_info->current_fbuf &&
                p_sys->p_info->current_fbuf->id )
544
            {
gbazin's avatar
 
gbazin committed
545 546
                p_sys->b_garbage_pic = 1;
                p_pic = p_sys->p_info->current_fbuf->id;
547
            }
548 549 550 551
            else if( !p_sys->p_info->sequence )
            {
                break;
            }
552 553 554 555
            else
            {
                if( (p_pic = GetNewPicture( p_dec, buf )) == NULL )
                    break;
gbazin's avatar
 
gbazin committed
556
                mpeg2_set_buf( p_sys->p_mpeg2dec, buf, p_pic );
557
            }
gbazin's avatar
 
gbazin committed
558
            p_sys->p_picture_to_destroy = p_pic;
559 560

            memset( p_pic->p[0].p_pixels, 0,
gbazin's avatar
 
gbazin committed
561 562
                    p_sys->p_info->sequence->width
                     * p_sys->p_info->sequence->height );
563
            memset( p_pic->p[1].p_pixels, 0x80,
gbazin's avatar
 
gbazin committed
564 565
                    p_sys->p_info->sequence->width
                     * p_sys->p_info->sequence->height / 4 );
566
            memset( p_pic->p[2].p_pixels, 0x80,
gbazin's avatar
 
gbazin committed
567 568
                    p_sys->p_info->sequence->width
                     * p_sys->p_info->sequence->height / 4 );
569

gbazin's avatar
 
gbazin committed
570
            if( p_sys->b_slice_i )
571
            {
gbazin's avatar
 
gbazin committed
572 573 574 575
                vout_SynchroNewPicture( p_sys->p_synchro,
                            I_CODING_TYPE, 2, 0, 0, p_sys->i_current_rate );
                vout_SynchroDecode( p_sys->p_synchro );
                vout_SynchroEnd( p_sys->p_synchro, I_CODING_TYPE, 0 );
576
            }
577
            break;
578
        }
579

gbazin's avatar
 
gbazin committed
580 581 582 583 584
        default:
            break;
        }
    }

gbazin's avatar
 
gbazin committed
585 586
    /* Never reached */
    return NULL;
gbazin's avatar
 
gbazin committed
587 588 589
}

/*****************************************************************************
gbazin's avatar
 
gbazin committed
590
 * CloseDecoder: libmpeg2 decoder destruction
gbazin's avatar
 
gbazin committed
591
 *****************************************************************************/
gbazin's avatar
 
gbazin committed
592
static void CloseDecoder( vlc_object_t *p_this )
gbazin's avatar
 
gbazin committed
593
{
gbazin's avatar
 
gbazin committed
594
    decoder_t *p_dec = (decoder_t *)p_this;
gbazin's avatar
 
gbazin committed
595 596
    decoder_sys_t *p_sys = p_dec->p_sys;

gbazin's avatar
 
gbazin committed
597
    if( p_sys->p_synchro ) vout_SynchroRelease( p_sys->p_synchro );
gbazin's avatar
 
gbazin committed
598

gbazin's avatar
 
gbazin committed
599
    if( p_sys->p_mpeg2dec ) mpeg2_close( p_sys->p_mpeg2dec );
gbazin's avatar
 
gbazin committed
600

gbazin's avatar
 
gbazin committed
601
    free( p_sys );
gbazin's avatar
 
gbazin committed
602
}
gbazin's avatar
 
gbazin committed
603 604 605 606

/*****************************************************************************
 * GetNewPicture: Get a new picture from the vout and set the buf struct
 *****************************************************************************/
gbazin's avatar
 
gbazin committed
607
static picture_t *GetNewPicture( decoder_t *p_dec, uint8_t **pp_buf )
gbazin's avatar
 
gbazin committed
608
{
gbazin's avatar
 
gbazin committed
609
    decoder_sys_t *p_sys = p_dec->p_sys;
gbazin's avatar
 
gbazin committed
610
    picture_t *p_pic;
gbazin's avatar
 
gbazin committed
611

gbazin's avatar
 
gbazin committed
612
    p_dec->fmt_out.video.i_width = p_sys->p_info->sequence->width;
613 614
    p_dec->fmt_out.video.i_visible_width =
        p_sys->p_info->sequence->picture_width;
gbazin's avatar
 
gbazin committed
615
    p_dec->fmt_out.video.i_height = p_sys->p_info->sequence->height;
616 617
    p_dec->fmt_out.video.i_visible_height =
        p_sys->p_info->sequence->picture_height;
gbazin's avatar
 
gbazin committed
618
    p_dec->fmt_out.video.i_aspect = p_sys->i_aspect;
gbazin's avatar
 
gbazin committed
619

620 621 622 623 624 625 626 627
    if( p_sys->p_info->sequence->frame_period > 0 )
    {
        p_dec->fmt_out.video.i_frame_rate =
            (uint32_t)( (uint64_t)1001000000 * 27 /
                        p_sys->p_info->sequence->frame_period );
        p_dec->fmt_out.video.i_frame_rate_base = 1001;
    }

gbazin's avatar
 
gbazin committed
628 629 630 631
    p_dec->fmt_out.i_codec =
        ( p_sys->p_info->sequence->chroma_height <
          p_sys->p_info->sequence->height ) ?
        VLC_FOURCC('I','4','2','0') : VLC_FOURCC('I','4','2','2');
gbazin's avatar
 
gbazin committed
632

gbazin's avatar
 
gbazin committed
633 634
    /* Get a new picture */
    p_pic = p_dec->pf_vout_buffer_new( p_dec );
gbazin's avatar
 
gbazin committed
635 636 637

    if( p_pic == NULL ) return NULL;

gbazin's avatar
 
gbazin committed
638 639 640 641 642 643 644
    p_pic->b_progressive = p_sys->p_info->current_picture != NULL ?
        p_sys->p_info->current_picture->flags & PIC_FLAG_PROGRESSIVE_FRAME : 1;
    p_pic->b_top_field_first = p_sys->p_info->current_picture != NULL ?
        p_sys->p_info->current_picture->flags & PIC_FLAG_TOP_FIELD_FIRST : 1;
    p_pic->i_nb_fields = p_sys->p_info->current_picture != NULL ?
        p_sys->p_info->current_picture->nb_fields : 2;

gbazin's avatar
 
gbazin committed
645
    p_dec->pf_picture_link( p_dec, p_pic );
gbazin's avatar
 
gbazin committed
646 647 648 649 650 651 652

    pp_buf[0] = p_pic->p[0].p_pixels;
    pp_buf[1] = p_pic->p[1].p_pixels;
    pp_buf[2] = p_pic->p[2].p_pixels;

    return p_pic;
}