mpegvideo.c 20.5 KB
Newer Older
1
/*****************************************************************************
2
 * mpegvideo.c: parse and packetize an MPEG1/2 video stream
3
 *****************************************************************************
4
 * Copyright (C) 2001-2005 VideoLAN (Centrale Réseaux) and its contributors
5
 * $Id$
6 7 8
 *
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
 *          Eric Petit <titer@videolan.org>
9
 *          Gildas Bazin <gbazin@videolan.org>
10
 *          Jean-Paul Saman <jpsaman #_at_# m2x dot nl>
11 12 13 14 15 16 17 18 19 20 21 22 23
 *
 * 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.
 *
 * 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
Antoine Cellerier's avatar
Antoine Cellerier committed
24
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25 26
 *****************************************************************************/

27 28 29 30 31 32 33 34 35 36 37 38 39 40
/*****************************************************************************
 * Problem with this implementation:
 *
 * Although we should time-stamp each picture with a PTS, this isn't possible
 * with the current implementation.
 * The problem comes from the fact that for non-low-delay streams we can't
 * calculate the PTS of pictures used as backward reference. Even the temporal
 * reference number doesn't help here because all the pictures don't
 * necessarily have the same duration (eg. 3:2 pulldown).
 *
 * However this doesn't really matter as far as the MPEG muxers are concerned
 * because they allow having empty PTS fields. --gibalou
 *****************************************************************************/

41 42 43
/*****************************************************************************
 * Preamble
 *****************************************************************************/
44 45
#include <stdlib.h>                                      /* malloc(), free() */

46 47 48 49
#include <vlc/vlc.h>
#include <vlc/decoder.h>
#include <vlc/input.h>

50 51
#include "vlc_block_helper.h"

52 53 54 55 56
#define SYNC_INTRAFRAME_TEXT N_("Sync on intraframe")
#define SYNC_INTRAFRAME_LONGTEXT N_("Normally the packetizer would " \
    "sync on the next full frame. This flags instructs the packetizer " \
    "to sync on the first intraframe found.")

57 58 59
/*****************************************************************************
 * Module descriptor
 *****************************************************************************/
60 61
static int  Open ( vlc_object_t * );
static void Close( vlc_object_t * );
62 63

vlc_module_begin();
64 65
    set_category( CAT_SOUT );
    set_subcategory( SUBCAT_SOUT_PACKETIZER );
66
    set_description( _("MPEG-I/II video packetizer") );
67
    set_capability( "packetizer", 50 );
68
    set_callbacks( Open, Close );
69

70
    add_bool( "packetizer-mpegvideo-sync-iframe", 0, NULL, SYNC_INTRAFRAME_TEXT,
71
              SYNC_INTRAFRAME_LONGTEXT, VLC_TRUE );
72 73 74
vlc_module_end();

/*****************************************************************************
75
 * Local prototypes
76
 *****************************************************************************/
77
static block_t *Packetize( decoder_t *, block_t ** );
78
static block_t *ParseMPEGBlock( decoder_t *, block_t * );
79

80 81
struct decoder_sys_t
{
82 83 84 85 86 87 88 89
    /*
     * Input properties
     */
    block_bytestream_t bytestream;
    int i_state;
    int i_offset;
    uint8_t p_startcode[3];

90
    /* Sequence header and extension */
91 92 93
    block_t *p_seq;
    block_t *p_ext;

94
    /* Current frame being built */
95
    block_t    *p_frame;
96 97
    block_t    **pp_last;

98 99 100 101
    vlc_bool_t b_frame_slice;
    mtime_t i_pts;
    mtime_t i_dts;

102
    /* Sequence properties */
103 104 105 106
    int         i_frame_rate;
    int         i_frame_rate_base;
    vlc_bool_t  b_seq_progressive;
    vlc_bool_t  b_low_delay;
107
    int         i_aspect_ratio_info;
108
    vlc_bool_t  b_inited;
109

110
    /* Picture properties */
111 112 113 114 115 116 117 118 119 120
    int i_temporal_ref;
    int i_picture_type;
    int i_picture_structure;
    int i_top_field_first;
    int i_repeat_first_field;
    int i_progressive_frame;

