libmpeg2.c 20.8 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@netcourrier.com>
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 59

    /*
     * Input properties
     */
    mtime_t          i_pts;
    mtime_t          i_previous_pts;
    mtime_t          i_current_pts;
60 61
    int              i_current_rate;
    picture_t *      p_picture_to_destroy;
62 63 64 65
    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
66 67 68 69

    /*
     * Output properties
     */
70
    vout_synchro_t *p_synchro;
gbazin's avatar
 
gbazin committed
71
    int i_aspect;
gbazin's avatar
 
gbazin committed
72

gbazin's avatar
 
gbazin committed
73
};
gbazin's avatar
 
gbazin committed
74 75 76 77

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

gbazin's avatar
 
gbazin committed
83
static picture_t *GetNewPicture( decoder_t *, uint8_t ** );
gbazin's avatar
 
gbazin committed
84

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

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

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

    /* Initialize the thread properties */
gbazin's avatar
 
gbazin committed
124 125 126 127 128 129 130 131 132 133 134
    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_pts      = mdate() + DEFAULT_PTS_DELAY;
    p_sys->i_current_pts  = 0;
    p_sys->i_previous_pts = 0;
    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
135

Sam Hocevar's avatar
Sam Hocevar committed
136 137 138 139 140 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
#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
167
    /* Initialize decoder */
gbazin's avatar
 
gbazin committed
168 169
    p_sys->p_mpeg2dec = mpeg2_init();
    if( p_sys->p_mpeg2dec == NULL)
gbazin's avatar
 
gbazin committed
170 171
    {
        msg_Err( p_dec, "mpeg2_init() failed" );
gbazin's avatar
 
gbazin committed
172
        free( p_sys );
gbazin's avatar
 
gbazin committed
173 174
        return VLC_EGENERIC;
    }
gbazin's avatar
 
gbazin committed
175

gbazin's avatar
 
gbazin committed
176 177 178
    p_sys->p_info = mpeg2_info( p_sys->p_mpeg2dec );

    p_dec->pf_decode_video = DecodeBlock;
gbazin's avatar
 
gbazin committed
179 180 181

    return VLC_SUCCESS;
}
gbazin's avatar
 
gbazin committed
182

gbazin's avatar
 
gbazin committed
183 184 185
/*****************************************************************************
 * RunDecoder: the libmpeg2 decoder
 *****************************************************************************/
gbazin's avatar
 
gbazin committed
186
static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
gbazin's avatar
 
