libmpeg2.c 29.4 KB
Newer Older
gbazin's avatar
 
gbazin committed
1 2 3
/*****************************************************************************
 * libmpeg2.c: mpeg2 video decoder module making use of libmpeg2.
 *****************************************************************************
4
 * Copyright (C) 1999-2001 the VideoLAN team
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
 * 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
dionoea's avatar
dionoea committed
22
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
gbazin's avatar
 
gbazin committed
23 24 25 26 27
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
28 29 30
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
31
#include <assert.h>
32

33
#include <vlc_common.h>
34
#include <vlc_plugin.h>
zorglub's avatar
zorglub committed
35
#include <vlc_codec.h>
36
#include <vlc_block_helper.h>
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
37
#include <vlc_cpu.h>
38
#include "../codec/cc.h"
gbazin's avatar
 
gbazin committed
39

40
#include <mpeg2.h>
gbazin's avatar
 
gbazin committed
41

42
#include <vlc_codec_synchro.h>
43

gbazin's avatar
 
gbazin committed
44
/*****************************************************************************
gbazin's avatar
 
gbazin committed
45
 * decoder_sys_t : libmpeg2 decoder descriptor
gbazin's avatar
 
gbazin committed
46
 *****************************************************************************/
47 48 49 50 51 52 53 54
#define DPB_COUNT (3+1)
typedef struct
{
    picture_t *p_picture;
    bool      b_linked;
    bool      b_displayed;
} picture_dpb_t;

gbazin's avatar
 
gbazin committed
55
struct decoder_sys_t
gbazin's avatar
 
gbazin committed
56 57 58 59 60 61
{
    /*
     * libmpeg2 properties
     */
    mpeg2dec_t          *p_mpeg2dec;
    const mpeg2_info_t  *p_info;
62
    bool                b_skip;
gbazin's avatar
 
gbazin committed
63 64 65 66 67 68

    /*
     * Input properties
     */
    mtime_t          i_previous_pts;
    mtime_t          i_current_pts;
69 70
    mtime_t          i_previous_dts;
    mtime_t          i_current_dts;
71 72
    bool             b_garbage_pic;
    bool             b_after_sequence_header; /* is it the next frame after
73
                                               * the sequence header ?    */
74 75
    bool             b_slice_i;             /* intra-slice refresh stream */
    bool             b_second_field;
gbazin's avatar
 
gbazin committed
76

77
    bool             b_preroll;
Laurent Aimar's avatar
Laurent Aimar committed
78

79 80 81
    /* */
    picture_dpb_t        p_dpb[DPB_COUNT];

gbazin's avatar
 
gbazin committed
82 83 84
    /*
     * Output properties
     */
85
    decoder_synchro_t *p_synchro;
86 87 88 89 90 91 92 93 94 95
    int             i_aspect;
    int             i_sar_num;
    int             i_sar_den;
    mtime_t         i_last_frame_pts;

    /* Closed captioning support */
    uint32_t        i_cc_flags;
    mtime_t         i_cc_pts;
    mtime_t         i_cc_dts;
    cc_data_t       cc;
96 97
    uint8_t        *p_gop_user_data;
    uint32_t        i_gop_user_data;
gbazin's avatar
 
gbazin committed
98
};
gbazin's avatar
 
gbazin committed
99 100 101 102

/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
gbazin's avatar
 
gbazin committed
103 104 105 106
static int  OpenDecoder( vlc_object_t * );
static void CloseDecoder( vlc_object_t * );

static picture_t *DecodeBlock( decoder_t *, block_t ** );
107
#if MPEG2_RELEASE >= MPEG2_VERSION (0, 5, 0)
108
static block_t   *GetCc( decoder_t *p_dec, bool pb_present[4] );
109
#endif
gbazin's avatar
 
gbazin committed
110

111 112 113
static picture_t *GetNewPicture( decoder_t * );
static void PutPicture( decoder_t *, picture_t * );

114
static void GetAR( decoder_t *p_dec );
gbazin's avatar
 
gbazin committed
115

116 117
static void Reset( decoder_t *p_dec );

118 119 120 121 122
/* */
static void DpbInit( decoder_t * );
static void DpbClean( decoder_t * );
static picture_t *DpbNewPicture( decoder_t * );
static void DpbUnlinkPicture( decoder_t *, picture_t * );
123
static int DpbDisplayPicture( decoder_t *, picture_t * );
124

gbazin's avatar
 
gbazin committed
125 126 127
/*****************************************************************************
 * Module descriptor
 *****************************************************************************/
128 129 130 131 132 133 134 135
vlc_module_begin ()
    set_description( N_("MPEG I/II video decoder (using libmpeg2)") )
    set_capability( "decoder", 150 )
    set_category( CAT_INPUT )
    set_subcategory( SUBCAT_INPUT_VCODEC )
    set_callbacks( OpenDecoder, CloseDecoder )
    add_shortcut( "libmpeg2" )
