libmpeg2.c 29.3 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

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

gbazin's avatar
 
gbazin committed
237 238 239
    p_sys->p_info = mpeg2_info( p_sys->p_mpeg2dec );

    p_dec->pf_decode_video = DecodeBlock;
240 241
    p_dec->fmt_out.i_cat = VIDEO_ES;
    p_dec->fmt_out.i_codec = 0;
gbazin's avatar
 
gbazin committed
242 243 244

    return VLC_SUCCESS;
}
gbazin's avatar
 
gbazin committed
245

gbazin's avatar
 
gbazin committed
246 247 248
/*****************************************************************************
 * RunDecoder: the libmpeg2 decoder
 *****************************************************************************/
gbazin's avatar
 
gbazin committed
249
static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
gbazin's avatar
 
gbazin committed
250 251 252 253 254
{
    decoder_sys_t   *p_sys = p_dec->p_sys;
    mpeg2_state_t   state;
    picture_t       *p_pic;

gbazin's avatar
 
gbazin committed
255 256
    block_t *p_block;

257 258
    if( !pp_block || !*pp_block )
        return NULL;
gbazin's avatar
 
gbazin committed
259 260

    p_block = *pp_block;
261
    if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY | BLOCK_FLAG_CORRUPTED) )
262
        Reset( p_dec );
gbazin's avatar
 
gbazin committed
263 264

    while( 1 )
gbazin's avatar
 
gbazin committed
265
    {
gbazin's avatar
 
gbazin committed
266
        state = mpeg2_parse( p_sys->p_mpeg2dec );
gbazin's avatar
 
gbazin committed
267 268 269 270

        switch( state )
        {
        case STATE_SEQUENCE:
gbazin's avatar
 
gbazin committed
271
        {
272 273
            /* */
            DpbClean( p_dec );
gbazin's avatar
 
gbazin committed
274

275
            /* */
gbazin's avatar
 
gbazin committed
276
            mpeg2_custom_fbuf( p_sys->p_mpeg2dec, 1 );
gbazin's avatar
 
gbazin committed
277 278

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

            if( p_sys->p_synchro )
294
                decoder_SynchroRelease( p_sys->p_synchro );
295

296 297 298 299 300 301
            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) );
302 303
            p_sys->b_after_sequence_header = true;
            break;
gbazin's avatar
 
gbazin committed
304
        }
gbazin's avatar
 
gbazin committed
305

306 307 308 309 310 311 312 313 314 315 316 317
        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 );
                }
            }
318 319
            break;

gbazin's avatar
 
