libmpeg2.c 22.4 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 68 69 70

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

gbazin's avatar
 
gbazin committed
75
};
gbazin's avatar
 
gbazin committed
76 77 78 79

/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
gbazin's avatar
 
gbazin committed
80 81 82 83
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
84

gbazin's avatar
 
gbazin committed
85
static picture_t *GetNewPicture( decoder_t *, uint8_t ** );
gbazin's avatar
 
gbazin committed
86

gbazin's avatar
 
gbazin committed
87 88 89 90 91
/*****************************************************************************
 * Module descriptor
 *****************************************************************************/
vlc_module_begin();
    set_description( _("MPEG I/II video decoder (using libmpeg2)") );
gbazin's avatar
 
gbazin committed
92
    set_capability( "decoder", 150 );
zorglub's avatar
zorglub committed
93 94
    set_category( CAT_INPUT );
    set_subcategory( SUBCAT_INPUT_VCODEC );
gbazin's avatar
 
gbazin committed
95
    set_callbacks( OpenDecoder, CloseDecoder );
gbazin's avatar
 
gbazin committed
96 97 98 99 100 101 102 103
    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
104
    decoder_t *p_dec = (decoder_t*)p_this;
gbazin's avatar
 
gbazin committed
105
    decoder_sys_t *p_sys;
Sam Hocevar's avatar
Sam Hocevar committed
106
    uint32_t i_accel = 0;
gbazin's avatar
 
gbazin committed
107

gbazin's avatar
 
gbazin committed
108 109
    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
110
        /* Pinnacle hardware-mpeg1 */
gbazin's avatar
 
gbazin committed
111
        p_dec->fmt_in.i_codec != VLC_FOURCC('P','I','M','1') &&
gbazin's avatar
 
gbazin committed
112
        /* ATI Video */
gbazin's avatar
 
gbazin committed
113 114
        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
115 116 117 118
    {
        return VLC_EGENERIC;
    }

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

    /* Initialize the thread properties */
gbazin's avatar
 
gbazin committed
128 129 130 131 132 133
    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;
134 135
    p_sys->i_current_dts  = 0;
    p_sys->i_previous_dts = 0;
gbazin's avatar
 
gbazin committed
136 137 138 139
    p_sys->p_picture_to_destroy = NULL;
    p_sys->b_garbage_pic = 0;
    p_sys->b_slice_i  = 0;
    p_sys->b_skip     = 0;
gbazin's avatar
 
gbazin committed
140

Sam Hocevar's avatar
Sam Hocevar committed
141 142 143 144 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
#if defined( __i386__ )
    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
172
    /* Initialize decoder */
gbazin's avatar
 
gbazin committed
173 174
    p_sys->p_mpeg2dec = mpeg2_init();
    if( p_sys->p_mpeg2dec == NULL)
gbazin's avatar
 
gbazin committed
175 176
    {
        msg_Err( p_dec, "mpeg2_init() failed" );
gbazin's avatar
 
gbazin committed
177
        free( p_sys );
gbazin's avatar
 
gbazin committed
178 179
        return VLC_EGENERIC;
    }
gbazin's avatar
 
gbazin committed
180

gbazin's avatar
 
gbazin committed
181 182 183
    p_sys->p_info = mpeg2_info( p_sys->p_mpeg2dec );

    p_dec->pf_decode_video = DecodeBlock;
gbazin's avatar
 
gbazin committed
184 185 186

    return VLC_SUCCESS;
}
gbazin's avatar
 
gbazin committed
187

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

gbazin's avatar
 
gbazin committed
197 198 199 200 201
    block_t *p_block;

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

    p_block = *pp_block;
gbazin's avatar
 
gbazin committed
202 203

    while( 1 )
gbazin's avatar
 
gbazin committed
204
    {
gbazin's avatar
 
gbazin committed
205
        state = mpeg2_parse( p_sys->p_mpeg2dec );
gbazin's avatar
 
gbazin committed
206 207 208 209

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

216 217
            if( (p_block->i_flags&BLOCK_FLAG_DISCONTINUITY) &&
                p_sys->p_synchro &&
218 219
                p_sys->p_info->sequence &&
                p_sys->p_info->sequence->width != (unsigned)-1 )
gbazin's avatar
 
gbazin committed
220 221 222 223
            {
                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
224
                {
gbazin's avatar
 
gbazin committed
225 226
                    p_sys->b_garbage_pic = 1;
                    p_pic = p_sys->p_info->current_fbuf->id;
gbazin's avatar
 
gbazin committed
227
                }
gbazin's avatar
 
gbazin committed
228 229 230 231 232 233 234 235 236 237 238
                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 )
239
                {
gbazin's avatar
 
gbazin committed
240 241 242 243
                    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 );
244
                }