    mtime_t i_interpolated_dts;
    mtime_t i_old_duration;
    mtime_t i_last_ref_pts;
121

122
    /* Number of pictures since last sequence header */
123
    int i_seq_old;
124 125 126 127
    
    /* Sync behaviour */
    vlc_bool_t  b_sync_on_intra_frame;
    vlc_bool_t  b_discontinuity;
128 129 130 131 132
};

enum {
    STATE_NOSYNC,
    STATE_NEXT_SYNC
133
};
134 135

/*****************************************************************************
136
 * Open:
137
 *****************************************************************************/
138
static int Open( vlc_object_t *p_this )
139
{
140 141
    decoder_t *p_dec = (decoder_t*)p_this;
    decoder_sys_t *p_sys;
142

143 144 145
    if( p_dec->fmt_in.i_codec != VLC_FOURCC( 'm', 'p', 'g', '1' ) &&
        p_dec->fmt_in.i_codec != VLC_FOURCC( 'm', 'p', 'g', '2' ) &&
        p_dec->fmt_in.i_codec != VLC_FOURCC( 'm', 'p', 'g', 'v' ) )
146
    {
147
        return VLC_EGENERIC;
148 149
    }

150
    es_format_Init( &p_dec->fmt_out, VIDEO_ES, VLC_FOURCC('m','p','g','v') );
151
    p_dec->pf_packetize = Packetize;
152

153
    p_dec->p_sys = p_sys = malloc( sizeof( decoder_sys_t ) );
154

155 156 157 158 159 160 161 162
    /* Misc init */
    p_sys->i_state = STATE_NOSYNC;
    p_sys->bytestream = block_BytestreamInit( p_dec );
    p_sys->p_startcode[0] = 0;
    p_sys->p_startcode[1] = 0;
    p_sys->p_startcode[2] = 1;
    p_sys->i_offset = 0;

163 164 165
    p_sys->p_seq = NULL;
    p_sys->p_ext = NULL;
    p_sys->p_frame = NULL;
166
    p_sys->pp_last = &p_sys->p_frame;
167
    p_sys->b_frame_slice = VLC_FALSE;
168

169
    p_sys->i_dts = p_sys->i_pts = 0;
170

171 172 173 174 175
    p_sys->i_frame_rate = 1;
    p_sys->i_frame_rate_base = 1;
    p_sys->b_seq_progressive = VLC_TRUE;
    p_sys->b_low_delay = VLC_TRUE;
    p_sys->i_seq_old = 0;
176

177 178 179 180 181 182
    p_sys->i_temporal_ref = 0;
    p_sys->i_picture_type = 0;
    p_sys->i_picture_structure = 0x03; /* frame */
    p_sys->i_top_field_first = 0;
    p_sys->i_repeat_first_field = 0;
    p_sys->i_progressive_frame = 0;
183
    p_sys->b_inited = 0;
184

185 186 187
    p_sys->i_interpolated_dts = 0;
    p_sys->i_old_duration = 0;
    p_sys->i_last_ref_pts = 0;
188

189 190 191 192 193
    p_sys->b_discontinuity = VLC_FALSE;
    p_sys->b_sync_on_intra_frame = var_CreateGetBool( p_dec, "packetizer-mpegvideo-sync-iframe" );
    if( p_sys->b_sync_on_intra_frame )
        msg_Dbg( p_dec, "syncing happens on intraframe now." );
        
194
    return VLC_SUCCESS;
195 196 197
}

/*****************************************************************************
198
 * Close:
199
 *****************************************************************************/
200
static void Close( vlc_object_t *p_this )
201
{
202 203
    decoder_t     *p_dec = (decoder_t*)p_this;
    decoder_sys_t *p_sys = p_dec->p_sys;
204

205 206
    block_BytestreamRelease( &p_sys->bytestream );

207
    if( p_sys->p_seq )
208
    {
209
        block_Release( p_sys->p_seq );
210
    }
211
    if( p_sys->p_ext )
212
    {
213 214 215 216
        block_Release( p_sys->p_ext );
    }
    if( p_sys->p_frame )
    {
217
        block_ChainRelease( p_sys->p_frame );
218
    }
219 220
    
    var_Destroy( p_dec, "packetizer-mpegvideo-sync-iframe" );
221

222
    free( p_sys );
223 224 225
}