gbazin committed
320 321
        case STATE_PICTURE:
        {
322 323 324
            const mpeg2_info_t *p_info = p_sys->p_info;
            const mpeg2_picture_t *p_current = p_info->current_picture;

325
            mtime_t i_pts, i_dts;
326

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

gbazin's avatar
 
gbazin committed
342
#ifdef PIC_FLAG_PTS
343 344
            i_pts = p_current->flags & PIC_FLAG_PTS ?
                ( ( p_current->pts ==
gbazin's avatar
 
gbazin committed
345 346
                    (uint32_t)p_sys->i_current_pts ) ?
                  p_sys->i_current_pts : p_sys->i_previous_pts ) : 0;
347
            i_dts = 0;
gbazin's avatar
 
gbazin committed
348

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

362 363
#else /* New interface */

364 365 366 367 368 369
            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;
370 371
#endif

372 373
            /* If nb_fields == 1, it is a field picture, and it will be
             * followed by another field picture for which we won't call
374
             * decoder_SynchroNewPicture() because this would have other
375 376 377
             * problems, so we take it into account here.
             * This kind of sucks, but I didn't think better. --Meuuh
             */
378
            decoder_SynchroNewPicture( p_sys->p_synchro,
379 380 381 382
                                       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
383

384 385

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

            p_pic = NULL;
            if( !b_skip )
401
            {
402
                p_pic = DpbNewPicture( p_dec );
403 404 405
                if( !p_pic )
                {
                    Reset( p_dec );
406 407 408 409 410 411 412 413

                    p_pic = DpbNewPicture( p_dec );
                    if( !p_pic )
                    {
                        mpeg2_reset( p_sys->p_mpeg2dec, 1 );
                        block_Release( p_block );
                        return NULL;
                    }
414 415
                }
            }
416 417

            if( b_skip || !p_pic )
418
            {
gbazin's avatar
 
gbazin committed
419
                mpeg2_skip( p_sys->p_mpeg2dec, 1 );
420
                p_sys->b_skip = true;
421
                decoder_SynchroTrash( p_sys->p_synchro );
422 423

                PutPicture( p_dec, NULL );
424 425 426 427 428 429

                if( !b_skip )
                {
                    block_Release( p_block );
                    return NULL;
                }
430 431
            }
            else
gbazin's avatar
 
gbazin committed
432
            {
gbazin's avatar
 
gbazin committed
433
                mpeg2_skip( p_sys->p_mpeg2dec, 0 );
434
                p_sys->b_skip = false;
435
                decoder_SynchroDecode( p_sys->p_synchro );
gbazin's avatar
 
gbazin committed
436

437
                PutPicture( p_dec, p_pic );
438
            }
439
            if( p_info->user_data_len > 2 || p_sys->i_gop_user_data > 2 )
440 441 442
            {
                p_sys->i_cc_pts = i_pts;
                p_sys->i_cc_dts = i_dts;
443
                if( (p_current->flags
444 445
                             & PIC_MASK_CODING_TYPE) == PIC_FLAG_CODING_TYPE_P )
                    p_sys->i_cc_flags = BLOCK_FLAG_TYPE_P;
446
                else if( (p_current->flags
447 448 449 450
                             & 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;

451 452 453 454 455 456 457 458
                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 */
459 460
                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
461 462
            }
        }
463
        break;
gbazin's avatar
 
gbazin committed
464

465 466 467

        case STATE_BUFFER:
            if( !p_block->i_buffer )
468
            {
469 470 471 472 473 474 475 476 477 478 479 480 481
                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 )
482
                {
483 484 485 486 487 488 489 490 491 492
                    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 );
493 494
                }
            }
495 496 497 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

            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;
539 540
            break;

541 542

        case STATE_INVALID_END:
gbazin's avatar
 
gbazin committed
543
        case STATE_END:
544
        case STATE_SLICE:
gbazin's avatar
 
gbazin committed
545
            p_pic = NULL;
546 547
            if( p_sys->p_info->display_fbuf &&
                p_sys->p_info->display_fbuf->id )
gbazin's avatar
 
gbazin committed
548
            {
549
                p_pic = p_sys->p_info->display_fbuf->id;
550 551
                if( DpbDisplayPicture( p_dec, p_pic ) )
                    p_pic = NULL;
gbazin's avatar
 
gbazin committed
552

553
                decoder_SynchroEnd( p_sys->p_synchro,
554 555
                                    p_sys->p_info->display_picture->flags & PIC_MASK_CODING_TYPE,
                                    p_sys->b_garbage_pic );
556

557 558 559 560 561 562 563
                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;
                }
564 565
            }

gbazin's avatar
 
gbazin committed
566 567
            if( p_sys->p_info->discard_fbuf &&
                p_sys->p_info->discard_fbuf->id )
568
            {
569
                DpbUnlinkPicture( p_dec, p_sys->p_info->discard_fbuf->id );
gbazin's avatar
 
gbazin committed
570
            }
gbazin's avatar
 
gbazin committed
571

572
            /* For still frames */
573 574
            if( state == STATE_END && p_pic )
                p_pic->b_force = true;
575 576 577 578 579

            if( p_pic )
            {
                /* Avoid frames with identical timestamps.
                 * Especially needed for still frames in DVD menus. */
580 581
                if( p_sys->i_last_frame_pts == p_pic->date )
                    p_pic->date++;
582 583 584
                p_sys->i_last_frame_pts = p_pic->date;
                return p_pic;
            }
gbazin's avatar
 
gbazin committed
585 586
            break;

587
        case STATE_INVALID:
588
        {
589 590 591
            msg_Err( p_dec, "invalid picture encountered" );
            /* I don't think we have anything to do, but well without
             * docs ... */
592
            break;
593
        }
594

gbazin's avatar
 
gbazin committed
595 596 597 598 599
        default:
            break;
        }
    }

gbazin's avatar
 
gbazin committed
600 601
    /* Never reached */
    return NULL;
gbazin's avatar
 
gbazin committed
602 603 604
}

/*****************************************************************************
gbazin's avatar
 
gbazin committed
605
 * CloseDecoder: libmpeg2 decoder destruction
gbazin's avatar
 
gbazin committed
606
 *****************************************************************************/
gbazin's avatar
 
gbazin committed
607
static void CloseDecoder( vlc_object_t *p_this )
gbazin's avatar
 