gbazin's avatar
 
gbazin committed
245
            }
246

247
#ifdef PIC_FLAG_PTS
gbazin's avatar
 
gbazin committed
248 249 250
            if( p_block->i_pts )
            {
                mpeg2_pts( p_sys->p_mpeg2dec, (uint32_t)p_block->i_pts );
gbazin's avatar
 
gbazin committed
251 252

#else /* New interface */
253 254
            if( p_block->i_pts || p_block->i_dts )
            {
gbazin's avatar
 
gbazin committed
255
                mpeg2_tag_picture( p_sys->p_mpeg2dec,
256 257
                                   (uint32_t)p_block->i_pts,
                                   (uint32_t)p_block->i_dts );
gbazin's avatar
 
gbazin committed
258
#endif
gbazin's avatar
 
gbazin committed
259 260
                p_sys->i_previous_pts = p_sys->i_current_pts;
                p_sys->i_current_pts = p_block->i_pts;
261 262
                p_sys->i_previous_dts = p_sys->i_current_dts;
                p_sys->i_current_dts = p_block->i_dts;
gbazin's avatar
 
gbazin committed
263 264
            }

gbazin's avatar
 
gbazin committed
265
            p_sys->i_current_rate = p_block->i_rate;
gbazin's avatar
 
gbazin committed
266

gbazin's avatar
 
gbazin committed
267 268 269
            mpeg2_buffer( p_sys->p_mpeg2dec, p_block->p_buffer,
                          p_block->p_buffer + p_block->i_buffer );

270
            p_block->i_buffer = 0;
gbazin's avatar
 
gbazin committed
271 272 273
            break;

        case STATE_SEQUENCE:
gbazin's avatar
 
gbazin committed
274
        {
gbazin's avatar
 
gbazin committed
275
            /* Initialize video output */
gbazin's avatar
 
gbazin committed
276
            uint8_t *buf[3];
277
            buf[0] = buf[1] = buf[2] = NULL;
gbazin's avatar
 
gbazin committed
278

gbazin's avatar
 
gbazin committed
279 280
            /* Check whether the input gave a particular aspect ratio */
            if( p_dec->fmt_in.video.i_aspect )
gbazin's avatar
 
gbazin committed
281
            {
gbazin's avatar
 
gbazin committed
282
                p_sys->i_aspect = p_dec->fmt_in.video.i_aspect;
gbazin's avatar
 
gbazin committed
283
                if( p_sys->i_aspect <= AR_221_1_PICTURE )
gbazin's avatar
 
gbazin committed
284
                switch( p_sys->i_aspect )
gbazin's avatar
 
gbazin committed
285 286
                {
                case AR_3_4_PICTURE:
gbazin's avatar
 
gbazin committed
287
                    p_sys->i_aspect = VOUT_ASPECT_FACTOR * 4 / 3;
gbazin's avatar
 
gbazin committed
288 289
                    break;
                case AR_16_9_PICTURE:
gbazin's avatar
 
gbazin committed
290
                    p_sys->i_aspect = VOUT_ASPECT_FACTOR * 16 / 9;
gbazin's avatar
 
gbazin committed
291 292
                    break;
                case AR_221_1_PICTURE:
gbazin's avatar
 
gbazin committed
293
                    p_sys->i_aspect = VOUT_ASPECT_FACTOR * 221 / 100;
gbazin's avatar
 
gbazin committed
294 295
                    break;
                case AR_SQUARE_PICTURE:
gbazin's avatar
 
gbazin committed
296
                    p_sys->i_aspect = VOUT_ASPECT_FACTOR *
gbazin's avatar
 
gbazin committed
297 298
                                   p_sys->p_info->sequence->width /
                                   p_sys->p_info->sequence->height;
gbazin's avatar
 
gbazin committed
299 300 301 302 303 304
                    break;
                }
            }
            else
            {
                /* Use the value provided in the MPEG sequence header */
305 306 307 308
                if( p_sys->p_info->sequence->pixel_height > 0 )
                {
                    p_sys->i_aspect =
                        ((uint64_t)p_sys->p_info->sequence->display_width) *
309 310
                        p_sys->p_info->sequence->pixel_width *
                        VOUT_ASPECT_FACTOR /
311 312 313 314 315
                        p_sys->p_info->sequence->display_height /
                        p_sys->p_info->sequence->pixel_height;
                }
                else
                {
316 317 318 319
                    /* 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;
320
                }
gbazin's avatar
 
gbazin committed
321 322
            }

gbazin's avatar
 
gbazin committed
323 324
            msg_Dbg( p_dec, "%dx%d, aspect %d, %u.%03u fps",
                     p_sys->p_info->sequence->width,
gbazin's avatar
 
gbazin committed
325
                     p_sys->p_info->sequence->height, p_sys->i_aspect,
Sam Hocevar's avatar
Sam Hocevar committed
326
                     (uint32_t)((uint64_t)1001000000 * 27 /
gbazin's avatar
 
gbazin committed
327
                         p_sys->p_info->sequence->frame_period / 1001),
Sam Hocevar's avatar
Sam Hocevar committed
328
                     (uint32_t)((uint64_t)1001000000 * 27 /
gbazin's avatar
 
gbazin committed
329
                         p_sys->p_info->sequence->frame_period % 1001) );
gbazin's avatar
 
gbazin committed
330 331

            mpeg2_custom_fbuf( p_sys->p_mpeg2dec, 1 );
gbazin's avatar
 
gbazin committed
332 333

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

gbazin's avatar
 
gbazin committed
336
            if( (p_pic = GetNewPicture( p_dec, buf )) == NULL )
337 338 339 340
            {
                block_Release( p_block );
                return NULL;
            }
gbazin's avatar
 
gbazin committed
341

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

344
            /* This picture will never go through display_picture. */
gbazin's avatar
 
gbazin committed
345 346
            p_pic->date = 0;

347 348
            /* 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
349
            p_dec->pf_picture_link( p_dec, p_pic );
350

gbazin's avatar
 
gbazin committed
351
            if( p_sys->p_synchro )
352
            {
gbazin's avatar
 
gbazin committed
353
                vout_SynchroRelease( p_sys->p_synchro );
354
            }
gbazin's avatar
 
gbazin committed
355
            p_sys->p_synchro = vout_SynchroInit( p_dec,
gbazin's avatar
 
gbazin committed
356 357 358
                (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
359 360
        }
        break;
gbazin's avatar
 
gbazin committed
361

362
        case STATE_PICTURE_2ND:
gbazin's avatar
 
gbazin committed
363 364 365
            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
366
                0, 0, p_sys->i_current_rate );
367

gbazin's avatar
 
gbazin committed
368
            if( p_sys->b_skip )
369
            {
gbazin's avatar
 
gbazin committed
370
                vout_SynchroTrash( p_sys->p_synchro );
371 372 373
            }
            else
            {
gbazin's avatar
 
gbazin committed
374
                vout_SynchroDecode( p_sys->p_synchro );
375 376 377
            }
            break;

gbazin's avatar
 
gbazin committed
378 379 380
        case STATE_PICTURE:
        {
            uint8_t *buf[3];
381
            mtime_t i_pts, i_dts;
382 383
            buf[0] = buf[1] = buf[2] = NULL;

gbazin's avatar
 
gbazin committed
384 385 386
            if ( p_sys->b_after_sequence_header &&
                 ((p_sys->p_info->current_picture->flags &
                       PIC_MASK_CODING_TYPE) == PIC_FLAG_CODING_TYPE_P) )
387 388
            {
                /* Intra-slice refresh. Simulate a blank I picture. */
gbazin's avatar
 
gbazin committed
389 390 391 392 393 394
                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;
395
            }
gbazin's avatar
 
gbazin committed
396 397
            p_sys->b_after_sequence_header = 0;

gbazin's avatar
 
gbazin committed
398
#ifdef PIC_FLAG_PTS
gbazin's avatar
 
gbazin committed
399 400 401 402
            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;
403
            i_dts = 0;
gbazin's avatar
 
gbazin committed
404

gbazin's avatar
 
gbazin committed
405 406 407 408 409 410 411 412 413 414 415 416 417
            /* 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 */

418 419 420 421 422 423 424 425 426 427 428 429
#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
430 431
            vout_SynchroNewPicture( p_sys->p_synchro,
                p_sys->p_info->current_picture->flags & PIC_MASK_CODING_TYPE,
432 433
                p_sys->p_info->current_picture->nb_fields, i_pts, i_dts,
                p_sys->i_current_rate );
gbazin's avatar
 
gbazin committed
434

435 436
            if( !p_dec->b_pace_control &&
                !(p_sys->b_slice_i
gbazin's avatar
 
gbazin committed
437
                   && ((p_sys->p_info->current_picture->flags
438
                         & PIC_MASK_CODING_TYPE) == P_CODING_TYPE))
gbazin's avatar
 
gbazin committed
439 440
                   && !vout_SynchroChoose( p_sys->p_synchro,
                              p_sys->p_info->current_picture->flags
gbazin's avatar
 
gbazin committed
441
                                & PIC_MASK_CODING_TYPE,
442
                              /*p_sys->p_vout->render_time*/ 0 /*FIXME*/ ) )
443
            {
gbazin's avatar
 
gbazin committed
444 445 446 447
                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 );
448 449
            }
            else
gbazin's avatar
 
gbazin committed
450
            {
gbazin's avatar
 
gbazin committed
451 452 453
                mpeg2_skip( p_sys->p_mpeg2dec, 0 );
                p_sys->b_skip = 0;
                vout_SynchroDecode( p_sys->p_synchro );
gbazin's avatar
 
gbazin committed
454 455

                if( (p_pic = GetNewPicture( p_dec, buf )) == NULL )
456 457 458 459
                {
                    block_Release( p_block );
                    return NULL;
                }
gbazin's avatar
 
gbazin committed
460

gbazin's avatar
 
gbazin committed
461
                mpeg2_set_buf( p_sys->p_mpeg2dec, buf, p_pic );
gbazin's avatar
 
gbazin committed
462 463
            }
        }
464
        break;
gbazin's avatar
 
gbazin committed
465 466

        case STATE_END:
467
        case STATE_SLICE:
gbazin's avatar
 
gbazin committed
468
            p_pic = NULL;
gbazin's avatar
 
gbazin committed
469 470
            if( p_sys->p_info->display_fbuf
                && p_sys->p_info->display_fbuf->id )
gbazin's avatar
 
gbazin committed
471
            {
gbazin's avatar
 
gbazin committed
472
                p_pic = (picture_t *)p_sys->p_info->display_fbuf->id;
gbazin's avatar
 
gbazin committed
473

gbazin's avatar
 
gbazin committed
474 475
                vout_SynchroEnd( p_sys->p_synchro,
                            p_sys->p_info->display_picture->flags
476
                             & PIC_MASK_CODING_TYPE,
gbazin's avatar
 
gbazin committed
477 478
                            p_sys->b_garbage_pic );
                p_sys->b_garbage_pic = 0;
479

gbazin's avatar
 
gbazin committed
480
                if ( p_sys->p_picture_to_destroy != p_pic )
481
                {
gbazin's avatar
 
gbazin committed
482
                    p_pic->date = vout_SynchroDate( p_sys->p_synchro );
483 484 485
                }
                else
                {
gbazin's avatar
 
gbazin committed
486
                    p_sys->p_picture_to_destroy = NULL;
gbazin's avatar
 
gbazin committed
487
                    p_pic->date = 0;
gbazin's avatar
 
gbazin committed
488
                }
489 490
            }

gbazin's avatar
 
gbazin committed
491 492
            if( p_sys->p_info->discard_fbuf &&
                p_sys->p_info->discard_fbuf->id )
493
            {
gbazin's avatar
 
gbazin committed
494 495
                p_dec->pf_picture_unlink( p_dec,
                                          p_sys->p_info->discard_fbuf->id );
gbazin's avatar
 
gbazin committed
496
            }
gbazin's avatar
 
gbazin committed
497

498 499 500 501 502 503 504 505 506 507 508 509
            /* 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
510

gbazin's avatar
 
gbazin committed
511 512
            break;

513
        case STATE_INVALID:
514 515 516 517
        {
            uint8_t *buf[3];
            buf[0] = buf[1] = buf[2] = NULL;

gbazin's avatar
 
gbazin committed
518
            msg_Warn( p_dec, "invalid picture encountered" );
Sam Hocevar's avatar
Sam Hocevar committed
519
            if ( ( p_sys->p_info->current_picture == NULL ) ||
gbazin's avatar
 
gbazin committed
520
               ( ( p_sys->p_info->current_picture->flags &
521
                   PIC_MASK_CODING_TYPE) != B_CODING_TYPE ) )
522
            {
523
                if( p_sys->p_synchro ) vout_SynchroReset( p_sys->p_synchro );
524
            }
gbazin's avatar
 
gbazin committed
525 526
            mpeg2_skip( p_sys->p_mpeg2dec, 1 );
            p_sys->b_skip = 1;
527

gbazin's avatar
 
gbazin committed
528 529
            if( p_sys->p_info->current_fbuf &&
                p_sys->p_info->current_fbuf->id )
530
            {
gbazin's avatar
 
gbazin committed
531 532
                p_sys->b_garbage_pic = 1;
                p_pic = p_sys->p_info->current_fbuf->id;
533
            }
534 535 536 537
            else if( !p_sys->p_info->sequence )
            {
                break;
            }
538 539 540 541
            else
            {
                if( (p_pic = GetNewPicture( p_dec, buf )) == NULL )
                    break;
gbazin's avatar
 
gbazin committed
542
                mpeg2_set_buf( p_sys->p_mpeg2dec, buf, p_pic );
543
            }
gbazin's avatar
 
gbazin committed
544
            p_sys->p_picture_to_destroy = p_pic;
545 546

            memset( p_pic->p[0].p_pixels, 0,
gbazin's avatar
 
gbazin committed
547 548
                    p_sys->p_info->sequence->width
                     * p_sys->p_info->sequence->height );
549
            memset( p_pic->p[1].p_pixels, 0x80,
gbazin's avatar
 
gbazin committed
550 551
                    p_sys->p_info->sequence->width
                     * p_sys->p_info->sequence->height / 4 );
552
            memset( p_pic->p[2].p_pixels, 0x80,
gbazin's avatar
 
gbazin committed
553 554
                    p_sys->p_info->sequence->width
                     * p_sys->p_info->sequence->height / 4 );
555

gbazin's avatar
 
gbazin committed
556
            if( p_sys->b_slice_i )
557
            {
gbazin's avatar
 
gbazin committed
558 559 560 561
                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 );
562
            }
563
            break;
564
        }
565

gbazin's avatar
 
gbazin committed
566 567 568 569 570
        default:
            break;
        }
    }

gbazin's avatar
 
gbazin committed
571 572
    /* Never reached */
    return NULL;
gbazin's avatar
 
gbazin committed
573 574 575
}