vlc_module_end ()
gbazin's avatar
 
gbazin committed
136 137 138 139 140 141

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

Laurent Aimar's avatar
Laurent Aimar committed
146
    if( p_dec->fmt_in.i_codec != VLC_CODEC_MPGV )
gbazin's avatar
 
gbazin committed
147
        return VLC_EGENERIC;
148

149 150 151 152 153 154 155 156 157 158 159 160 161
    /* Select onl recognized original format (standard mpeg video) */
    switch( p_dec->fmt_in.i_original_fourcc )
    {
    case VLC_FOURCC('m','p','g','1'):
    case VLC_FOURCC('m','p','g','2'):
    case VLC_FOURCC('m','p','g','v'):
    case VLC_FOURCC('P','I','M','1'):
    case VLC_FOURCC('h','d','v','2'):
        break;
    default:
        if( p_dec->fmt_in.i_original_fourcc )
            return VLC_EGENERIC;
        break;
gbazin's avatar
 
gbazin committed
162 163
    }

gbazin's avatar
 
gbazin committed
164
    /* Allocate the memory needed to store the decoder's structure */
165
    if( ( p_dec->p_sys = p_sys = calloc( 1, sizeof(*p_sys)) ) == NULL )
166
        return VLC_ENOMEM;
gbazin's avatar
 
gbazin committed
167 168

    /* Initialize the thread properties */
gbazin's avatar
 
gbazin committed
169 170 171 172 173
    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;
174 175
    p_sys->i_current_dts  = 0;
    p_sys->i_previous_dts = 0;
176
    p_sys->i_aspect = 0;
177 178 179 180
    p_sys->b_garbage_pic = false;
    p_sys->b_slice_i  = false;
    p_sys->b_second_field = false;
    p_sys->b_skip     = false;
181
    p_sys->b_preroll = false;
182
    DpbInit( p_dec );
gbazin's avatar
 
gbazin committed
183

184 185 186 187 188 189 190
    p_sys->i_cc_pts = 0;
    p_sys->i_cc_dts = 0;
    p_sys->i_cc_flags = 0;
#if MPEG2_RELEASE >= MPEG2_VERSION (0, 5, 0)
    p_dec->pf_get_cc = GetCc;
    cc_Init( &p_sys->cc );
#endif
191 192
    p_sys->p_gop_user_data = NULL;
    p_sys->i_gop_user_data = 0;
193

Christophe Massiot's avatar
Christophe Massiot committed
194
#if defined( __i386__ ) || defined( __x86_64__ )
195
    if( vlc_CPU() & CPU_CAPABILITY_MMX )
Sam Hocevar's avatar
Sam Hocevar committed
196 197 198 199
    {
        i_accel |= MPEG2_ACCEL_X86_MMX;
    }

200
    if( vlc_CPU() & CPU_CAPABILITY_3DNOW )
Sam Hocevar's avatar
Sam Hocevar committed
201 202 203 204
    {
        i_accel |= MPEG2_ACCEL_X86_3DNOW;
    }

205
    if( vlc_CPU() & CPU_CAPABILITY_MMXEXT )
Sam Hocevar's avatar
Sam Hocevar committed
206 207 208 209
    {
        i_accel |= MPEG2_ACCEL_X86_MMXEXT;
    }

hartman's avatar
hartman committed
210
#elif defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc64__ )
211
    if( vlc_CPU() & CPU_CAPABILITY_ALTIVEC )
Sam Hocevar's avatar
Sam Hocevar committed
212 213 214 215
    {
        i_accel |= MPEG2_ACCEL_PPC_ALTIVEC;
    }

216
#elif defined(__arm__)
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
217
    i_accel |= MPEG2_ACCEL_ARM;
218

219 220 221 222 223
# ifdef MPEG2_ACCEL_ARM_NEON
    if( vlc_CPU() & CPU_CAPABILITY_NEON )
	i_accel |= MPEG2_ACCEL_ARM_NEON;
# endif

Sam Hocevar's avatar
Sam Hocevar committed
224 225 226 227 228 229 230 231 232
#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
233
    /* Initialize decoder */
gbazin's avatar
 
gbazin committed
234 235
    p_sys->p_mpeg2dec = mpeg2_init();
    if( p_sys->p_mpeg2dec == NULL)
gbazin's avatar
 
gbazin committed
236 237
    {
        msg_Err( p_dec, "mpeg2_init() failed" );
gbazin's avatar
 
gbazin committed
238
        free( p_sys );
gbazin's avatar
 
gbazin committed
239 240
        return VLC_EGENERIC;
    }
gbazin's avatar
 
gbazin committed
241