gbazin committed
608
{
gbazin's avatar
 
gbazin committed
609
    decoder_t *p_dec = (decoder_t *)p_this;
gbazin's avatar
 
gbazin committed
610 611
    decoder_sys_t *p_sys = p_dec->p_sys;

612 613
    DpbClean( p_dec );

614 615
    free( p_sys->p_gop_user_data );

616
    if( p_sys->p_synchro ) decoder_SynchroRelease( p_sys->p_synchro );
gbazin's avatar
 
gbazin committed
617

gbazin's avatar
 
gbazin committed
618
    if( p_sys->p_mpeg2dec ) mpeg2_close( p_sys->p_mpeg2dec );
gbazin's avatar
 
gbazin committed
619

gbazin's avatar
 
gbazin committed
620
    free( p_sys );
gbazin's avatar
 
gbazin committed
621
}
gbazin's avatar
 
gbazin committed
622

623 624 625 626 627 628 629 630
/*****************************************************************************
 * 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 );
631
    mpeg2_reset( p_sys->p_mpeg2dec, 0 );
632 633 634
    DpbClean( p_dec );
}

gbazin's avatar
 
gbazin committed
635 636 637
/*****************************************************************************
 * GetNewPicture: Get a new picture from the vout and set the buf struct
 *****************************************************************************/
638
static picture_t *GetNewPicture( decoder_t *p_dec )
gbazin's avatar
 
gbazin committed
639
{
gbazin's avatar
 
gbazin committed
640
    decoder_sys_t *p_sys = p_dec->p_sys;
gbazin's avatar
 
gbazin committed
641
    picture_t *p_pic;
gbazin's avatar
 
gbazin committed
642

gbazin's avatar
 
gbazin committed
643
    p_dec->fmt_out.video.i_width = p_sys->p_info->sequence->width;
644 645
    p_dec->fmt_out.video.i_visible_width =
        p_sys->p_info->sequence->picture_width;
gbazin's avatar
 
gbazin committed
646
    p_dec->fmt_out.video.i_height = p_sys->p_info->sequence->height;
647 648
    p_dec->fmt_out.video.i_visible_height =
        p_sys->p_info->sequence->picture_height;
gbazin's avatar
 
gbazin committed
649
    p_dec->fmt_out.video.i_aspect = p_sys->i_aspect;
650 651
    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
652

653 654 655 656 657 658 659 660
    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
661 662 663
    p_dec->fmt_out.i_codec =
        ( p_sys->p_info->sequence->chroma_height <
          p_sys->p_info->sequence->height ) ?
664
        VLC_CODEC_I420 : VLC_CODEC_I422;
gbazin's avatar
 
gbazin committed
665

gbazin's avatar
 
gbazin committed
666
    /* Get a new picture */
667
    p_pic = decoder_NewPicture( p_dec );
gbazin's avatar
 
gbazin committed
668

669 670
    if( p_pic == NULL )
        return NULL;
gbazin's avatar
 
gbazin committed
671

gbazin's avatar
 
gbazin committed
672 673 674 675 676 677 678
    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
679 680
    return p_pic;
}
681

682
#if MPEG2_RELEASE >= MPEG2_VERSION (0, 5, 0)
683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708
/*****************************************************************************
 * 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;
}
709
#endif
710

711 712 713 714 715
/*****************************************************************************
 * GetAR: Get aspect ratio
 *****************************************************************************/
static void GetAR( decoder_t *p_dec )
{
716
    decoder_sys_t *p_sys = p_dec->p_sys;
717
    int i_old_aspect = p_sys->i_aspect;
718 719 720 721 722 723 724 725 726 727 728 729

    /* 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 =
730
                ((uint64_t)p_sys->p_info->sequence->picture_width) *
731 732
                p_sys->p_info->sequence->pixel_width *
                VOUT_ASPECT_FACTOR /
733
                p_sys->p_info->sequence->picture_height /
734
                p_sys->p_info->sequence->pixel_height;
735 736
            p_sys->i_sar_num = p_sys->p_info->sequence->pixel_width;
            p_sys->i_sar_den = p_sys->p_info->sequence->pixel_height;
737 738 739 740 741 742 743
        }
        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;
744 745
            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;
746 747 748
        }
    }

749 750 751
    if( p_sys->i_aspect == i_old_aspect )
        return;

752 753 754 755 756 757 758 759 760 761 762 763 764 765
    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" );
766
}
767 768 769 770 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

/*****************************************************************************
 * 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 );
871 872 873 874 875 876 877 878

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

879 880 881 882 883 884 885 886 887 888 889 890
    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.
 */
891
static int DpbDisplayPicture( decoder_t *p_dec, picture_t *p_picture )
892 893
{
    picture_dpb_t *p = DpbFindPicture( p_dec, p_picture );
894 895 896 897 898 899 900 901

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

902 903 904
    assert( p && !p->b_displayed && p->b_linked );

    p->b_displayed = true;
905
    return VLC_SUCCESS;
906 907 908
}