Changeset a1bf965dd5248902f24b0d0ee5279b5f758db02d

Show
Ignore:
Timestamp:
06/10/06 00:20:11 (2 years ago)
Author:
Gildas Bazin <gbazin@videolan.org>
git-committer:
Gildas Bazin <gbazin@videolan.org> 1149891611 +0000
git-parent:

[31a2d53b0aa1e4e8f929471e8760043aa65c50e4]

git-author:
Gildas Bazin <gbazin@videolan.org> 1149891611 +0000
Message:

* modules/packetizer/mpeg4video.c: rewrite using the block helper facility. Fixes a few issues with the previous packetizer and is simpler.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • modules/packetizer/mpeg4video.c

    rbf706ca ra1bf965  
    22 * mpeg4video.c: mpeg 4 video packetizer 
    33 ***************************************************************************** 
    4  * Copyright (C) 2001, 2002, 2006 the VideoLAN team 
     4 * Copyright (C) 2001-2006 the VideoLAN team 
    55 * $Id$ 
    66 * 
    7  * Authors: Laurent Aimar <fenrir@via.ecp.fr> 
     7 * Authors: Gildas Bazin <gbazin@videolan.org> 
     8 *          Laurent Aimar <fenrir@via.ecp.fr> 
    89 *          Eric Petit <titer@videolan.org> 
    9  *          Gildas Bazin <gbazin@videolan.org> 
    1010 * 
    1111 * This program is free software; you can redistribute it and/or modify 
     
    3535 
    3636#include "vlc_bits.h" 
     37#include "vlc_block_helper.h" 
    3738 
    3839/***************************************************************************** 
     
    5051vlc_module_end(); 
    5152 
    52  
    5353/**************************************************************************** 
    5454 * Local prototypes 
     
    5858struct decoder_sys_t 
    5959{ 
     60    /* 
     61     * Input properties 
     62     */ 
     63    block_bytestream_t bytestream; 
     64    int i_state; 
     65    int i_offset; 
     66    uint8_t p_startcode[3]; 
     67 
    6068    /* 
    6169     * Common properties 
     
    6977    mtime_t i_last_timeincr; 
    7078 
    71     vlc_bool_t  b_vop; 
    72     int         i_buffer; 
    73     int         i_buffer_size; 
    74     uint8_t     *p_buffer; 
    7579    unsigned int i_flags; 
    7680 
     
    8185 
    8286    vlc_bool_t  b_frame; 
     87 
     88    /* Current frame being built */ 
     89    block_t    *p_frame; 
     90    block_t    **pp_last; 
    8391}; 
    8492 
    85 static int m4v_FindStartCode( uint8_t **, uint8_t * ); 
    86 static int m4v_VOLParse( decoder_t *, es_format_t *, uint8_t *, int ); 
     93enum { 
     94    STATE_NOSYNC, 
     95    STATE_NEXT_SYNC 
     96}; 
     97 
     98static block_t *ParseMPEGBlock( decoder_t *, block_t * ); 
     99static int ParseVOL( decoder_t *, es_format_t *, uint8_t *, int ); 
     100static int ParseVOP( decoder_t *, block_t * ); 
    87101static int vlc_log2( unsigned int ); 
    88102 
     
    148162    memset( p_sys, 0, sizeof(decoder_sys_t) ); 
    149163 
     164    /* Misc init */ 
     165    p_sys->i_state = STATE_NOSYNC; 
     166    p_sys->bytestream = block_BytestreamInit( p_dec ); 
     167    p_sys->p_startcode[0] = 0; 
     168    p_sys->p_startcode[1] = 0; 
     169    p_sys->p_startcode[2] = 1; 
     170    p_sys->i_offset = 0; 
     171    p_sys->p_frame = NULL; 
     172    p_sys->pp_last = &p_sys->p_frame; 
     173 
    150174    /* Setup properties */ 
    151175    es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in ); 
     
    161185 
    162186        msg_Dbg( p_dec, "opening with vol size: %d", p_dec->fmt_in.i_extra ); 
    163         m4v_VOLParse( p_dec, &p_dec->fmt_out, 
    164                       p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra ); 
     187        ParseVOL( p_dec, &p_dec->fmt_out, 
     188                  p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra ); 
    165189    } 
    166190    else 
     
    184208    decoder_t *p_dec = (decoder_t*)p_this; 
    185209 
    186     if( p_dec->p_sys->p_buffer ) free( p_dec->p_sys->p_buffer ); 
     210    block_BytestreamRelease( &p_dec->p_sys->bytestream ); 
     211    if( p_dec->p_sys->p_frame ) block_ChainRelease( p_dec->p_sys->p_frame ); 
    187212    free( p_dec->p_sys ); 
    188213} 
     
    194219{ 
    195220    decoder_sys_t *p_sys = p_dec->p_sys; 
    196  
    197     block_t *p_chain_out = NULL; 
    198     block_t *p_block; 
    199     uint8_t *p_vol = NULL; 
    200     uint8_t *p_start; 
    201  
    202     if( !pp_block || !*pp_block ) return NULL; 
    203  
    204     p_block = *pp_block; 
    205  
    206     /* Append data */ 
    207     if( p_sys->i_buffer + p_block->i_buffer > p_sys->i_buffer_size ) 
    208     { 
    209         p_sys->i_buffer_size += p_block->i_buffer + 1024; 
    210         p_sys->p_buffer = realloc( p_sys->p_buffer, p_sys->i_buffer_size ); 
    211     } 
    212     memcpy( &p_sys->p_buffer[p_sys->i_buffer], p_block->p_buffer, 
    213             p_block->i_buffer ); 
    214     p_sys->i_buffer += p_block->i_buffer; 
    215  
    216     if( p_sys->i_buffer > 10*1000000 ) 
    217     { 
    218         msg_Warn( p_dec, "reseting context" ); 
    219         p_sys->i_buffer = 0; 
    220     } 
    221  
    222     /* Search vop */ 
    223     p_start = &p_sys->p_buffer[p_sys->i_buffer - p_block->i_buffer - 4]; 
    224     if( p_start < p_sys->p_buffer ) 
    225     { 
    226         p_start = p_sys->p_buffer; 
    227     } 
    228     for( ;; ) 
    229     { 
    230         if( m4v_FindStartCode( &p_start, &p_sys->p_buffer[p_sys->i_buffer] ) ) 
     221    block_t       *p_pic; 
     222    mtime_t       i_pts, i_dts; 
     223 
     224    if( pp_block == NULL || *pp_block == NULL ) return NULL; 
     225 
     226    if( (*pp_block)->i_flags & BLOCK_FLAG_DISCONTINUITY ) 
     227    { 
     228        p_sys->i_state = STATE_NOSYNC; 
     229        if( p_sys->p_frame ) block_ChainRelease( p_sys->p_frame ); 
     230        p_sys->p_frame = NULL; 
     231        p_sys->pp_last = &p_sys->p_frame; 
     232        block_Release( *pp_block ); 
     233        return NULL; 
     234    } 
     235 
     236    block_BytestreamPush( &p_sys->bytestream, *pp_block ); 
     237 
     238    while( 1 ) 
     239    { 
     240        switch( p_sys->i_state ) 
    231241        { 
    232             block_Release( p_block ); 
    233             *pp_block = NULL; 
    234             return p_chain_out; 
     242 
     243        case STATE_NOSYNC: 
     244            if( block_FindStartcodeFromOffset( &p_sys->bytestream, 
     245                    &p_sys->i_offset, p_sys->p_startcode, 3 ) == VLC_SUCCESS ) 
     246            { 
     247                p_sys->i_state = STATE_NEXT_SYNC; 
     248            } 
     249 
     250            if( p_sys->i_offset ) 
     251            { 
     252                block_SkipBytes( &p_sys->bytestream, p_sys->i_offset ); 
     253                p_sys->i_offset = 0; 
     254                block_BytestreamFlush( &p_sys->bytestream ); 
     255            } 
     256 
     257            if( p_sys->i_state != STATE_NEXT_SYNC ) 
     258            { 
     259                /* Need more data */ 
     260                return NULL; 
     261            } 
     262 
     263            p_sys->i_offset = 1; /* To find next startcode */ 
     264 
     265        case STATE_NEXT_SYNC: 
     266            /* TODO: If p_block == NULL, flush the buffer without checking the 
     267             * next sync word */ 
     268 
     269            /* Find the next startcode */ 
     270            if( block_FindStartcodeFromOffset( &p_sys->bytestream, 
     271                    &p_sys->i_offset, p_sys->p_startcode, 3 ) != VLC_SUCCESS ) 
     272            { 
     273                /* Need more data */ 
     274                return NULL; 
     275            } 
     276 
     277            /* Get the new fragment and set the pts/dts */ 
     278            p_pic = block_New( p_dec, p_sys->i_offset ); 
     279            block_BytestreamFlush( &p_sys->bytestream ); 
     280            p_pic->i_pts = i_pts = p_sys->bytestream.p_block->i_pts; 
     281            p_pic->i_dts = i_dts = p_sys->bytestream.p_block->i_dts; 
     282            p_pic->i_rate = p_sys->bytestream.p_block->i_rate; 
     283 
     284            block_GetBytes( &p_sys->bytestream, p_pic->p_buffer, 
     285                            p_pic->i_buffer ); 
     286 
     287            p_sys->i_offset = 0; 
     288 
     289            /* Get picture if any */ 
     290            if( !( p_pic = ParseMPEGBlock( p_dec, p_pic ) ) ) 
     291            { 
     292                p_sys->i_state = STATE_NOSYNC; 
     293                break; 
     294            } 
     295 
     296            /* don't reuse the same timestamps several times */ 
     297            if( i_pts == p_sys->bytestream.p_block->i_pts && 
     298                i_dts == p_sys->bytestream.p_block->i_dts ) 
     299            { 
     300                p_sys->bytestream.p_block->i_pts = 0; 
     301                p_sys->bytestream.p_block->i_dts = 0; 
     302            } 
     303 
     304            /* We've just started the stream, wait for the first PTS. 
     305             * We discard here so we can still get the sequence header. */ 
     306            if( p_sys->i_interpolated_pts <= 0 && 
     307                p_sys->i_interpolated_dts <= 0 ) 
     308            { 
     309                msg_Dbg( p_dec, "need a starting pts/dts" ); 
     310                p_sys->i_state = STATE_NOSYNC; 
     311                block_Release( p_pic ); 
     312                break; 
     313            } 
     314 
     315            /* When starting the stream we can have the first frame with 
     316             * a null DTS (i_interpolated_pts is initialized to 0) */ 
     317            if( !p_pic->i_dts ) p_pic->i_dts = p_pic->i_pts; 
     318 
     319            /* So p_block doesn't get re-added several times */ 
     320            *pp_block = block_BytestreamPop( &p_sys->bytestream ); 
     321 
     322            p_sys->i_state = STATE_NOSYNC; 
     323 
     324            return p_pic; 
    235325        } 
    236         /* fprintf( stderr, "start code=0x1%2.2x\n", p_start[3] ); */ 
    237  
    238         if( p_vol ) 
     326    } 
     327
     328 
     329/***************************************************************************** 
     330 * ParseMPEGBlock: Re-assemble fragments into a block containing a picture 
     331 *****************************************************************************/ 
     332static block_t *ParseMPEGBlock( decoder_t *p_dec, block_t *p_frag ) 
     333
     334    decoder_sys_t *p_sys = p_dec->p_sys; 
     335    block_t *p_pic = NULL; 
     336 
     337    if( p_frag->p_buffer[3] == 0xB0 || p_frag->p_buffer[3] == 0xB1 ) 
     338    { 
     339        /* Remove VOS start/end code from the original stream */ 
     340        block_Release( p_frag ); 
     341        return NULL; 
     342    } 
     343    if( p_frag->p_buffer[3] >= 0x20 && p_frag->p_buffer[3] <= 0x2f ) 
     344    { 
     345        /* Copy the complete VOL */ 
     346        p_dec->fmt_out.i_extra = p_frag->i_buffer; 
     347        p_dec->fmt_out.p_extra = 
     348            realloc( p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra ); 
     349        memcpy( p_dec->fmt_out.p_extra, p_frag->p_buffer, p_frag->i_buffer ); 
     350        ParseVOL( p_dec, &p_dec->fmt_out, 
     351                  p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra ); 
     352 
     353        /* Remove from the original stream */ 
     354        block_Release( p_frag ); 
     355        return NULL; 
     356    } 
     357    else 
     358    { 
     359        if( !p_dec->fmt_out.i_extra ) 
    239360        { 
    240             if( !p_dec->fmt_out.i_extra ) 
    241             { 
    242                 /* Copy the complete VOL */ 
    243                 p_dec->fmt_out.i_extra = p_start - p_vol; 
    244                 p_dec->fmt_out.p_extra = 
    245                     realloc( p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra ); 
    246                 memcpy( p_dec->fmt_out.p_extra, p_vol, 
    247                         p_dec->fmt_out.i_extra ); 
    248                 m4v_VOLParse( p_dec, &p_dec->fmt_out, 
    249                               p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra ); 
    250             } 
    251  
    252             /* Remove VOL from the original stream */ 
    253             memmove( p_vol, p_start, 
    254                      p_sys->i_buffer - (p_start - p_sys->p_buffer) ); 
    255             p_sys->i_buffer -= p_dec->fmt_out.i_extra; 
    256             p_start = p_vol; 
    257  
    258             p_vol = NULL; 
     361            msg_Warn( p_dec, "waiting for VOL" ); 
     362            block_Release( p_frag ); 
     363            return NULL; 
    259364        } 
    260         if( p_sys->b_vop ) 
    261         { 
    262             /* Output the complete VOP we have */ 
    263             int     i_out = p_start - p_sys->p_buffer; 
    264             block_t *p_out = block_New( p_dec, i_out ); 
    265  
    266             /* extract data */ 
    267             memcpy( p_out->p_buffer, p_sys->p_buffer, i_out ); 
    268             if( i_out < p_sys->i_buffer ) 
    269             { 
    270                 memmove( p_sys->p_buffer, &p_sys->p_buffer[i_out], 
    271                          p_sys->i_buffer - i_out ); 
    272             } 
    273             p_sys->i_buffer -= i_out; 
    274             p_start -= i_out; 
    275  
    276             p_out->i_flags = p_sys->i_flags; 
    277             p_out->i_pts = p_sys->i_interpolated_pts; 
    278             p_out->i_dts = p_sys->i_interpolated_dts; 
    279  
    280             /* FIXME doesn't work when there is multiple VOP in one block */ 
    281             if( p_block->i_dts > p_sys->i_interpolated_dts ) 
    282             { 
    283                 p_out->i_length = p_block->i_dts - p_sys->i_interpolated_dts; 
    284             } 
    285  
    286             if( p_dec->fmt_out.i_extra > 0 ) 
    287             { 
    288                 block_ChainAppend( &p_chain_out, p_out ); 
    289             } 
    290             else 
    291             { 
    292                 msg_Warn( p_dec, "waiting for VOL" ); 
    293                 block_Release( p_out ); 
    294             } 
    295  
    296             p_sys->b_vop = VLC_FALSE; 
    297         } 
    298  
    299         if( p_start[3] >= 0x20 && p_start[3] <= 0x2f ) 
    300         { 
    301             /* Start of the VOL */ 
    302             p_vol = p_start; 
    303         } 
    304         else if( p_start[3] == 0xb3 ) 
    305         { 
    306             /* GOP header */ 
    307         } 
    308         else if( p_start[3] == 0xb6 ) 
    309         { 
    310             /* Parse the VOP */ 
    311             bs_t s; 
    312             int i_modulo_time_base = 0; 
    313             int i_time_increment_bits; 
    314             int64_t i_time_increment, i_time_ref; 
    315  
    316             /* FIXME: we don't actually check we received enough data to read 
    317              * the VOP time increment. */ 
    318             bs_init( &s, &p_start[4], 
    319                      p_sys->i_buffer - (p_start - p_sys->p_buffer) - 4 ); 
    320  
    321             switch( bs_read( &s, 2 ) ) 
    322             { 
    323                 case 0: 
    324                     p_sys->i_flags = BLOCK_FLAG_TYPE_I; 
    325                     break; 
    326                 case 1: 
    327                     p_sys->i_flags = BLOCK_FLAG_TYPE_P; 
    328                     break; 
    329                 case 2: 
    330                     p_sys->i_flags = BLOCK_FLAG_TYPE_B; 
    331                     p_sys->b_frame = VLC_TRUE; 
    332                     break; 
    333                 case 3: /* gni ? */ 
    334                     p_sys->i_flags = BLOCK_FLAG_TYPE_PB; 
    335                     break; 
    336             } 
    337  
    338             while( bs_read( &s, 1 ) ) i_modulo_time_base++; 
    339             if( !bs_read1( &s ) ) continue; /* Marker */ 
    340  
    341             /* VOP time increment */ 
    342             i_time_increment_bits = vlc_log2(p_dec->p_sys->i_fps_num - 1) + 1; 
    343             if( i_time_increment_bits < 1 ) i_time_increment_bits = 1; 
    344             i_time_increment = bs_read( &s, i_time_increment_bits ); 
    345  
    346             /* Interpolate PTS/DTS */ 
    347             if( !(p_sys->i_flags & BLOCK_FLAG_TYPE_B) ) 
    348             { 
    349                 p_sys->i_last_time_ref = p_sys->i_time_ref; 
    350                 p_sys->i_time_ref += 
    351                     (i_modulo_time_base * p_dec->p_sys->i_fps_num); 
    352                 i_time_ref = p_sys->i_time_ref; 
    353             } 
    354             else 
    355             { 
    356                 i_time_ref = p_sys->i_last_time_ref + 
    357                     (i_modulo_time_base * p_dec->p_sys->i_fps_num); 
    358             } 
    359  
    360             if( p_dec->p_sys->i_fps_num < 5 && /* Work-around buggy streams */ 
    361                 p_dec->fmt_in.video.i_frame_rate > 0 && 
    362                 p_dec->fmt_in.video.i_frame_rate_base > 0 ) 
    363             { 
    364                 p_sys->i_interpolated_pts += I64C(1000000) * 
    365                     p_dec->fmt_in.video.i_frame_rate_base * 
    366                     p_block->i_rate / INPUT_RATE_DEFAULT / 
    367                     p_dec->fmt_in.video.i_frame_rate; 
    368             } 
    369             else if( p_dec->p_sys->i_fps_num ) 
    370                 p_sys->i_interpolated_pts += 
    371                     ( I64C(1000000) * (i_time_ref + i_time_increment - 
    372                        p_sys->i_last_time - p_sys->i_last_timeincr) * 
    373                       p_block->i_rate / INPUT_RATE_DEFAULT / 
    374                       p_dec->p_sys->i_fps_num ); 
    375  
    376             p_sys->i_last_time = i_time_ref; 
    377             p_sys->i_last_timeincr = i_time_increment; 
    378  
    379             /* Correct interpolated dts when we receive a new pts/dts */ 
    380             if( p_block->i_pts > 0 ) 
    381                 p_sys->i_interpolated_pts = p_block->i_pts; 
    382             if( p_block->i_dts > 0 ) 
    383                 p_sys->i_interpolated_dts = p_block->i_dts; 
    384  
    385             if( (p_sys->i_flags & BLOCK_FLAG_TYPE_B) || !p_sys->b_frame ) 
    386             { 
    387                 /* Trivial case (DTS == PTS) */ 
    388  
    389                 p_sys->i_interpolated_dts = p_sys->i_interpolated_pts; 
    390  
    391                 if( p_block->i_pts > 0 ) 
    392                     p_sys->i_interpolated_dts = p_block->i_pts; 
    393                 if( p_block->i_dts > 0 ) 
    394                     p_sys->i_interpolated_dts = p_block->i_dts; 
    395  
    396                 p_sys->i_interpolated_pts = p_sys->i_interpolated_dts; 
    397             } 
    398             else 
    399             { 
    400                 if( p_sys->i_last_ref_pts > 0 ) 
    401                     p_sys->i_interpolated_dts = p_sys->i_last_ref_pts; 
    402  
    403                 p_sys->i_last_ref_pts = p_sys->i_interpolated_pts; 
    404             } 
    405  
    406             p_sys->b_vop = VLC_TRUE; 
    407  
    408             /* Don't re-use the same PTS/DTS twice */ 
    409             p_block->i_pts = p_block->i_dts = 0; 
    410         } 
    411  
    412         p_start += 4; /* Next */ 
    413     } 
     365 
     366        /* Append the block */ 
     367        block_ChainLastAppend( &p_sys->pp_last, p_frag ); 
     368    } 
     369 
     370    if( p_frag->p_buffer[3] == 0xb6 && 
     371        ParseVOP( p_dec, p_frag ) == VLC_SUCCESS ) 
     372    { 
     373        /* We are dealing with a VOP */ 
     374        p_pic = block_ChainGather( p_sys->p_frame ); 
     375        p_pic->i_pts = p_sys->i_interpolated_pts; 
     376        p_pic->i_dts = p_sys->i_interpolated_dts; 
     377 
     378        /* Reset context */ 
     379        p_sys->p_frame = NULL; 
     380        p_sys->pp_last = &p_sys->p_frame; 
     381    } 
     382 
     383    return p_pic; 
    414384} 
    415385 
    416 /**************************************************************************** 
    417  * m4v_FindStartCode 
    418  ****************************************************************************/ 
    419 static int m4v_FindStartCode( uint8_t **pp_start, uint8_t *p_end ) 
    420 
    421     uint8_t *p = *pp_start; 
    422  
    423     /* We wait for 4+1 bytes */ 
    424     for( p = *pp_start; p < p_end - 5; p++ ) 
    425     { 
    426         if( p[0] == 0 && p[1] == 0 && p[2] == 1 ) 
    427         { 
    428             *pp_start = p; 
    429             return VLC_SUCCESS; 
    430         } 
    431     } 
    432  
    433     *pp_start = p_end; 
    434     return VLC_EGENERIC; 
    435 
    436  
    437  
    438 /* look at ffmpeg av_log2 ;) */ 
    439 static int vlc_log2( unsigned int v ) 
    440 
    441     int n = 0; 
    442     static const int vlc_log2_table[16] = 
    443     { 
    444         0,0,1,1,2,2,2,2, 3,3,3,3,3,3,3,3 
    445     }; 
    446  
    447     if( v&0xffff0000 ) 
    448     { 
    449         v >>= 16; 
    450         n += 16; 
    451     } 
    452     if( v&0xff00 ) 
    453     { 
    454         v >>= 8; 
    455         n += 8; 
    456     } 
    457     if( v&0xf0 ) 
    458     { 
    459         v >>= 4; 
    460         n += 4; 
    461     } 
    462     n += vlc_log2_table[v]; 
    463  
    464     return n; 
    465 
    466  
    467 /* m4v_VOLParse: 
     386/* ParseVOL: 
    468387 *  TODO: 
    469388 *      - support aspect ratio 
    470389 */ 
    471 static int m4v_VOLParse( decoder_t *p_dec, es_format_t *fmt, 
    472                          uint8_t *p_vol, int i_vol ) 
    473 
     390static int ParseVOL( decoder_t *p_dec, es_format_t *fmt, 
     391                     uint8_t *p_vol, int i_vol ) 
     392
     393    decoder_sys_t *p_sys = p_dec->p_sys; 
     394    int i_vo_type, i_vo_ver_id, i_ar, i_shape; 
    474395    bs_t s; 
    475     int i_vo_type; 
    476     int i_vo_ver_id; 
    477     int i_ar; 
    478     int i_shape; 
    479396 
    480397    for( ;; ) 
    481398    { 
    482         if( p_vol[0] == 0x00 && p_vol[1] == 0x00 && 
    483             p_vol[2] == 0x01 && 
    484             p_vol[3] >= 0x20 && p_vol[3] <= 0x2f ) 
    485         { 
    486             break; 
    487         } 
    488         p_vol++; 
    489         i_vol--; 
    490         if( i_vol <= 4 ) 
    491         { 
    492             return VLC_EGENERIC; 
    493         } 
    494     } 
    495  
    496     /* parse the vol */ 
     399        if( p_vol[0] == 0x00 && p_vol[1] == 0x00 && p_vol[2] == 0x01 && 
     400            p_vol[3] >= 0x20 && p_vol[3] <= 0x2f ) break; 
     401 
     402        p_vol++; i_vol--; 
     403        if( i_vol <= 4 ) return VLC_EGENERIC; 
     404    } 
     405 
    497406    bs_init( &s, &p_vol[4], i_vol - 4 ); 
    498407 
     
    545454    if( !bs_read1( &s ) ) return VLC_EGENERIC; /* Marker */ 
    546455 
    547     p_dec->p_sys->i_fps_num = bs_read( &s, 16 ); /* Time increment resolution*/ 
    548     if( !p_dec->p_sys->i_fps_num ) p_dec->p_sys->i_fps_num = 1; 
     456    p_sys->i_fps_num = bs_read( &s, 16 ); /* Time increment resolution*/ 
     457    if( !p_sys->i_fps_num ) p_sys->i_fps_num = 1; 
    549458 
    550459    if( !bs_read1( &s ) ) return VLC_EGENERIC; /* Marker */ 
     
    552461    if( bs_read1( &s ) ) 
    553462    { 
    554         int i_time_increment_bits = 
    555             vlc_log2( p_dec->p_sys->i_fps_num - 1 ) + 1; 
     463        int i_time_increment_bits = vlc_log2( p_sys->i_fps_num - 1 ) + 1; 
    556464 
    557465        if( i_time_increment_bits < 1 ) i_time_increment_bits = 1; 
    558466 
    559         p_dec->p_sys->i_fps_den = bs_read( &s, i_time_increment_bits ); 
     467        p_sys->i_fps_den = bs_read( &s, i_time_increment_bits ); 
    560468    } 
    561469    if( i_shape == 0 ) 
     
    567475        bs_skip( &s, 1 ); 
    568476    } 
     477 
    569478    return VLC_SUCCESS; 
    570479} 
     480 
     481static int ParseVOP( decoder_t *p_dec, block_t *p_vop ) 
     482{ 
     483    decoder_sys_t *p_sys = p_dec->p_sys; 
     484    int64_t i_time_increment, i_time_ref; 
     485    int i_modulo_time_base = 0, i_time_increment_bits; 
     486    bs_t s; 
     487 
     488    bs_init( &s, &p_vop->p_buffer[4], p_vop->i_buffer - 4 ); 
     489 
     490    switch( bs_read( &s, 2 ) ) 
     491    { 
     492    case 0: 
     493        p_sys->i_flags = BLOCK_FLAG_TYPE_I; 
     494        break; 
     495    case 1: 
     496        p_sys->i_flags = BLOCK_FLAG_TYPE_P; 
     497        break; 
     498    case 2: 
     499        p_sys->i_flags = BLOCK_FLAG_TYPE_B; 
     500        p_sys->b_frame = VLC_TRUE; 
     501        break; 
     502    case 3: /* gni ? */ 
     503        p_sys->i_flags = BLOCK_FLAG_TYPE_PB; 
     504        break; 
     505    } 
     506 
     507    while( bs_read( &s, 1 ) ) i_modulo_time_base++; 
     508    if( !bs_read1( &s ) ) return VLC_EGENERIC; /* Marker */ 
     509 
     510    /* VOP time increment */ 
     511    i_time_increment_bits = vlc_log2(p_dec->p_sys->i_fps_num - 1) + 1; 
     512    if( i_time_increment_bits < 1 ) i_time_increment_bits = 1; 
     513    i_time_increment = bs_read( &s, i_time_increment_bits ); 
     514 
     515    /* Interpolate PTS/DTS */ 
     516    if( !(p_sys->i_flags & BLOCK_FLAG_TYPE_B) ) 
     517    { 
     518        p_sys->i_last_time_ref = p_sys->i_time_ref; 
     519        p_sys->i_time_ref += 
     520            (i_modulo_time_base * p_dec->p_sys->i_fps_num); 
     521        i_time_ref = p_sys->i_time_ref; 
     522    } 
     523    else 
     524    { 
     525        i_time_ref = p_sys->i_last_time_ref + 
     526            (i_modulo_time_base * p_dec->p_sys->i_fps_num); 
     527    } 
     528 
     529#if 0 
     530    msg_Err( p_dec, "interp pts/dts (%lli,%lli), pts/dts (%lli,%lli)", 
     531             p_sys->i_interpolated_pts, p_sys->i_interpolated_dts, 
     532             p_vop->i_pts, p_vop->i_dts ); 
     533#endif 
     534 
     535    if( p_dec->p_sys->i_fps_num < 5 && /* Work-around buggy streams */ 
     536        p_dec->fmt_in.video.i_frame_rate > 0 && 
     537        p_dec->fmt_in.video.i_frame_rate_base > 0 ) 
     538    { 
     539        p_sys->i_interpolated_pts += I64C(1000000) * 
     540        p_dec->fmt_in.video.i_frame_rate_base * 
     541        p_vop->i_rate / INPUT_RATE_DEFAULT / 
     542        p_dec->fmt_in.video.i_frame_rate; 
     543    } 
     544    else if( p_dec->p_sys->i_fps_num ) 
     545        p_sys->i_interpolated_pts += 
     546            ( I64C(1000000) * (i_time_ref + i_time_increment - 
     547              p_sys->i_last_time - p_sys->i_last_timeincr) * 
     548              p_vop->i_rate / INPUT_RATE_DEFAULT / 
     549              p_dec->p_sys->i_fps_num ); 
     550 
     551    p_sys->i_last_time = i_time_ref; 
     552    p_sys->i_last_timeincr = i_time_increment; 
     553 
     554    /* Correct interpolated dts when we receive a new pts/dts */ 
     555    if( p_vop->i_pts > 0 ) 
     556        p_sys->i_interpolated_pts = p_vop->i_pts; 
     557    if( p_vop->i_dts > 0 ) 
     558        p_sys->i_interpolated_dts = p_vop->i_dts; 
     559 
     560    if( (p_sys->i_flags & BLOCK_FLAG_TYPE_B) || !p_sys->b_frame ) 
     561    { 
     562        /* Trivial case (DTS == PTS) */ 
     563 
     564        p_sys->i_interpolated_dts = p_sys->i_interpolated_pts; 
     565 
     566        if( p_vop->i_pts > 0 ) 
     567            p_sys->i_interpolated_dts = p_vop->i_pts; 
     568        if( p_vop->i_dts > 0 ) 
     569            p_sys->i_interpolated_dts = p_vop->i_dts; 
     570 
     571        p_sys->i_interpolated_pts = p_sys->i_interpolated_dts; 
     572    } 
     573    else 
     574    { 
     575        if( p_sys->i_last_ref_pts > 0 ) 
     576            p_sys->i_interpolated_dts = p_sys->i_last_ref_pts; 
     577 
     578        p_sys->i_last_ref_pts = p_sys->i_interpolated_pts; 
     579    } 
     580 
     581    return VLC_SUCCESS; 
     582} 
     583 
     584/* look at ffmpeg av_log2 ;) */ 
     585static int vlc_log2( unsigned int v ) 
     586{ 
     587    int n = 0; 
     588    static const int vlc_log2_table[16] = 
     589    { 
     590        0,0,1,1,2,2,2,2, 3,3,3,3,3,3,3,3 
     591    }; 
     592 
     593    if( v&0xffff0000 ) 
     594    { 
     595        v >>= 16; 
     596        n += 16; 
     597    } 
     598    if( v&0xff00 ) 
     599    { 
     600        v >>= 8; 
     601        n += 8; 
     602    } 
     603    if( v&0xf0 ) 
     604    { 
     605        v >>= 4; 
     606        n += 4; 
     607    } 
     608    n += vlc_log2_table[v]; 
     609 
     610    return n; 
     611}