gbazin's avatar
 
gbazin committed
242 243 244
    p_sys->p_info = mpeg2_info( p_sys->p_mpeg2dec );

    p_dec->pf_decode_video = DecodeBlock;
245 246
    p_dec->fmt_out.i_cat = VIDEO_ES;
    p_dec->fmt_out.i_codec = 0;
gbazin's avatar
 
gbazin committed
247 248 249

    return VLC_SUCCESS;
}
gbazin's avatar
 
gbazin committed
250

gbazin's avatar
 
gbazin committed
251 252 253
/*****************************************************************************
 * RunDecoder: the libmpeg2 decoder
 *****************************************************************************/
gbazin's avatar
 
gbazin committed
254
static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
gbazin's avatar
 
gbazin committed
255 256 257 258 259
{
    decoder_sys_t   *p_sys = p_dec->p_sys;
    mpeg2_state_t   state;
    picture_t       *p_pic;

gbazin's avatar
 
gbazin committed
260 261
    block_t *p_block;

262 263
    if( !pp_block || !*pp_block )
        return NULL;
gbazin's avatar
 
gbazin committed
264 265

    p_block = *pp_block;
266
    if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY | BLOCK_FLAG_CORRUPTED) )
267
        Reset( p_dec );
gbazin's avatar
 
gbazin committed
268 269

    while( 1 )
gbazin's avatar
 