/*****************************************************************************
gbazin's avatar
 
gbazin committed
576
 * CloseDecoder: libmpeg2 decoder destruction
gbazin's avatar
 
gbazin committed
577
 *****************************************************************************/
gbazin's avatar
 
gbazin committed
578
static void CloseDecoder( vlc_object_t *p_this )
gbazin's avatar
 
gbazin committed
579
{
gbazin's avatar
 
gbazin committed
580
    decoder_t *p_dec = (decoder_t *)p_this;
gbazin's avatar
 
gbazin committed
581 582
    decoder_sys_t *p_sys = p_dec->p_sys;

gbazin's avatar
 
gbazin committed
583
    if( p_sys->p_synchro ) vout_SynchroRelease( p_sys->p_synchro );
gbazin's avatar
 
gbazin committed
584

gbazin's avatar
 
gbazin committed
585
    if( p_sys->p_mpeg2dec ) mpeg2_close( p_sys->p_mpeg2dec );
gbazin's avatar
 
gbazin committed
586

gbazin's avatar
 
gbazin committed
587
    free( p_sys );
gbazin's avatar
 
gbazin committed
588
}
gbazin's avatar
 
gbazin committed
589 590 591 592

/*****************************************************************************
 * GetNewPicture: Get a new picture from the vout and set the buf struct
 *****************************************************************************/