gbazin committed
187 188 189 190 191
{
    decoder_sys_t   *p_sys = p_dec->p_sys;
    mpeg2_state_t   state;
    picture_t       *p_pic;

gbazin's avatar
 
gbazin committed
192 193 194 195 196
    block_t *p_block;

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

    p_block = *pp_block;
gbazin's avatar
 
gbazin committed
197 198

    while( 1 )
gbazin's avatar
 
gbazin committed
199
    {
gbazin's avatar
 
gbazin committed
200
        state = mpeg2_parse( p_sys->p_mpeg2dec );
gbazin's avatar
 
gbazin committed
201 202 203 204

        switch( state )
        {
        case STATE_BUFFER:
gbazin's avatar
 
gbazin committed
205
            if( !p_block->i_buffer )
gbazin's avatar
 
gbazin committed
206 207
            {
                block_Release( p_block );
gbazin's avatar
 
gbazin committed
208
                return NULL;
gbazin's avatar
 
gbazin committed
209 210
            }

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

gbazin's avatar
 
gbazin committed
242 243
            if( p_block->i_pts )
            {
gbazin's avatar
 
gbazin committed
244
#ifdef PIC_FLAG_PTS
gbazin's avatar
 
gbazin committed
245
                mpeg2_pts( p_sys->p_mpeg2dec, (uint32_t)p_block->i_pts );
gbazin's avatar
 
gbazin committed
246 247 248 249 250

#else /* New interface */
                mpeg2_tag_picture( p_sys->p_mpeg2dec,
                                   (uint32_t)p_block->i_pts, 0/*dts*/ );
#endif
gbazin's avatar
 
gbazin committed
251 252
                p_sys->i_previous_pts = p_sys->i_current_pts;
                p_sys->i_current_pts = p_block->i_pts;
gbazin's avatar
 
gbazin committed
253 254
            }

gbazin's avatar
 
gbazin committed
255
            p_sys->i_current_rate = p_block->i_rate;
gbazin's avatar
 
gbazin committed
256

gbazin's avatar
 
gbazin committed
257 258 259
            mpeg2_buffer( p_sys->p_mpeg2dec, p_block->p_buffer,
                          p_block->p_buffer + p_block->i_buffer );

260
            p_block->i_buffer = 0;
gbazin's avatar
 
gbazin committed
261 262 263
            break;

        case STATE_SEQUENCE:
gbazin's avatar
 
gbazin committed
264
        {
gbazin's avatar
 
gbazin committed
265
            /* Initialize video output */
gbazin's avatar
 
gbazin committed
266
            uint8_t *buf[3];
267
            buf[0] = buf[1] = buf[2] = NULL;
gbazin's avatar
 
gbazin committed
268

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

gbazin's avatar
 
gbazin committed
313 314
            msg_Dbg( p_dec, "%dx%d, aspect %d, %u.%03u fps",
                     p_sys->p_info->sequence->width,
gbazin's avatar
 
gbazin committed
315
                     p_sys->p_info->sequence->height, p_sys->i_aspect,
Sam Hocevar's avatar
Sam Hocevar committed
316
                     (uint32_t)((uint64_t)1001000000 * 27 /
gbazin's avatar
 
gbazin committed
317
                         p_sys->p_info->sequence->frame_period / 1001),
Sam Hocevar's avatar
Sam Hocevar committed
318
                     (uint32_t)((uint64_t)1001000000 * 27 /
gbazin's avatar
 
gbazin committed
319
                         p_sys->p_info->sequence->frame_period % 1001) );
gbazin's avatar
 
gbazin committed
320 321

            mpeg2_custom_fbuf( p_sys->p_mpeg2dec, 1 );
gbazin's avatar
 
gbazin committed
322 323

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

gbazin's avatar
 
gbazin committed
326
            if( (p_pic = GetNewPicture( p_dec, buf )) == NULL )
327 328 329 330
            {
                block_Release( p_block );
                return NULL;
            }
gbazin's avatar
 
gbazin committed
331

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

334
            /* This picture will never go through display_picture. */
gbazin's avatar
 
gbazin committed
335 336
            p_pic->date = 0;

337 338
            /* 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
339
            p_dec->pf_picture_link( p_dec, p_pic );
340

gbazin's avatar
 
gbazin committed
341
            if( p_sys->p_synchro )
342
            {
gbazin's avatar
 
gbazin committed
343
                vout_SynchroRelease( p_sys->p_synchro );
344
            }
gbazin's avatar
 
gbazin committed
345
            p_sys->p_synchro = vout_SynchroInit( p_dec,
gbazin's avatar
 
gbazin committed
346 347 348
                (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
349 350
        }
        break;
gbazin's avatar
 
gbazin committed
351

352
        case STATE_PICTURE_2ND:
gbazin's avatar
 
gbazin committed
353 354 355
            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
356
                0, 0, p_sys->i_current_rate );
357

gbazin's avatar
 
gbazin committed
358
            if( p_sys->b_skip )
359
            {
gbazin's avatar
 
gbazin committed
360
                vout_SynchroTrash( p_sys->p_synchro );
361 362 363
            }
            else
            {
gbazin's avatar
 
gbazin committed
364
                vout_SynchroDecode( p_sys->p_synchro );
365 366 367
            }
            break;

gbazin's avatar
 
gbazin committed
368 369 370
        case STATE_PICTURE:
        {
            uint8_t *buf[3];
gbazin's avatar
 
gbazin committed
371
            mtime_t i_pts;
372 373
            buf[0] = buf[1] = buf[2] = NULL;

gbazin's avatar
 
gbazin committed
374 375 376
            if ( p_sys->b_after_sequence_header &&
                 ((p_sys->p_info->current_picture->flags &
                       PIC_MASK_CODING_TYPE) == PIC_FLAG_CODING_TYPE_P) )
377 378
            {
                /* Intra-slice refresh. Simulate a blank I picture. */
gbazin's avatar
 
gbazin committed
379 380 381 382 383 384
                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;
385
            }
gbazin's avatar
 
gbazin committed
386 387
            p_sys->b_after_sequence_header = 0;

gbazin's avatar
 
gbazin committed
388
#ifdef PIC_FLAG_PTS
gbazin's avatar
 
gbazin committed
389 390 391 392 393
            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;

gbazin's avatar
 
gbazin committed
394 395 396 397 398 399 400 401
#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;
#endif

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

gbazin's avatar
 
gbazin committed
415 416
            vout_SynchroNewPicture( p_sys->p_synchro,
                p_sys->p_info->current_picture->flags & PIC_MASK_CODING_TYPE,
417
                p_sys->p_info->current_picture->nb_fields, i_pts,
gbazin's avatar
 
gbazin committed
418 419 420 421
                0, p_sys->i_current_rate );

            if ( !(p_sys->b_slice_i
                   && ((p_sys->p_info->current_picture->flags
422
                         & PIC_MASK_CODING_TYPE) == P_CODING_TYPE))
gbazin's avatar
 
gbazin committed
423 424
                   && !vout_SynchroChoose( p_sys->p_synchro,
                              p_sys->p_info->current_picture->flags
gbazin's avatar
 
gbazin committed
425
                                & PIC_MASK_CODING_TYPE,
426
                              /*p_sys->p_vout->render_time*/ 0 /*FIXME*/ ) )
427
            {
gbazin's avatar
 
gbazin committed
428 429 430 431
                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 );
432 433
            }
            else
gbazin's avatar
 
gbazin committed
434
            {
gbazin's avatar
 
gbazin committed
435 436 437
                mpeg2_skip( p_sys->p_mpeg2dec, 0 );
                p_sys->b_skip = 0;
                vout_SynchroDecode( p_sys->p_synchro );
gbazin's avatar
 
gbazin committed
438 439

                if( (p_pic = GetNewPicture( p_dec, buf )) == NULL )
440 441 442 443
                {
                    block_Release( p_block );
                    return NULL;
                }
gbazin's avatar
 
gbazin committed
444

gbazin's avatar
 
gbazin committed
445
                mpeg2_set_buf( p_sys->p_mpeg2dec, buf, p_pic );
gbazin's avatar
 
gbazin committed
446 447
            }
        }
448
        break;
gbazin's avatar
 
gbazin committed
449 450

        case STATE_END:
451
        case STATE_SLICE:
gbazin's avatar
 
gbazin committed
452
            p_pic = NULL;
gbazin's avatar
 
gbazin committed
453 454
            if( p_sys->p_info->display_fbuf
                && p_sys->p_info->display_fbuf->id )
gbazin's avatar
 
gbazin committed
455
            {
gbazin's avatar
 
gbazin committed
456
                p_pic = (picture_t *)p_sys->p_info->display_fbuf->id;
gbazin's avatar
 
gbazin committed
457

gbazin's avatar
 
gbazin committed
458 459
                vout_SynchroEnd( p_sys->p_synchro,
                            p_sys->p_info->display_picture->flags
460
                             & PIC_MASK_CODING_TYPE,
gbazin's avatar
 
gbazin committed
461 462
                            p_sys->b_garbage_pic );
                p_sys->b_garbage_pic = 0;
463

gbazin's avatar
 
gbazin committed
464
                if ( p_sys->p_picture_to_destroy != p_pic )
465
                {
gbazin's avatar
 
gbazin committed
466
                    p_pic->date = vout_SynchroDate( p_sys->p_synchro );
467 468 469
                }
                else
                {
gbazin's avatar
 
gbazin committed
470
                    p_sys->p_picture_to_destroy = NULL;
gbazin's avatar
 
gbazin committed
471
                    p_pic->date = 0;
gbazin's avatar
 
gbazin committed
472
                }
473 474
            }

gbazin's avatar
 
gbazin committed
475 476
            if( p_sys->p_info->discard_fbuf &&
                p_sys->p_info->discard_fbuf->id )
477
            {
gbazin's avatar
 
gbazin committed
478 479
                p_dec->pf_picture_unlink( p_dec,
                                          p_sys->p_info->discard_fbuf->id );
gbazin's avatar
 
gbazin committed
480
            }
gbazin's avatar
 
gbazin committed
481

482
            if( p_pic ) return p_pic;
gbazin's avatar
 
gbazin committed
483

gbazin's avatar
 
gbazin committed
484 485
            break;

486
        case STATE_INVALID:
487 488 489 490
        {
            uint8_t *buf[3];
            buf[0] = buf[1] = buf[2] = NULL;

gbazin's avatar
 
gbazin committed
491
            msg_Warn( p_dec, "invalid picture encountered" );
Sam Hocevar's avatar
Sam Hocevar committed
492
            if ( ( p_sys->p_info->current_picture == NULL ) ||
gbazin's avatar
 
gbazin committed
493
               ( ( p_sys->p_info->current_picture->flags &
494
                   PIC_MASK_CODING_TYPE) != B_CODING_TYPE ) )
495
            {
496
                if( p_sys->p_synchro ) vout_SynchroReset( p_sys->p_synchro );
497
            }
gbazin's avatar
 
gbazin committed
498 499
            mpeg2_skip( p_sys->p_mpeg2dec, 1 );
            p_sys->b_skip = 1;
500

gbazin's avatar
 
gbazin committed
501 502
            if( p_sys->p_info->current_fbuf &&
                p_sys->p_info->current_fbuf->id )
503
            {
gbazin's avatar
 
gbazin committed
504 505
                p_sys->b_garbage_pic = 1;
                p_pic = p_sys->p_info->current_fbuf->id;
506
            }
507 508 509 510
            else if( !p_sys->p_info->sequence )
            {
                break;
            }
511 512 513 514
            else
            {
                if( (p_pic = GetNewPicture( p_dec, buf )) == NULL )
                    break;
gbazin's avatar
 
gbazin committed
515
                mpeg2_set_buf( p_sys->p_mpeg2dec, buf, p_pic );
516
            }
gbazin's avatar
 
gbazin committed
517
            p_sys->p_picture_to_destroy = p_pic;
518 519

            memset( p_pic->p[0].p_pixels, 0,
gbazin's avatar
 
gbazin committed
520 521
                    p_sys->p_info->sequence->width
                     * p_sys->p_info->sequence->height );
522
            memset( p_pic->p[1].p_pixels, 0x80,
gbazin's avatar
 
gbazin committed
523 524
                    p_sys->p_info->sequence->width
                     * p_sys->p_info->sequence->height / 4 );
525
            memset( p_pic->p[2].p_pixels, 0x80,
gbazin's avatar
 
gbazin committed
526 527
                    p_sys->p_info->sequence->width
                     * p_sys->p_info->sequence->height / 4 );
528

gbazin's avatar
 
gbazin committed
529
            if( p_sys->b_slice_i )
530
            {
gbazin's avatar
 
gbazin committed
531 532 533 534
                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 );
535
            }
536
            break;
537
        }