gbazin committed
270
    {
gbazin's avatar
 
gbazin committed
271
        state = mpeg2_parse( p_sys->p_mpeg2dec );
gbazin's avatar
 
gbazin committed
272 273 274 275

        switch( state )
        {
        case STATE_SEQUENCE:
gbazin's avatar
 
gbazin committed
276
        {
277 278
            /* */
            DpbClean( p_dec );
gbazin's avatar
 
gbazin committed
279

280
            /* */
gbazin's avatar
 
gbazin committed
281
            mpeg2_custom_fbuf( p_sys->p_mpeg2dec, 1 );
gbazin's avatar
 
gbazin committed
282 283

            /* Set the first 2 reference frames */
284
            p_sys->i_aspect = 0;
285 286
            GetAR( p_dec );
            for( int i = 0; i < 2; i++ )
287
            {
288 289 290
                picture_t *p_picture = DpbNewPicture( p_dec );
                if( !p_picture )
                {
291
                    Reset( p_dec );
292 293 294 295
                    block_Release( p_block );
                    return NULL;
                }
                PutPicture( p_dec, p_picture );
296
            }
gbazin's avatar
 
gbazin committed
297 298

            if( p_sys->p_synchro )
299
                decoder_SynchroRelease( p_sys->p_synchro );
300

301 302 303 304 305 306
            if( p_sys->p_info->sequence->frame_period <= 0 )
                p_sys->p_synchro = NULL;
            else
                p_sys->p_synchro =
                decoder_SynchroInit( p_dec, (uint32_t)(UINT64_C(1001000000) *
                                27 / p_sys->p_info->sequence->frame_period) );
307 308
            p_sys->b_after_sequence_header = true;
            break;
gbazin's avatar
 
gbazin committed
309
        }
gbazin's avatar
 
gbazin committed
310

311 312 313 314 315 316 317 318 319 320 321 322
        case STATE_GOP:
            /* There can be userdata in a GOP. It needs to be remembered for the next picture. */
            if( p_sys->p_info->user_data_len > 2 )
            {
                free( p_sys->p_gop_user_data );
                p_sys->p_gop_user_data = calloc( p_sys->p_info->user_data_len, sizeof(uint8_t) );
                if( p_sys->p_gop_user_data )
                {
                    p_sys->i_gop_user_data = p_sys->p_info->user_data_len;
                    memcpy( p_sys->p_gop_user_data, p_sys->p_info->user_data, p_sys->p_info->user_data_len );
                }
            }
323 324
            break;

gbazin's avatar
 
gbazin committed
325 326
        case STATE_PICTURE:
        {
327 328 329
            const mpeg2_info_t *p_info = p_sys->p_info;
            const mpeg2_picture_t *p_current = p_info->current_picture;

330
            mtime_t i_pts, i_dts;
331

332 333 334
            if( p_sys->b_after_sequence_header &&
                (p_current->flags &
                    PIC_MASK_CODING_TYPE) == PIC_FLAG_CODING_TYPE_P )
335 336
            {
                /* Intra-slice refresh. Simulate a blank I picture. */
gbazin's avatar
 
gbazin committed
337
                msg_Dbg( p_dec, "intra-slice refresh stream" );
338
                decoder_SynchroNewPicture( p_sys->p_synchro,
339 340
                                           I_CODING_TYPE, 2, 0, 0,
                                           p_info->sequence->flags & SEQ_FLAG_LOW_DELAY );
341 342
                decoder_SynchroDecode( p_sys->p_synchro );
                decoder_SynchroEnd( p_sys->p_synchro, I_CODING_TYPE, 0 );
343
                p_sys->b_slice_i = true;
344
            }
345
            p_sys->b_after_sequence_header = false;
gbazin's avatar
 
gbazin committed
346

gbazin's avatar
 
gbazin committed
347
#ifdef PIC_FLAG_PTS
348 349
            i_pts = p_current->flags & PIC_FLAG_PTS ?
                ( ( p_current->pts ==
gbazin's avatar
 
gbazin committed
350 351
                    (uint32_t)p_sys->i_current_pts ) ?
                  p_sys->i_current_pts : p_sys->i_previous_pts ) : 0;
352
            i_dts = 0;
gbazin's avatar
 
gbazin committed
353

gbazin's avatar
 
gbazin committed
354 355 356
            /* Hack to handle demuxers which only have DTS timestamps */
            if( !i_pts && !p_block->i_pts && p_block->i_dts > 0 )
            {
357 358
                if( p_info->sequence->flags & SEQ_FLAG_LOW_DELAY ||
                    (p_current->flags &
gbazin's avatar
 
gbazin committed
359 360 361 362 363 364 365 366
                      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 */

367 368
#else /* New interface */

369 370 371 372 373 374
            i_pts = p_current->flags & PIC_FLAG_TAGS ?
                ( ( p_current->tag == (uint32_t)p_sys->i_current_pts ) ?
                            p_sys->i_current_pts : p_sys->i_previous_pts ) : 0;
            i_dts = p_current->flags & PIC_FLAG_TAGS ?
                ( ( p_current->tag2 == (uint32_t)p_sys->i_current_dts ) ?
                            p_sys->i_current_dts : p_sys->i_previous_dts ) : 0;
375 376
#endif

377 378
            /* If nb_fields == 1, it is a field picture, and it will be
             * followed by another field picture for which we won't call
379
             * decoder_SynchroNewPicture() because this would have other
380 381 382
             * problems, so we take it into account here.
             * This kind of sucks, but I didn't think better. --Meuuh
             */
383
            decoder_SynchroNewPicture( p_sys->p_synchro,
384 385 386 387
                                       p_current->flags & PIC_MASK_CODING_TYPE,
                                       p_current->nb_fields == 1 ? 2 :
                                       p_current->nb_fields, i_pts, i_dts,
                                       p_info->sequence->flags & SEQ_FLAG_LOW_DELAY );
gbazin's avatar
 
gbazin committed
388

389 390

            bool b_skip = false;
Laurent Aimar's avatar
Laurent Aimar committed
391
            if( !p_dec->b_pace_control && !p_sys->b_preroll &&
392
                !(p_sys->b_slice_i
393
                   && ((p_current->flags
394
                         & PIC_MASK_CODING_TYPE) == PIC_FLAG_CODING_TYPE_P))
395
                   && !decoder_SynchroChoose( p_sys->p_synchro,
396
                              p_current->flags
gbazin's avatar
 
gbazin committed
397
                                & PIC_MASK_CODING_TYPE,
398
                              /*p_sys->p_vout->render_time*/ 0 /*FIXME*/,
399
                              p_info->sequence->flags & SEQ_FLAG_LOW_DELAY ) )
400 401 402 403 404 405
            {
                b_skip = true;
            }

            p_pic = NULL;
            if( !b_skip )
406
            {
407
                p_pic = DpbNewPicture( p_dec );
408 409 410
                if( !p_pic )
                {
                    Reset( p_dec );
411 412 413 414 415 416 417 418

                    p_pic = DpbNewPicture( p_dec );
                    if( !p_pic )
                    {
                        mpeg2_reset( p_sys->p_mpeg2dec, 1 );
                        block_Release( p_block );
                        return NULL;
                    }
419 420
                }
            }
421 422

            if( b_skip || !p_pic )
423
            {
gbazin's avatar
 
gbazin committed
424
                mpeg2_skip( p_sys->p_mpeg2dec, 1 );
425
                p_sys->b_skip = true;
426
                decoder_SynchroTrash( p_sys->p_synchro );
427 428

                PutPicture( p_dec, NULL );
429 430 431 432 433 434

                if( !b_skip )
                {
                    block_Release( p_block );
                    return NULL;
                }
435 436
            }
            else
gbazin's avatar
 
gbazin committed
437
            {
gbazin's avatar
 
gbazin committed
438
                mpeg2_skip( p_sys->p_mpeg2dec, 0 );
439
                p_sys->b_skip = false;
440
                decoder_SynchroDecode( p_sys->p_synchro );
gbazin's avatar
 
gbazin committed
441

442
                PutPicture( p_dec, p_pic );
443
            }
444
            if( p_info->user_data_len > 2 || p_sys->i_gop_user_data > 2 )
445 446 447
            {
                p_sys->i_cc_pts = i_pts;
                p_sys->i_cc_dts = i_dts;
448
                if( (p_current->flags
449 450
                             & PIC_MASK_CODING_TYPE) == PIC_FLAG_CODING_TYPE_P )
                    p_sys->i_cc_flags = BLOCK_FLAG_TYPE_P;
451
                else if( (p_current->flags
452 453 454 455
                             & PIC_MASK_CODING_TYPE) == PIC_FLAG_CODING_TYPE_B )
                    p_sys->i_cc_flags = BLOCK_FLAG_TYPE_B;
                else p_sys->i_cc_flags = BLOCK_FLAG_TYPE_I;

456 457 458 459 460 461 462 463
                if( p_sys->i_gop_user_data > 2 )
                {
                    /* We now have picture info for any cached user_data out of the gop */
                    cc_Extract( &p_sys->cc, &p_sys->p_gop_user_data[0], p_sys->i_gop_user_data );
                    p_sys->i_gop_user_data = 0;
                }

                /* Extract the CC from the user_data of the picture */
464 465
                if( p_info->user_data_len > 2 )
                    cc_Extract( &p_sys->cc, &p_info->user_data[0], p_info->user_data_len );
gbazin's avatar
 
gbazin committed
466 467
            }
        }
468
        break;
gbazin's avatar
 
gbazin committed
469

470 471 472

        case STATE_BUFFER:
            if( !p_block->i_buffer )
473
            {
474 475 476 477 478 479 480 481 482 483 484 485 486
                block_Release( p_block );
                return NULL;
            }

            if( (p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY
                                      | BLOCK_FLAG_CORRUPTED)) &&
                p_sys->p_synchro &&
                p_sys->p_info->sequence &&
                p_sys->p_info->sequence->width != (unsigned)-1 )
            {
                decoder_SynchroReset( p_sys->p_synchro );
                if( p_sys->p_info->current_fbuf != NULL &&
                    p_sys->p_info->current_fbuf->id != NULL )
487
                {
488 489 490 491 492 493 494 495 496 497
                    p_sys->b_garbage_pic = true;
                }
                if( p_sys->b_slice_i )
                {
                    decoder_SynchroNewPicture( p_sys->p_synchro,
                                               I_CODING_TYPE, 2, 0, 0,
                                               p_sys->p_info->sequence->flags &
                                                            SEQ_FLAG_LOW_DELAY );
                    decoder_SynchroDecode( p_sys->p_synchro );
                    decoder_SynchroEnd( p_sys->p_synchro, I_CODING_TYPE, 0 );
498 499
                }
            }
500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543

            if( p_block->i_flags & BLOCK_FLAG_PREROLL )
            {
                p_sys->b_preroll = true;
            }
            else if( p_sys->b_preroll )
            {
                p_sys->b_preroll = false;
                if( p_sys->p_synchro )
                    decoder_SynchroReset( p_sys->p_synchro );
            }

#ifdef PIC_FLAG_PTS
            if( p_block->i_pts )
            {
                mpeg2_pts( p_sys->p_mpeg2dec, (uint32_t)p_block->i_pts );

#else /* New interface */
            if( p_block->i_pts || p_block->i_dts )
            {
                mpeg2_tag_picture( p_sys->p_mpeg2dec,
                                   (uint32_t)p_block->i_pts,
                                   (uint32_t)p_block->i_dts );
#endif
                p_sys->i_previous_pts = p_sys->i_current_pts;
                p_sys->i_current_pts = p_block->i_pts;
                p_sys->i_previous_dts = p_sys->i_current_dts;
                p_sys->i_current_dts = p_block->i_dts;
            }

            mpeg2_buffer( p_sys->p_mpeg2dec, p_block->p_buffer,
                          p_block->p_buffer + p_block->i_buffer );

            p_block->i_buffer = 0;
            break;

#if MPEG2_RELEASE >= MPEG2_VERSION (0, 5, 0)

        case STATE_SEQUENCE_MODIFIED:
            GetAR( p_dec );
            break;
#endif
        case STATE_PICTURE_2ND:
            p_sys->b_second_field = true;
544 545
            break;

546 547

        case STATE_INVALID_END:
gbazin's avatar
 
gbazin committed
548
        case STATE_END:
549
        case STATE_SLICE:
gbazin's avatar
 
gbazin committed
550
            p_pic = NULL;
551 552
            if( p_sys->p_info->display_fbuf &&
                p_sys->p_info->display_fbuf->id )
gbazin's avatar
 
gbazin committed
553
            {
554
                p_pic = p_sys->p_info->display_fbuf->id;
555 556
                if( DpbDisplayPicture( p_dec, p_pic ) )
                    p_pic = NULL;
gbazin's avatar
 
gbazin committed
557

558
                decoder_SynchroEnd( p_sys->p_synchro,
559 560
                                    p_sys->p_info->display_picture->flags & PIC_MASK_CODING_TYPE,
                                    p_sys->b_garbage_pic );
561

562 563 564 565 566 567 568
                if( p_pic )
                {
                    p_pic->date = decoder_SynchroDate( p_sys->p_synchro );
                    if( p_sys->b_garbage_pic )
                        p_pic->date = 0; /* ??? */
                    p_sys->b_garbage_pic = false;
                }
569 570
            }

gbazin's avatar
 
gbazin committed
571 572
            if( p_sys->p_info->discard_fbuf &&
                p_sys->p_info->discard_fbuf->id )
573
            {
574
                DpbUnlinkPicture( p_dec, p_sys->p_info->discard_fbuf->id );
gbazin's avatar
 
gbazin committed
575
            }
gbazin's avatar
 
gbazin committed
576

577
            /* For still frames */
578 579
            if( state == STATE_END && p_pic )
                p_pic->b_force = true;
580 581 582 583 584

            if( p_pic )
            {
                /* Avoid frames with identical timestamps.
                 * Especially needed for still frames in DVD menus. */
585 586
                if( p_sys->i_last_frame_pts == p_pic->date )
                    p_pic->date++;
587 588 589
                p_sys->i_last_frame_pts = p_pic->date;
                return p_pic;
            }
gbazin's avatar
 
gbazin committed
590 591
            break;

592
        case STATE_INVALID:
593
        {
594 595 596
            msg_Err( p_dec, "invalid picture encountered" );
            /* I don't think we have anything to do, but well without
             * docs ... */
597
            break;
598
        }
599

gbazin's avatar
 
gbazin committed
600 601 602 603 604
        default:
            break;
        }
    }

gbazin's avatar
 
gbazin committed
605 606
    /* Never reached */
    return NULL;
gbazin's avatar
 
gbazin committed
607 608 609
}

/*****************************************************************************
gbazin's avatar
 
gbazin committed
610
 * CloseDecoder: libmpeg2 decoder destruction
gbazin's avatar
 
gbazin committed
611
 *****************************************************************************/
gbazin's avatar
 
gbazin committed
612
static void CloseDecoder( vlc_object_t *p_this )
gbazin's avatar
 
gbazin committed
613
{
gbazin's avatar
 
gbazin committed
614
    decoder_t *p_dec = (decoder_t *)p_this;
gbazin's avatar
 
gbazin committed
615 616
    decoder_sys_t *p_sys = p_dec->p_sys;

617 618
    DpbClean( p_dec );

619 620
    free( p_sys->p_gop_user_data );

621
    if( p_sys->p_synchro ) decoder_SynchroRelease( p_sys->p_synchro );
gbazin's avatar
 
gbazin committed
622

gbazin's avatar
 
gbazin committed
623
    if( p_sys->p_mpeg2dec ) mpeg2_close( p_sys->p_mpeg2dec );
gbazin's avatar
 
gbazin committed
624

gbazin's avatar
 
gbazin committed
625
    free( p_sys );
gbazin's avatar
 
gbazin committed
626
}
gbazin's avatar
 
gbazin committed
627

628 629 630 631 632 633 634 635
/*****************************************************************************
 * Reset: reset the decoder state
 *****************************************************************************/
static void Reset( decoder_t *p_dec )
{
    decoder_sys_t *p_sys = p_dec->p_sys;

    cc_Flush( &p_sys->cc );
636
    mpeg2_reset( p_sys->p_mpeg2dec, 0 );
637 638 639
    DpbClean( p_dec );
}

gbazin's avatar
 
gbazin committed
640 641 642
/*****************************************************************************
 * GetNewPicture: Get a new picture from the vout and set the buf struct
 *****************************************************************************/
643
static picture_t *GetNewPicture( decoder_t *p_dec )
gbazin's avatar
 
gbazin committed
644
{
gbazin's avatar
 
gbazin committed
645
    decoder_sys_t *p_sys = p_dec->p_sys;
gbazin's avatar
 
gbazin committed
646
    picture_t *p_pic;
gbazin's avatar
 
gbazin committed
647

gbazin's avatar
 
gbazin committed
648
    p_dec->fmt_out.video.i_width = p_sys->p_info->sequence->width;
649 650
    p_dec->fmt_out.video.i_visible_width =
        p_sys->p_info->sequence->picture_width;
gbazin's avatar
 
gbazin committed
651
    p_dec->fmt_out.video.i_height = p_sys->p_info->sequence->height;
652 653
    p_dec->fmt_out.video.i_visible_height =
        p_sys->p_info->sequence->picture_height;
gbazin's avatar
 
gbazin committed
654
    p_dec->fmt_out.video.i_aspect = p_sys->i_aspect;
655 656
    p_dec->fmt_out.video.i_sar_num = p_sys->i_sar_num;
    p_dec->fmt_out.video.i_sar_den = p_sys->i_sar_den;
gbazin's avatar
 
gbazin committed
657

658 659 660 661 662 663 664 665
    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
666 667 668
    p_dec->fmt_out.i_codec =
        ( p_sys->p_info->sequence->chroma_height <
          p_sys->p_info->sequence->height ) ?
669
        VLC_CODEC_I420 : VLC_CODEC_I422;
gbazin's avatar
 
gbazin committed
670

gbazin's avatar
 
gbazin committed
671
    /* Get a new picture */
672
    p_pic = decoder_NewPicture( p_dec );
gbazin's avatar
 
gbazin committed
673

674 675
    if( p_pic == NULL )
        return NULL;
gbazin's avatar
 
gbazin committed
676

gbazin's avatar
 
gbazin committed
677 678 679 680 681 682 683
    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
684 685
    return p_pic;
}
686

687
#if MPEG2_RELEASE >= MPEG2_VERSION (0, 5, 0)
688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713
/*****************************************************************************
 * GetCc: Retrieves the Closed Captions for the CC decoder.
 *****************************************************************************/
static block_t *GetCc( decoder_t *p_dec, bool pb_present[4] )
{
    decoder_sys_t   *p_sys = p_dec->p_sys;
    block_t         *p_cc = NULL;
    int i;

    for( i = 0; i < 4; i++ )
        pb_present[i] = p_sys->cc.pb_present[i];

    if( p_sys->cc.i_data <= 0 )
        return NULL;

    p_cc = block_New( p_dec, p_sys->cc.i_data);
    if( p_cc )
    {
        memcpy( p_cc->p_buffer, p_sys->cc.p_data, p_sys->cc.i_data );
        p_cc->i_dts =
        p_cc->i_pts = p_sys->cc.b_reorder ? p_sys->i_cc_pts : p_sys->i_cc_dts;
        p_cc->i_flags = ( p_sys->cc.b_reorder  ? p_sys->i_cc_flags : BLOCK_FLAG_TYPE_P ) & ( BLOCK_FLAG_TYPE_I|BLOCK_FLAG_TYPE_P|BLOCK_FLAG_TYPE_B);
    }
    cc_Flush( &p_sys->cc );
    return p_cc;
}
714
#endif
715

716 717 718 719 720
/*****************************************************************************
 * GetAR: Get aspect ratio
 *****************************************************************************/
static void GetAR( decoder_t *p_dec )
{
721
    decoder_sys_t *p_sys = p_dec->p_sys;
722
    int i_old_aspect = p_sys->i_aspect;
723 724 725 726 727 728 729 730 731 732 733 734

    /* Check whether the input gave a particular aspect ratio */
    if( p_dec->fmt_in.video.i_aspect )
    {
        p_sys->i_aspect = p_dec->fmt_in.video.i_aspect;
    }
    else
    {
        /* Use the value provided in the MPEG sequence header */
        if( p_sys->p_info->sequence->pixel_height > 0 )
        {
            p_sys->i_aspect =
735
                ((uint64_t)p_sys->p_info->sequence->display_width) *
736 737
                p_sys->p_info->sequence->pixel_width *
                VOUT_ASPECT_FACTOR /
738
                p_sys->p_info->sequence->display_height /
739
                p_sys->p_info->sequence->pixel_height;
740 741
            p_sys->i_sar_num = p_sys->p_info->sequence->pixel_width;
            p_sys->i_sar_den = p_sys->p_info->sequence->pixel_height;
742 743 744 745 746 747 748
        }
        else
        {
            /* 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;
749 750
            p_sys->i_sar_num = p_sys->p_info->sequence->picture_height * 4;
            p_sys->i_sar_den = p_sys->p_info->sequence->picture_width * 3;
751 752 753
        }
    }

754 755 756
    if( p_sys->i_aspect == i_old_aspect )
        return;

757 758 759 760 761 762 763 764 765 766 767 768 769 770
    if( p_sys->p_info->sequence->frame_period > 0 )
        msg_Dbg( p_dec,
                 "%dx%d (display %d,%d), aspect %d, sar %i:%i, %u.%03u fps",
                 p_sys->p_info->sequence->picture_width,
                 p_sys->p_info->sequence->picture_height,
                 p_sys->p_info->sequence->display_width,
                 p_sys->p_info->sequence->display_height,
                 p_sys->i_aspect, p_sys->i_sar_num, p_sys->i_sar_den,
                 (uint32_t)((uint64_t)1001000000 * 27 /
                     p_sys->p_info->sequence->frame_period / 1001),
                 (uint32_t)((uint64_t)1001000000 * 27 /
                     p_sys->p_info->sequence->frame_period % 1001) );
    else
        msg_Dbg( p_dec, "bad frame period" );
771
}
772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875

/*****************************************************************************
 * PutPicture: Put a picture_t in mpeg2 context
 *****************************************************************************/
static void PutPicture( decoder_t *p_dec, picture_t *p_picture )
{
    decoder_sys_t *p_sys = p_dec->p_sys;

    /* */
    uint8_t *pp_buf[3];
    for( int j = 0; j < 3; j++ )
        pp_buf[j] = p_picture ? p_picture->p[j].p_pixels : NULL;
    mpeg2_set_buf( p_sys->p_mpeg2dec, pp_buf, p_picture );

    /* Completly broken API, why the hell does it suppose
     * the stride of the chroma planes ! */
    if( p_picture )
        mpeg2_stride( p_sys->p_mpeg2dec, p_picture->p[Y_PLANE].i_pitch );
}


/**
 * Initialize a virtual Decoded Picture Buffer to workaround
 * libmpeg2 deficient API
 */
static void DpbInit( decoder_t *p_dec )
{
    decoder_sys_t *p_sys = p_dec->p_sys;

    for( int i = 0; i < DPB_COUNT; i++ )
        p_sys->p_dpb[i].p_picture = NULL;
}
/**
 * Empty and reset the current DPB
 */
static void DpbClean( decoder_t *p_dec )
{
    decoder_sys_t *p_sys = p_dec->p_sys;

    for( int i = 0; i < DPB_COUNT; i++ )
    {
        picture_dpb_t *p = &p_sys->p_dpb[i];
        if( !p->p_picture )
            continue;
        if( p->b_linked )
            decoder_UnlinkPicture( p_dec, p->p_picture );
        if( !p->b_displayed )
            decoder_DeletePicture( p_dec, p->p_picture );

        p->p_picture = NULL;
    }
}
/**
 * Retreive a picture and reserve a place in the DPB
 */
static picture_t *DpbNewPicture( decoder_t *p_dec )
{
    decoder_sys_t *p_sys = p_dec->p_sys;

    picture_dpb_t *p;
    int i;

    for( i = 0; i < DPB_COUNT; i++ )
    {
        p = &p_sys->p_dpb[i];
        if( !p->p_picture )
            break;
    }
    if( i >= DPB_COUNT )
    {
        msg_Err( p_dec, "Leaking picture" );
        return NULL;
    }

    p->p_picture = GetNewPicture( p_dec );
    if( p->p_picture )
    {
        decoder_LinkPicture( p_dec, p->p_picture );
        p->b_linked = true;
        p->b_displayed = false;

        p->p_picture->date = 0;
    }
    return p->p_picture;
}
static picture_dpb_t *DpbFindPicture( decoder_t *p_dec, picture_t *p_picture )
{
    decoder_sys_t *p_sys = p_dec->p_sys;

    for( int i = 0; i < DPB_COUNT; i++ )
    {
        picture_dpb_t *p = &p_sys->p_dpb[i];
        if( p->p_picture == p_picture )
            return p;
    }
    return NULL;
}
/**
 * Unlink the provided picture and ensure that the decoder
 * does not own it anymore.
 */
static void DpbUnlinkPicture( decoder_t *p_dec, picture_t *p_picture )
{
    picture_dpb_t *p = DpbFindPicture( p_dec, p_picture );
876 877 878 879 880 881 882 883

    /* XXX it is needed to workaround libmpeg2 bugs */
    if( !p || !p->b_linked )
    {
        msg_Err( p_dec, "DpbUnlinkPicture called on an invalid picture" );
        return;
    }

884 885 886 887 888 889 890 891 892 893 894 895
    assert( p && p->b_linked );

    decoder_UnlinkPicture( p_dec, p->p_picture );
    p->b_linked = false;

    if( !p->b_displayed )
        decoder_DeletePicture( p_dec, p->p_picture );
    p->p_picture = NULL;
}
/**
 * Mark the provided picture as displayed.
 */
896
static int DpbDisplayPicture( decoder_t *p_dec, picture_t *p_picture )
897 898
{
    picture_dpb_t *p = DpbFindPicture( p_dec, p_picture );
899 900 901 902 903 904 905 906

    /* XXX it is needed to workaround libmpeg2 bugs */
    if( !p || p->b_displayed || !p->b_linked )
    {
        msg_Err( p_dec, "DpbDisplayPicture called on an invalid picture" );
        return VLC_EGENERIC;
    }

907 908 909
    assert( p && !p->b_displayed && p->b_linked );

    p->b_displayed = true;
910
    return VLC_SUCCESS;
911 912 913
}