gbazin's avatar
 
gbazin committed
593
static picture_t *GetNewPicture( decoder_t *p_dec, uint8_t **pp_buf )
gbazin's avatar
 
gbazin committed
594
{
gbazin's avatar
 
gbazin committed
595
    decoder_sys_t *p_sys = p_dec->p_sys;
gbazin's avatar
 
gbazin committed
596
    picture_t *p_pic;
gbazin's avatar
 
gbazin committed
597

gbazin's avatar
 
gbazin committed
598
    p_dec->fmt_out.video.i_width = p_sys->p_info->sequence->width;
599 600
    p_dec->fmt_out.video.i_visible_width =
        p_sys->p_info->sequence->picture_width;
gbazin's avatar
 
gbazin committed
601
    p_dec->fmt_out.video.i_height = p_sys->p_info->sequence->height;
602 603
    p_dec->fmt_out.video.i_visible_height =
        p_sys->p_info->sequence->picture_height;
gbazin's avatar
 
gbazin committed
604
    p_dec->fmt_out.video.i_aspect = p_sys->i_aspect;
gbazin's avatar
 
gbazin committed
605

606 607 608 609 610 611 612 613
    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
614 615 616 617
    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
618

gbazin's avatar
 
gbazin committed
619 620
    /* Get a new picture */
    p_pic = p_dec->pf_vout_buffer_new( p_dec );
gbazin's avatar
 
gbazin committed
621 622 623

    if( p_pic == NULL ) return NULL;

gbazin's avatar
 
gbazin committed
624 625 626 627 628 629 630
    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
631
    p_dec->pf_picture_link( p_dec, p_pic );
gbazin's avatar
 
gbazin committed
632 633 634 635 636 637 638

    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;
}