538

gbazin's avatar
 
gbazin committed
539 540 541 542 543
        default:
            break;
        }
    }

gbazin's avatar
 
gbazin committed
544 545
    /* Never reached */
    return NULL;
gbazin's avatar
 
gbazin committed
546 547 548
}

/*****************************************************************************
gbazin's avatar
 
gbazin committed
549
 * CloseDecoder: libmpeg2 decoder destruction
gbazin's avatar
 
gbazin committed
550
 *****************************************************************************/
gbazin's avatar
 
gbazin committed
551
static void CloseDecoder( vlc_object_t *p_this )
gbazin's avatar
 
gbazin committed
552
{
gbazin's avatar
 
gbazin committed
553
    decoder_t *p_dec = (decoder_t *)p_this;
gbazin's avatar
 
gbazin committed
554 555
    decoder_sys_t *p_sys = p_dec->p_sys;

gbazin's avatar
 
gbazin committed
556
    if( p_sys->p_synchro ) vout_SynchroRelease( p_sys->p_synchro );
gbazin's avatar
 
gbazin committed
557

gbazin's avatar
 
gbazin committed
558
    if( p_sys->p_mpeg2dec ) mpeg2_close( p_sys->p_mpeg2dec );
gbazin's avatar
 
gbazin committed
559

gbazin's avatar
 
gbazin committed
560
    free( p_sys );
gbazin's avatar
 
gbazin committed
561
}
gbazin's avatar
 
