Changeset 355794923679b416110e848bbc875a4a546980f2

Show
Ignore:
Timestamp:
18/11/03 21:15:38 (5 years ago)
Author:
Laurent Aimar <fenrir@videolan.org>
git-committer:
Laurent Aimar <fenrir@videolan.org> 1069186538 +0000
git-parent:

[7d0dc9c466cd72e86332b28c510316318508805b]

git-author:
Laurent Aimar <fenrir@videolan.org> 1069186538 +0000
Message:
  • include/vlc_bits.h: bit stream reader/writer.
  • mpeg4video.c: rework of the mpeg4 video packetizer.
    (not well tested)
Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • Makefile.am

    r1672cb9 r3557949  
    9191    include/video_output.h \ 
    9292    include/vlc_block.h \ 
     93    include/vlc_bits.h \ 
    9394    include/vlc_block_helper.h \ 
    9495    include/vlc_codec.h \ 
  • modules/packetizer/mpeg4video.c

    r5078da2 r3557949  
    33 ***************************************************************************** 
    44 * Copyright (C) 2001, 2002 VideoLAN 
    5  * $Id: mpeg4video.c,v 1.15 2003/11/17 18:48:08 gbazin Exp $ 
     5 * $Id: mpeg4video.c,v 1.16 2003/11/18 20:15:38 fenrir Exp $ 
    66 * 
    77 * Authors: Laurent Aimar <fenrir@via.ecp.fr> 
     
    2727 * Preamble 
    2828 *****************************************************************************/ 
     29#include <stdlib.h>                                      /* malloc(), free() */ 
     30 
    2931#include <vlc/vlc.h> 
    3032#include <vlc/decoder.h> 
    31 #include <vlc/input.h> 
    3233#include <vlc/sout.h> 
    3334 
    34 #include <stdlib.h>                                      /* malloc(), free() */ 
    35 #include <string.h>                                              /* strdup() */ 
    36  
    37 #include "codecs.h" 
     35#include "vlc_bits.h" 
    3836 
    3937/***************************************************************************** 
    40  * decoder_sys_t : decoder descriptor 
     38 * Module descriptor 
    4139 *****************************************************************************/ 
     40static int  Open ( vlc_object_t * ); 
     41static void Close( vlc_object_t * ); 
     42 
     43vlc_module_begin(); 
     44    set_description( _("MPEG4 Video packetizer") ); 
     45    set_capability( "packetizer", 50 ); 
     46    set_callbacks( Open, Close ); 
     47vlc_module_end(); 
     48 
     49 
     50/**************************************************************************** 
     51 * Local prototypes 
     52 ****************************************************************************/ 
     53static block_t *Packetize( decoder_t *, block_t ** ); 
     54 
    4255struct decoder_sys_t 
    4356{ 
     
    4659     */ 
    4760    mtime_t i_pts; 
     61    mtime_t i_dts; 
     62 
     63 
     64    vlc_bool_t  b_vop; 
     65    int         i_buffer; 
     66    int         i_buffer_size; 
     67    uint8_t     *p_buffer; 
    4868}; 
    4969 
    50 /**************************************************************************** 
    51  * Local prototypes 
    52  ****************************************************************************/ 
    53 static int  OpenPacketizer ( vlc_object_t * ); 
    54 static void ClosePacketizer( vlc_object_t * ); 
    55  
    56 static block_t *PacketizeBlock( decoder_t *, block_t ** ); 
    57  
    58 static int m4v_FindVol( decoder_t *p_dec, block_t *p_block ); 
     70static int m4v_FindStartCode( uint8_t **pp_start, uint8_t *p_end ); 
     71static int m4v_VOLParse( es_format_t *fmt, uint8_t *p_vol, int i_vol ); 
    5972 
    6073#define VIDEO_OBJECT_MASK                       0x01f 
     
    7992 
    8093/***************************************************************************** 
    81  * Module descriptor 
     94 * Open: probe the packetizer and return score 
    8295 *****************************************************************************/ 
    83 vlc_module_begin(); 
    84     set_description( _("MPEG4 Video packetizer") ); 
    85     set_capability( "packetizer", 50 ); 
    86     set_callbacks( OpenPacketizer, ClosePacketizer ); 
    87 vlc_module_end(); 
    88  
    89 /***************************************************************************** 
    90  * OpenPacketizer: probe the packetizer and return score 
    91  *****************************************************************************/ 
    92 static int OpenPacketizer( vlc_object_t *p_this ) 
    93 
    94     decoder_t *p_dec = (decoder_t*)p_this; 
     96static int Open( vlc_object_t *p_this ) 
     97
     98    decoder_t     *p_dec = (decoder_t*)p_this; 
    9599    decoder_sys_t *p_sys; 
    96100 
    97     switch( p_dec->p_fifo->i_fourcc ) 
     101    switch( p_dec->fmt_in.i_codec ) 
    98102    { 
    99103        case VLC_FOURCC( 'm', '4', 's', '2'): 
     
    117121 
    118122    /* Allocate the memory needed to store the decoder's structure */ 
    119     if( ( p_dec->p_sys = p_sys = 
    120           (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL ) 
     123    if( ( p_dec->p_sys = p_sys = malloc( sizeof(decoder_sys_t) ) ) == NULL ) 
    121124    { 
    122125        msg_Err( p_dec, "out of memory" ); 
    123126        return VLC_EGENERIC; 
    124127    } 
     128    p_sys->i_pts = 0; 
     129    p_sys->b_vop = VLC_FALSE; 
     130    p_sys->i_buffer = 0; 
     131    p_sys->i_buffer_size = 10000; 
     132    p_sys->p_buffer = malloc( p_sys->i_buffer_size ); 
    125133 
    126134    /* Setup properties */ 
     
    137145 
    138146        msg_Dbg( p_dec, "opening with vol size:%d", p_dec->fmt_in.i_extra ); 
     147        m4v_VOLParse( &p_dec->fmt_out, 
     148                      p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra ); 
    139149    } 
    140150    else 
     
    146156 
    147157    /* Set callback */ 
    148     p_dec->pf_packetize = PacketizeBlock
     158    p_dec->pf_packetize = Packetize
    149159 
    150160    return VLC_SUCCESS; 
    151161} 
    152162 
     163/***************************************************************************** 
     164 * Close: clean up the packetizer 
     165 *****************************************************************************/ 
     166static void Close( vlc_object_t *p_this ) 
     167{ 
     168    decoder_t *p_dec = (decoder_t*)p_this; 
     169 
     170    free( p_dec->p_sys ); 
     171} 
     172 
    153173/**************************************************************************** 
    154  * PacketizeBlock: the whole thing 
     174 * Packetize: the whole thing 
    155175 ****************************************************************************/ 
    156 static block_t *PacketizeBlock( decoder_t *p_dec, block_t **pp_block ) 
    157 
     176static block_t *Packetize( decoder_t *p_dec, block_t **pp_block ) 
     177
     178    decoder_sys_t *p_sys = p_dec->p_sys; 
     179 
     180    block_t *p_chain_out = NULL; 
    158181    block_t *p_block; 
     182    uint8_t *p_vol = NULL; 
     183    uint8_t *p_start; 
    159184 
    160185    if( !pp_block || !*pp_block ) return NULL; 
     
    162187    p_block = *pp_block; 
    163188 
    164     if( !p_dec->fmt_out.i_extra ) 
    165     { 
    166         m4v_FindVol( p_dec, p_block ); 
    167     } 
    168  
    169     /* Drop blocks until we have a VOL */ 
    170     if( !p_dec->fmt_out.i_extra ) 
    171     { 
    172         block_Release( p_block ); 
    173         return NULL; 
    174     } 
    175  
    176     /* TODO: Date management */ 
    177     p_block->i_length = 1000000 / 25; 
    178  
    179     *pp_block = NULL; 
    180     return p_block; 
     189    /* Append data */ 
     190    if( p_sys->i_buffer + p_block->i_buffer > p_sys->i_buffer_size ) 
     191    { 
     192        p_sys->i_buffer_size += p_block->i_buffer + 1024; 
     193        p_sys->p_buffer = realloc( p_sys->p_buffer, p_sys->i_buffer_size ); 
     194    } 
     195    memcpy( &p_sys->p_buffer[p_sys->i_buffer], p_block->p_buffer, 
     196            p_block->i_buffer ); 
     197    p_sys->i_buffer += p_block->i_buffer; 
     198 
     199    if( p_sys->i_buffer > 10*1000000 ) 
     200    { 
     201        msg_Err( p_dec, "mmh reseting context" ); 
     202        p_sys->i_buffer = 0; 
     203    } 
     204 
     205    /* Search vop */ 
     206    p_start = &p_sys->p_buffer[p_sys->i_buffer - p_block->i_buffer - 4]; 
     207    if( p_start < p_sys->p_buffer ) 
     208    { 
     209        p_start = p_sys->p_buffer; 
     210    } 
     211    for( ;; ) 
     212    { 
     213        if( m4v_FindStartCode( &p_start, &p_sys->p_buffer[p_sys->i_buffer] ) ) 
     214        { 
     215            block_Release( p_block ); 
     216            *pp_block = NULL; 
     217            return p_chain_out; 
     218        } 
     219        /* fprintf( stderr, "start code=0x1%2.2x\n", p_start[3] ); */ 
     220 
     221        if( p_vol ) 
     222        { 
     223            /* Copy the complete VOL */ 
     224            p_dec->fmt_out.i_extra = p_start - p_vol; 
     225            p_dec->fmt_out.p_extra = malloc( p_dec->fmt_out.i_extra ); 
     226            memcpy( p_dec->fmt_out.p_extra, p_vol, p_dec->fmt_out.i_extra ); 
     227            m4v_VOLParse( &p_dec->fmt_out, 
     228                          p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra ); 
     229 
     230            p_vol = NULL; 
     231        } 
     232        if( p_sys->b_vop ) 
     233        { 
     234            /* Output the complete VOP we have */ 
     235            int     i_out = p_start - p_sys->p_buffer; 
     236            block_t *p_out = block_New( p_dec, i_out ); 
     237 
     238            /* extract data */ 
     239            memcpy( p_out->p_buffer, p_sys->p_buffer, i_out ); 
     240            if( i_out < p_sys->i_buffer ) 
     241            { 
     242                memmove( p_sys->p_buffer, &p_sys->p_buffer[i_out], 
     243                         p_sys->i_buffer - i_out ); 
     244            } 
     245            p_sys->i_buffer -= i_out; 
     246            p_start -= i_out; 
     247 
     248            /* FIXME do proper dts/pts */ 
     249            p_out->i_pts = p_sys->i_pts; 
     250            p_out->i_dts = p_sys->i_dts; 
     251            /* FIXME doesn't work when there is multiple VOP in one block */ 
     252            if( p_block->i_dts > p_sys->i_dts ) 
     253            { 
     254                p_out->i_length = p_block->i_dts - p_sys->i_dts; 
     255            } 
     256 
     257            if( p_dec->fmt_out.i_extra > 0 ) 
     258            { 
     259                block_ChainAppend( &p_chain_out, p_out ); 
     260            } 
     261            else 
     262            { 
     263                msg_Warn( p_dec, "waiting for VOL" ); 
     264                block_Release( p_out ); 
     265            } 
     266 
     267#if 0 
     268            fprintf( stderr, "pts=%lld dts=%lld length=%lldms\n", 
     269                     p_out->i_pts, p_out->i_dts, 
     270                     p_out->i_length / 1000 ); 
     271#endif 
     272            p_sys->b_vop = VLC_FALSE; 
     273        } 
     274 
     275        if( p_start[3] >= 0x20 && p_start[3] <= 0x2f ) 
     276        { 
     277            /* Start of the VOL */ 
     278            p_vol = p_start; 
     279        } 
     280        else if( p_start[3] == 0xb6 ) 
     281        { 
     282            p_sys->b_vop = VLC_TRUE; 
     283            p_sys->i_pts = p_block->i_pts; 
     284            p_sys->i_dts = p_block->i_dts; 
     285        } 
     286        p_start += 4; /* Next */ 
     287    } 
    181288} 
    182289 
     
    184291 * m4v_FindStartCode 
    185292 ****************************************************************************/ 
    186 static int m4v_FindStartCode( uint8_t **pp_data, uint8_t *p_end ) 
    187 
    188     for( ; *pp_data < p_end - 4; (*pp_data)++ ) 
    189     { 
    190         if( (*pp_data)[0] == 0 && (*pp_data)[1] == 0 && (*pp_data)[2] == 1 ) 
    191         { 
    192             return 0; 
    193         } 
    194     } 
    195     return -1; 
    196 
    197  
    198 static int m4v_FindVol( decoder_t *p_dec, block_t *p_block ) 
    199 
    200     uint8_t *p_vol_begin, *p_vol_end, *p_end; 
    201  
    202     /* search if p_block contains with a vol */ 
    203     p_vol_begin = p_block->p_buffer; 
    204     p_vol_end   = NULL; 
    205     p_end       = p_block->p_buffer + p_block->i_buffer; 
     293static int m4v_FindStartCode( uint8_t **pp_start, uint8_t *p_end ) 
     294
     295    uint8_t *p = *pp_start; 
     296 
     297    for( p = *pp_start; p < p_end - 4; p++ ) 
     298    { 
     299        if( p[0] == 0 && p[1] == 0 && p[2] == 1 ) 
     300        { 
     301            *pp_start = p; 
     302            return VLC_SUCCESS; 
     303        } 
     304    } 
     305 
     306    *pp_start = p_end; 
     307    return VLC_EGENERIC; 
     308
     309 
     310 
     311/* look at ffmpeg av_log2 ;) */ 
     312static int vlc_log2( unsigned int v ) 
     313
     314    int n = 0; 
     315    static const int vlc_log2_table[16] = 
     316    { 
     317        0,0,1,1,2,2,2,2, 3,3,3,3,3,3,3,3 
     318    }; 
     319 
     320    if( v&0xffff0000 ) 
     321    { 
     322        v >>= 16; 
     323        n += 16; 
     324    } 
     325    if( v&0xff00 ) 
     326    { 
     327        v >>= 8; 
     328        n += 8; 
     329    } 
     330    if( v&0xf0 ) 
     331    { 
     332        v >>= 4; 
     333        n += 4; 
     334    } 
     335    n += vlc_log2_table[v]; 
     336 
     337    return n; 
     338
     339 
     340/* m4v_VOLParse: 
     341 *  TODO: 
     342 *      - support aspect ratio 
     343 */ 
     344static int m4v_VOLParse( es_format_t *fmt, uint8_t *p_vol, int i_vol ) 
     345
     346    bs_t s; 
     347    int i_vo_type; 
     348    int i_vo_ver_id; 
     349    int i_ar; 
     350    int i_shape; 
     351    int i_time_increment_resolution; 
    206352 
    207353    for( ;; ) 
    208354    { 
    209         if( m4v_FindStartCode( &p_vol_begin, p_end ) ) 
     355        if( p_vol[0] == 0x00 && p_vol[1] == 0x00 && 
     356            p_vol[2] == 0x01 && 
     357            p_vol[3] >= 0x20 && p_vol[3] <= 0x2f ) 
    210358        { 
    211359            break; 
    212360        } 
    213  
    214         msg_Dbg( p_dec, "starcode 0x%2.2x%2.2x%2.2x%2.2x", 
    215                  p_vol_begin[0], p_vol_begin[1], 
    216                  p_vol_begin[2], p_vol_begin[3] ); 
    217  
    218         if( ( p_vol_begin[3] & ~VIDEO_OBJECT_MASK ) == 
    219             ( VIDEO_OBJECT_START_CODE&0xff ) ) 
    220         { 
    221             p_vol_end = p_vol_begin + 4; 
    222             if( m4v_FindStartCode( &p_vol_end, p_end ) ) 
    223             { 
    224                 p_vol_begin++; 
    225                 continue; 
    226             } 
    227             if( ( p_vol_end[3] & ~VIDEO_OBJECT_LAYER_MASK ) == 
    228                 ( VIDEO_OBJECT_LAYER_START_CODE&0xff ) ) 
    229             { 
    230                 p_vol_end += 4; 
    231                 if( m4v_FindStartCode( &p_vol_end, p_end ) ) 
    232                 { 
    233                     p_vol_end = p_end; 
    234                 } 
    235             } 
    236             else 
    237             { 
    238                 p_vol_begin++; 
    239                 continue; 
    240             } 
    241         } 
    242         else if( ( p_vol_begin[3] & ~VIDEO_OBJECT_LAYER_MASK ) == 
    243                  ( VIDEO_OBJECT_LAYER_START_CODE&0xff) ) 
    244         { 
    245             p_vol_end = p_vol_begin + 4; 
    246             if( m4v_FindStartCode( &p_vol_end, p_end ) ) 
    247             { 
    248                 p_vol_end = p_end; 
    249             } 
    250         } 
    251  
    252         if( p_vol_end != NULL && p_vol_begin < p_vol_end ) 
    253         { 
    254             p_dec->fmt_out.i_extra = p_vol_end - p_vol_begin; 
    255             msg_Dbg( p_dec, "Found VOL" ); 
    256  
    257             p_dec->fmt_out.p_extra = malloc( p_dec->fmt_out.i_extra ); 
    258             memcpy( p_dec->fmt_out.p_extra, p_vol_begin, 
    259                     p_dec->fmt_out.i_extra ); 
    260             return VLC_SUCCESS; 
    261         } 
    262         else 
    263         { 
    264             p_vol_begin++; 
    265         } 
    266     } 
    267  
     361        p_vol++; 
     362        i_vol--; 
     363        if( i_vol <= 4 ) 
     364        { 
     365            return VLC_EGENERIC; 
     366        } 
     367    } 
     368 
     369    /* parse the vol */ 
     370    bs_init( &s, &p_vol[4], i_vol - 4 ); 
     371 
     372    bs_skip( &s, 1 );   /* random access */ 
     373    i_vo_type = bs_read( &s, 8 ); 
     374    if( bs_read1( &s ) ) 
     375    { 
     376        i_vo_ver_id = bs_read( &s, 4 ); 
     377        bs_skip( &s, 3 ); 
     378    } 
     379    else 
     380    { 
     381        i_vo_ver_id = 1; 
     382    } 
     383    i_ar = bs_read( &s, 4 ); 
     384    if( i_ar == 0xf ) 
     385    { 
     386        int i_ar_width = bs_read( &s, 8 ); 
     387        int i_ar_height= bs_read( &s, 8 ); 
     388    } 
     389    if( bs_read1( &s ) ) 
     390    { 
     391        /* vol control parameter */ 
     392        int i_chroma_format = bs_read( &s, 2 ); 
     393        int i_low_delay = bs_read1( &s ); 
     394 
     395        if( bs_read1( &s ) ) 
     396        { 
     397            bs_skip( &s, 16 ); 
     398            bs_skip( &s, 16 ); 
     399            bs_skip( &s, 16 ); 
     400            bs_skip( &s, 3 ); 
     401            bs_skip( &s, 11 ); 
     402            bs_skip( &s, 1 ); 
     403            bs_skip( &s, 16 ); 
     404        } 
     405    } 
     406    /* shape 0->RECT, 1->BIN, 2->BIN_ONLY, 3->GRAY */ 
     407    i_shape = bs_read( &s, 2 ); 
     408    if( i_shape == 3 && i_vo_ver_id != 1 ) 
     409    { 
     410        bs_skip( &s, 4 ); 
     411    } 
     412 
     413    if( !bs_read1( &s ) ) 
     414    { 
     415        /* marker */ 
     416        return VLC_EGENERIC; 
     417    } 
     418    i_time_increment_resolution = bs_read( &s, 16 ); 
     419    if( !bs_read1( &s ) ) 
     420    { 
     421        /* marker */ 
     422        return VLC_EGENERIC; 
     423    } 
     424 
     425    if( bs_read1( &s ) ) 
     426    { 
     427        int i_time_increment_bits = vlc_log2( i_time_increment_resolution - 1 ) + 1; 
     428        if( i_time_increment_bits < 1 ) 
     429        { 
     430            i_time_increment_bits = 1; 
     431        } 
     432        bs_skip( &s, i_time_increment_bits ); 
     433    } 
     434    if( i_shape == 0 ) 
     435    { 
     436        bs_skip( &s, 1 ); 
     437        fmt->video.i_width = bs_read( &s, 13 ); 
     438        bs_skip( &s, 1 ); 
     439        fmt->video.i_height= bs_read( &s, 13 ); 
     440        bs_skip( &s, 1 ); 
     441    } 
    268442    return VLC_SUCCESS; 
    269443} 
    270444 
    271 /***************************************************************************** 
    272  * ClosePacketizer: clean up the packetizer 
    273  *****************************************************************************/ 
    274 static void ClosePacketizer( vlc_object_t *p_this ) 
    275 
    276     decoder_t *p_dec = (decoder_t*)p_this; 
    277  
    278     free( p_dec->p_sys ); 
    279 
     445 
     446