/*****************************************************************************
226
 * Packetize:
227
 *****************************************************************************/
228
static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
229
{
230
    decoder_sys_t *p_sys = p_dec->p_sys;
231
    block_t       *p_pic;
232

233 234 235 236
    if( pp_block == NULL || *pp_block == NULL )
    {
        return NULL;
    }
237

238
    if( (*pp_block)->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
239
    {
240
        p_sys->i_state = STATE_NOSYNC;
241 242 243
        p_sys->b_discontinuity = VLC_TRUE;
        if( p_sys->p_frame )
            block_ChainRelease( p_sys->p_frame );        
244
        p_sys->p_frame = NULL;
245
        p_sys->pp_last = &p_sys->p_frame;
246
        p_sys->b_frame_slice = VLC_FALSE;
247 248
        block_Release( *pp_block );
        return NULL;
249
    }
250

251
    block_BytestreamPush( &p_sys->bytestream, *pp_block );
252

253 254 255
    while( 1 )
    {
        switch( p_sys->i_state )
256
        {
257

258 259 260 261 262 263
        case STATE_NOSYNC:
            if( block_FindStartcodeFromOffset( &p_sys->bytestream,
                    &p_sys->i_offset, p_sys->p_startcode, 3 ) == VLC_SUCCESS )
            {
                p_sys->i_state = STATE_NEXT_SYNC;
            }
264

265 266 267 268 269 270
            if( p_sys->i_offset )
            {
                block_SkipBytes( &p_sys->bytestream, p_sys->i_offset );
                p_sys->i_offset = 0;
                block_BytestreamFlush( &p_sys->bytestream );
            }
271

272 273 274 275 276
            if( p_sys->i_state != STATE_NEXT_SYNC )
            {
                /* Need more data */
                return NULL;
            }
277

278 279 280 281 282
            p_sys->i_offset = 1; /* To find next startcode */

        case STATE_NEXT_SYNC:
            /* TODO: If p_block == NULL, flush the buffer without checking the
             * next sync word */
283

284 285 286
            /* Find the next startcode */
            if( block_FindStartcodeFromOffset( &p_sys->bytestream,
                    &p_sys->i_offset, p_sys->p_startcode, 3 ) != VLC_SUCCESS )
287
            {
288
                /* Need more data */
289
                return NULL;
290 291
            }

292 293
            /* Get the new fragment and set the pts/dts */
            p_pic = block_New( p_dec, p_sys->i_offset );
294
            block_BytestreamFlush( &p_sys->bytestream );
295 296
            p_pic->i_pts = p_sys->bytestream.p_block->i_pts;
            p_pic->i_dts = p_sys->bytestream.p_block->i_dts;
297

298 299 300 301 302
            block_GetBytes( &p_sys->bytestream, p_pic->p_buffer,
                            p_pic->i_buffer );

            /* don't reuse the same timestamps several times */
            if( p_pic->i_buffer >= 4 && p_pic->p_buffer[3] == 0x00 )
303
            {
304 305 306
                /* We have a picture start code */
                p_sys->bytestream.p_block->i_pts = 0;
                p_sys->bytestream.p_block->i_dts = 0;
307
            }
308

309
            p_sys->i_offset = 0;
310

311 312 313 314 315 316
            /* Get picture if any */
            if( !( p_pic = ParseMPEGBlock( p_dec, p_pic ) ) )
            {
                p_sys->i_state = STATE_NOSYNC;
                break;
            }
317

318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335
            /* If a discontinuity has been encountered, then wait till
             * the next Intra frame before continuing with packetizing */
            if( p_sys->b_discontinuity &&
                p_sys->b_sync_on_intra_frame )
            {
                if( p_pic->i_flags & BLOCK_FLAG_TYPE_I )
                {
                    msg_Dbg( p_dec, "synced on Intra frame" );
                    p_sys->b_discontinuity = VLC_FALSE;
                    p_pic->i_flags |= BLOCK_FLAG_DISCONTINUITY;
                }
                else
                {
                    p_sys->i_state = STATE_NOSYNC;
                    break;
                }
            }
            
336 337 338 339 340 341 342 343 344
            /* We've just started the stream, wait for the first PTS.
             * We discard here so we can still get the sequence header. */
            if( p_sys->i_dts <= 0 && p_sys->i_pts <= 0 &&
                p_sys->i_interpolated_dts <= 0 )
            {
                msg_Dbg( p_dec, "need a starting pts/dts" );
                p_sys->i_state = STATE_NOSYNC;
                block_Release( p_pic );
                break;
345 346
            }

347 348 349 350
            /* When starting the stream we can have the first frame with
             * a null DTS (i_interpolated_pts is initialized to 0) */
            if( !p_pic->i_dts ) p_pic->i_dts = p_pic->i_pts;

351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380
            /* So p_block doesn't get re-added several times */
            *pp_block = block_BytestreamPop( &p_sys->bytestream );

            p_sys->i_state = STATE_NOSYNC;

            return p_pic;
        }
    }
}

/*****************************************************************************
 * ParseMPEGBlock: Re-assemble fragments into a block containing a picture
 *****************************************************************************/
static block_t *ParseMPEGBlock( decoder_t *p_dec, block_t *p_frag )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    block_t *p_pic = NULL;

    /*
     * Check if previous picture is finished
     */
    if( ( p_sys->b_frame_slice &&
          (p_frag->p_buffer[3] == 0x00 || p_frag->p_buffer[3] > 0xaf) ) &&
          p_sys->p_seq == NULL )
    {
        /* We have a picture but without a sequence header we can't
         * do anything */
        msg_Dbg( p_dec, "waiting for sequence start" );
        if( p_sys->p_frame ) block_ChainRelease( p_sys->p_frame );
        p_sys->p_frame = NULL;
381
        p_sys->pp_last = &p_sys->p_frame;
382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403
        p_sys->b_frame_slice = VLC_FALSE;

    }
    else if( p_sys->b_frame_slice &&
             (p_frag->p_buffer[3] == 0x00 || p_frag->p_buffer[3] > 0xaf) )
    {
        mtime_t i_duration;

        p_pic = block_ChainGather( p_sys->p_frame );

        i_duration = (mtime_t)( 1000000 * p_sys->i_frame_rate_base /
                                p_sys->i_frame_rate );

        if( !p_sys->b_seq_progressive && p_sys->i_picture_structure != 0x03 )
        {
            i_duration /= 2;
        }

        if( p_sys->b_seq_progressive )
        {
            if( p_sys->i_top_field_first == 0 &&
                p_sys->i_repeat_first_field == 1 )
404
            {
405
                i_duration *= 2;
406
            }
407 408
            else if( p_sys->i_top_field_first == 1 &&
                     p_sys->i_repeat_first_field == 1 )
409
            {
410 411 412 413 414 415 416 417
                i_duration *= 3;
            }
        }
        else
        {
            if( p_sys->i_picture_structure == 0x03 )
            {
                if( p_sys->i_progressive_frame && p_sys->i_repeat_first_field )
418
                {
419
                    i_duration += i_duration / 2;
420
                }
421 422
            }
        }
423

424 425 426 427 428 429 430 431 432 433 434 435 436
        if( p_sys->b_low_delay || p_sys->i_picture_type == 0x03 )
        {
            /* Trivial case (DTS == PTS) */
            /* Correct interpolated dts when we receive a new pts/dts */
            if( p_sys->i_pts > 0 ) p_sys->i_interpolated_dts = p_sys->i_pts;
            if( p_sys->i_dts > 0 ) p_sys->i_interpolated_dts = p_sys->i_dts;
        }
        else
        {
            /* Correct interpolated dts when we receive a new pts/dts */
            if( p_sys->i_last_ref_pts > 0 )
                p_sys->i_interpolated_dts = p_sys->i_last_ref_pts;
            if( p_sys->i_dts > 0 ) p_sys->i_interpolated_dts = p_sys->i_dts;
437

438 439
            p_sys->i_last_ref_pts = p_sys->i_pts;
        }
440

441
        p_pic->i_dts = p_sys->i_interpolated_dts;
442

443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467
        /* Set PTS only if we have a B frame or if it comes from the stream */
        if( p_sys->i_pts > 0 )
        {
            p_pic->i_pts = p_sys->i_pts;
        }
        else if( p_sys->i_picture_type == 0x03 )
        {
            p_pic->i_pts = p_pic->i_dts;
        }
        else
        {
            p_pic->i_pts = 0;
        }

        if( p_sys->b_low_delay || p_sys->i_picture_type == 0x03 )
        {
            /* Trivial case (DTS == PTS) */
            p_sys->i_interpolated_dts += i_duration;
        }
        else
        {
            p_sys->i_interpolated_dts += p_sys->i_old_duration;
            p_sys->i_old_duration = i_duration;
        }

468 469 470 471 472 473 474 475 476 477 478 479 480
        switch ( p_sys->i_picture_type )
        {
        case 0x01:
            p_pic->i_flags |= BLOCK_FLAG_TYPE_I;
            break;
        case 0x02:
            p_pic->i_flags |= BLOCK_FLAG_TYPE_P;
            break;
        case 0x03:
            p_pic->i_flags |= BLOCK_FLAG_TYPE_B;
            break;
        }

481
        p_pic->i_length = p_sys->i_interpolated_dts - p_pic->i_dts;
482

483
#if 0
484 485
        msg_Dbg( p_dec, "pic: type=%d dts="I64Fd" pts-dts="I64Fd,
        p_sys->i_picture_type, p_pic->i_dts, p_pic->i_pts - p_pic->i_dts);
486
#endif
487 488 489

        /* Reset context */
        p_sys->p_frame = NULL;
490
        p_sys->pp_last = &p_sys->p_frame;
491 492 493 494 495 496 497 498 499 500 501 502 503
        p_sys->b_frame_slice = VLC_FALSE;
    }

    /*
     * Check info of current fragment
     */
    if( p_frag->p_buffer[3] == 0xb8 )
    {
        /* Group start code */
        if( p_sys->p_seq &&
            p_sys->i_seq_old > p_sys->i_frame_rate/p_sys->i_frame_rate_base )
        {
            /* Usefull for mpeg1: repeat sequence header every second */
504
            block_ChainLastAppend( &p_sys->pp_last, block_Duplicate( p_sys->p_seq ) );
505
            if( p_sys->p_ext )
506
            {
507
                block_ChainLastAppend( &p_sys->pp_last, block_Duplicate( p_sys->p_ext ) );
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 544 545 546

            p_sys->i_seq_old = 0;
        }
    }
    else if( p_frag->p_buffer[3] == 0xb3 && p_frag->i_buffer >= 8 )
    {
        /* Sequence header code */
        static const int code_to_frame_rate[16][2] =
        {
            { 1, 1 },  /* invalid */
            { 24000, 1001 }, { 24, 1 }, { 25, 1 },       { 30000, 1001 },
            { 30, 1 },       { 50, 1 }, { 60000, 1001 }, { 60, 1 },
            /* Unofficial 15fps from Xing*/
            { 15, 1001 },
            /* Unofficial economy rates from libmpeg3 */
            { 5, 1001 }, { 10, 1001 }, { 12, 1001 }, { 15, 1001 },
            { 1, 1 },  { 1, 1 }  /* invalid */
        };

        if( p_sys->p_seq ) block_Release( p_sys->p_seq );
        if( p_sys->p_ext ) block_Release( p_sys->p_ext );

        p_sys->p_seq = block_Duplicate( p_frag );
        p_sys->i_seq_old = 0;
        p_sys->p_ext = NULL;

        p_dec->fmt_out.video.i_width =
            ( p_frag->p_buffer[4] << 4)|(p_frag->p_buffer[5] >> 4 );
        p_dec->fmt_out.video.i_height =
            ( (p_frag->p_buffer[5]&0x0f) << 8 )|p_frag->p_buffer[6];
        p_sys->i_aspect_ratio_info = p_frag->p_buffer[7] >> 4;

        /* TODO: MPEG1 aspect ratio */

        p_sys->i_frame_rate = code_to_frame_rate[p_frag->p_buffer[7]&0x0f][0];
        p_sys->i_frame_rate_base =
            code_to_frame_rate[p_frag->p_buffer[7]&0x0f][1];

547 548 549
        p_dec->fmt_out.video.i_frame_rate = p_sys->i_frame_rate;
        p_dec->fmt_out.video.i_frame_rate_base = p_sys->i_frame_rate_base;

550 551 552
        p_sys->b_seq_progressive = VLC_TRUE;
        p_sys->b_low_delay = VLC_TRUE;

553 554 555
        if ( !p_sys->b_inited )
        {
            msg_Dbg( p_dec, "Size %dx%d fps=%.3f",
556 557
                 p_dec->fmt_out.video.i_width, p_dec->fmt_out.video.i_height,
                 p_sys->i_frame_rate / (float)p_sys->i_frame_rate_base );
558 559
            p_sys->b_inited = 1;
        }
560 561 562 563 564 565 566 567
    }
    else if( p_frag->p_buffer[3] == 0xb5 )
    {
        int i_type = p_frag->p_buffer[4] >> 4;

        /* Extention start code */
        if( i_type == 0x01 )
        {
568
#if 0
569
            static const int mpeg2_aspect[16][2] =
570
            {
571 572 573 574
                {0,1}, {1,1}, {4,3}, {16,9}, {221,100},
                {0,1}, {0,1}, {0,1}, {0,1}, {0,1}, {0,1}, {0,1}, {0,1}, {0,1},
                {0,1}, {0,1}
            };
575
#endif
576

577 578 579 580 581
            /* sequence extention */
            if( p_sys->p_ext) block_Release( p_sys->p_ext );
            p_sys->p_ext = block_Duplicate( p_frag );

            if( p_frag->i_buffer >= 10 )
582
            {
583 584 585 586
                p_sys->b_seq_progressive =
                    p_frag->p_buffer[5]&0x08 ? VLC_TRUE : VLC_FALSE;
                p_sys->b_low_delay =
                    p_frag->p_buffer[9]&0x80 ? VLC_TRUE : VLC_FALSE;
587
            }
588

589 590 591 592 593 594 595
            /* Do not set aspect ratio : in case we're transcoding,
             * transcode will take our fmt_out as a fmt_in to libmpeg2.
             * libmpeg2.c will then believe that the user has requested
             * a specific aspect ratio, which she hasn't. Thus in case
             * of aspect ratio change, we're screwed. --Meuuh
             */
#if 0
596 597 598 599
            p_dec->fmt_out.video.i_aspect =
                mpeg2_aspect[p_sys->i_aspect_ratio_info][0] *
                VOUT_ASPECT_FACTOR /
                mpeg2_aspect[p_sys->i_aspect_ratio_info][1];
600
#endif
601 602 603 604 605 606 607 608 609

        }
        else if( i_type == 0x08 )
        {
            /* picture extention */
            p_sys->i_picture_structure = p_frag->p_buffer[6]&0x03;
            p_sys->i_top_field_first   = p_frag->p_buffer[7] >> 7;
            p_sys->i_repeat_first_field= (p_frag->p_buffer[7]>>1)&0x01;
            p_sys->i_progressive_frame = p_frag->p_buffer[8] >> 7;
610
        }
611
    }
612
    else if( p_frag->p_buffer[3] == 0x00 )
613
    {
614 615 616 617
        /* Picture start code */
        p_sys->i_seq_old++;

        if( p_frag->i_buffer >= 6 )
618
        {
619 620 621
            p_sys->i_temporal_ref =
                ( p_frag->p_buffer[4] << 2 )|(p_frag->p_buffer[5] >> 6);
            p_sys->i_picture_type = ( p_frag->p_buffer[5] >> 3 ) & 0x03;
622 623
        }

624 625 626 627 628 629 630 631
        p_sys->i_dts = p_frag->i_dts;
        p_sys->i_pts = p_frag->i_pts;
    }
    else if( p_frag->p_buffer[3] >= 0x01 && p_frag->p_buffer[3] <= 0xaf )
    {
        /* Slice start code */
        p_sys->b_frame_slice = VLC_TRUE;
    }
632

633
    /* Append the block */
634
    block_ChainLastAppend( &p_sys->pp_last, p_frag );
635

636 637
    return p_pic;
}