gbazin committed
562 563 564 565

/*****************************************************************************
 * GetNewPicture: Get a new picture from the vout and set the buf struct
 *****************************************************************************/
gbazin's avatar
 
gbazin committed
566
static picture_t *GetNewPicture( decoder_t *p_dec, uint8_t **pp_buf )
gbazin's avatar
 
gbazin committed
567
{
gbazin's avatar
 
gbazin committed
568
    decoder_sys_t *p_sys = p_dec->p_sys;
gbazin's avatar
 
gbazin committed
569
    picture_t *p_pic;
gbazin's avatar
 
gbazin committed
570

gbazin's avatar
 
gbazin committed
571 572 573
    p_dec->fmt_out.video.i_width = p_sys->p_info->sequence->width;
    p_dec->fmt_out.video.i_height = p_sys->p_info->sequence->height;
    p_dec->fmt_out.video.i_aspect = p_sys->i_aspect;
gbazin's avatar
 
gbazin committed
574

gbazin's avatar
 
gbazin committed
575 576 577 578
    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
579

gbazin's avatar
 
gbazin committed
580 581
    /* Get a new picture */
    p_pic = p_dec->pf_vout_buffer_new( p_dec );
gbazin's avatar
 
gbazin committed
582 583 584

    if( p_pic == NULL ) return NULL;

gbazin's avatar
 
gbazin committed
585 586 587 588 589 590 591
    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
592
    p_dec->pf_picture_link( p_dec, p_pic );
gbazin's avatar
 
gbazin committed
593 594 595 596 597 598 599

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