Changeset 5c2cf083f90c34009b799ff65db74f27930a493d

Show
Ignore:
Timestamp:
23/01/04 18:56:14 (5 years ago)
Author:
Gildas Bazin <gbazin@videolan.org>
git-committer:
Gildas Bazin <gbazin@videolan.org> 1074880574 +0000
git-parent:

[83fb2ffc0f3884d99ea91d0de0451a6923fb944a]

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

* src/stream_output/stream_output.c, include/stream_output.h: new sout_AccessOutRead() funcion.
* modules/access_output/file.c: implemented sout_AccessOutRead().
* modules/access_output/udp.c: coding style cleanup.
* modules/mux/mp4.c: Added support for generating "fast start" files (ie. with the moov header at the beginning of the file).

Started some code cleanup.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • include/stream_output.h

    rc89488f r5c2cf08  
    33 ***************************************************************************** 
    44 * Copyright (C) 2002 VideoLAN 
    5  * $Id: stream_output.h,v 1.18 2003/12/07 17:09:33 gbazin Exp $ 
     5 * $Id: stream_output.h,v 1.19 2004/01/23 17:56:14 gbazin Exp $ 
    66 * 
    77 * Authors: Christophe Massiot <massiot@via.ecp.fr> 
     
    122122    int                     (* pf_seek  )( sout_access_out_t *, 
    123123                                           off_t ); 
     124    int                     (* pf_read  )( sout_access_out_t *, 
     125                                           sout_buffer_t * ); 
    124126    int                     (* pf_write )( sout_access_out_t *, 
    125127                                           sout_buffer_t * ); 
     
    296298VLC_EXPORT( void,                sout_AccessOutDelete, ( sout_access_out_t * ) ); 
    297299VLC_EXPORT( int,                 sout_AccessOutSeek,   ( sout_access_out_t *, off_t ) ); 
     300VLC_EXPORT( int,                 sout_AccessOutRead,   ( sout_access_out_t *, sout_buffer_t * ) ); 
    298301VLC_EXPORT( int,                 sout_AccessOutWrite,  ( sout_access_out_t *, sout_buffer_t * ) ); 
    299302 
  • modules/access_output/file.c

    r0d90e52 r5c2cf08  
    33 ***************************************************************************** 
    44 * Copyright (C) 2001, 2002 VideoLAN 
    5  * $Id: file.c,v 1.10 2003/12/04 12:33:43 gbazin Exp $ 
     5 * $Id: file.c,v 1.11 2004/01/23 17:56:14 gbazin Exp $ 
    66 * 
    77 * Authors: Laurent Aimar <fenrir@via.ecp.fr> 
     
    6262static int     Write( sout_access_out_t *, sout_buffer_t * ); 
    6363static int     Seek ( sout_access_out_t *, off_t  ); 
     64static int     Read ( sout_access_out_t *, sout_buffer_t * ); 
    6465 
    6566/***************************************************************************** 
     
    9899        return VLC_EGENERIC; 
    99100    } 
    100     i_flags = O_WRONLY|O_CREAT; 
     101    i_flags = O_RDWR|O_CREAT; 
    101102    if( sout_cfg_find_value( p_access->p_cfg, "append" ) ) 
    102103    { 
     
    121122    } 
    122123 
    123     p_access->pf_write        = Write; 
    124     p_access->pf_seek         = Seek; 
     124    p_access->pf_write = Write; 
     125    p_access->pf_read  = Read; 
     126    p_access->pf_seek  = Seek; 
    125127 
    126128    msg_Info( p_access, "Open: name:`%s'", p_access->psz_name ); 
     
    133135static void Close( vlc_object_t * p_this ) 
    134136{ 
    135     sout_access_out_t   *p_access = (sout_access_out_t*)p_this; 
     137    sout_access_out_t *p_access = (sout_access_out_t*)p_this; 
    136138 
    137139    if( strcmp( p_access->psz_name, "-" ) ) 
     
    149151/***************************************************************************** 
    150152 * Read: standard read on a file descriptor. 
     153 *****************************************************************************/ 
     154static int Read( sout_access_out_t *p_access, sout_buffer_t *p_buffer ) 
     155{ 
     156    if( strcmp( p_access->psz_name, "-" ) ) 
     157    { 
     158        return read( p_access->p_sys->i_handle, p_buffer->p_buffer, 
     159                     p_buffer->i_size ); 
     160    } 
     161    else 
     162    { 
     163        msg_Err( p_access, "cannot seek while using stdout" ); 
     164        return VLC_EGENERIC; 
     165    } 
     166} 
     167 
     168/***************************************************************************** 
     169 * Write: standard write on a file descriptor. 
    151170 *****************************************************************************/ 
    152171static int Write( sout_access_out_t *p_access, sout_buffer_t *p_buffer ) 
     
    174193static int Seek( sout_access_out_t *p_access, off_t i_pos ) 
    175194{ 
    176     msg_Dbg( p_access, "Seek: pos:"I64Fd, (int64_t)i_pos ); 
     195    //msg_Dbg( p_access, "Seek: pos:"I64Fd, (int64_t)i_pos ); 
    177196 
    178197    if( strcmp( p_access->psz_name, "-" ) ) 
  • modules/access_output/udp.c

    r8c510a9 r5c2cf08  
    33 ***************************************************************************** 
    44 * Copyright (C) 2001, 2002 VideoLAN 
    5  * $Id: udp.c,v 1.16 2003/11/17 14:46:37 massiot Exp $ 
     5 * $Id: udp.c,v 1.17 2004/01/23 17:56:14 gbazin Exp $ 
    66 * 
    77 * Authors: Laurent Aimar <fenrir@via.ecp.fr> 
     
    5454 
    5555#define DEFAULT_PORT 1234 
    56 #define LATENCY     100000 
    57 #define MAX_ERROR    500000 
    5856/***************************************************************************** 
    5957 * Exported prototypes 
     
    131129    network_socket_t    socket_desc; 
    132130 
    133     char                *val; 
     131    vlc_value_t         val; 
     132    char                *psz_val; 
    134133 
    135134    if( !( p_sys = p_access->p_sys = 
     
    137136    { 
    138137        msg_Err( p_access, "Not enough memory" ); 
    139         return( VLC_EGENERIC )
     138        return VLC_EGENERIC
    140139    } 
    141140 
     
    185184    { 
    186185        msg_Err( p_access, "out of memory" ); 
    187         return( VLC_EGENERIC )
     186        return VLC_EGENERIC
    188187    } 
    189188 
     
    199198    socket_desc.i_bind_port     = 0; 
    200199    socket_desc.i_ttl           = 0; 
    201     if( ( val = sout_cfg_find_value( p_access->p_cfg, "ttl" ) ) ) 
    202     { 
    203         socket_desc.i_ttl = atoi( val ); 
     200    if( ( psz_val = sout_cfg_find_value( p_access->p_cfg, "ttl" ) ) ) 
     201    { 
     202        socket_desc.i_ttl = atoi( psz_val ); 
    204203    } 
    205204    p_sys->p_thread->p_private = (void*)&socket_desc; 
    206     if( !( p_network = module_Need( p_sys->p_thread, 
    207                                     "network", "" ) ) ) 
     205    if( !( p_network = module_Need( p_sys->p_thread, "network", "" ) ) ) 
    208206    { 
    209207        msg_Err( p_access, "failed to open a connection (udp)" ); 
    210         return( VLC_EGENERIC )
     208        return VLC_EGENERIC
    211209    } 
    212210    module_Unneed( p_sys->p_thread, p_network ); 
    213211 
    214212    p_sys->p_thread->i_handle = socket_desc.i_handle; 
    215     p_sys->p_thread->i_caching = config_GetInt( p_this, "udp-sout-caching" ) * 1000; 
    216     if( ( val = sout_cfg_find_value( p_access->p_cfg, "caching" ) ) ) 
    217     { 
    218         p_sys->p_thread->i_caching = atoll( val ) * 1000; 
    219     } 
    220  
    221     p_sys->i_mtu     = socket_desc.i_mtu; 
     213 
     214    var_Create( p_this, "udp-sout-caching", 
     215                VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); 
     216    var_Get( p_this, "udp-sout-caching", &val ); 
     217    p_sys->p_thread->i_caching = val.i_int * 1000; 
     218    if( ( psz_val = sout_cfg_find_value( p_access->p_cfg, "caching" ) ) ) 
     219    { 
     220        p_sys->p_thread->i_caching = atoll( psz_val ) * 1000; 
     221    } 
     222 
     223    p_sys->i_mtu = socket_desc.i_mtu; 
    222224 
    223225    if( vlc_thread_create( p_sys->p_thread, "sout write thread", ThreadWrite, 
     
    226228        msg_Err( p_access->p_sout, "cannot spawn sout access thread" ); 
    227229        vlc_object_destroy( p_sys->p_thread ); 
    228         return( VLC_EGENERIC )
     230        return VLC_EGENERIC
    229231    } 
    230232 
     
    236238    if( sout_cfg_find( p_access->p_cfg, "raw" ) ) 
    237239    { 
    238         p_access->pf_write       = WriteRaw; 
     240        p_access->pf_write = WriteRaw; 
    239241    } 
    240242    else 
    241243    { 
    242         p_access->pf_write       = Write; 
    243     } 
    244     p_access->pf_seek        = Seek; 
    245  
    246     msg_Info( p_access, "Open: addr:`%s' port:`%d'", 
    247               psz_dst_addr, i_dst_port ); 
     244        p_access->pf_write = Write; 
     245    } 
     246 
     247    p_access->pf_seek = Seek; 
     248 
     249    msg_Info( p_access, "Open: addr:`%s' port:`%d'", psz_dst_addr, i_dst_port); 
    248250 
    249251    free( psz_dst_addr ); 
     
    256258static void Close( vlc_object_t * p_this ) 
    257259{ 
    258     sout_access_out_t       *p_access = (sout_access_out_t*)p_this; 
    259     sout_access_out_sys_t   *p_sys = p_access->p_sys; 
    260     int                 i; 
     260    sout_access_out_t     *p_access = (sout_access_out_t*)p_this; 
     261    sout_access_out_sys_t *p_sys = p_access->p_sys; 
     262    int i; 
    261263 
    262264    p_sys->p_thread->b_die = 1; 
    263265    for( i = 0; i < 10; i++ ) 
    264266    { 
    265         sout_buffer_t       *p_dummy; 
     267        sout_buffer_t *p_dummy; 
    266268 
    267269        p_dummy = sout_BufferNew( p_access->p_sout, p_sys->i_mtu ); 
     
    297299static int Write( sout_access_out_t *p_access, sout_buffer_t *p_buffer ) 
    298300{ 
    299     sout_access_out_sys_t   *p_sys = p_access->p_sys; 
     301    sout_access_out_sys_t *p_sys = p_access->p_sys; 
    300302    unsigned int i_write; 
    301303 
     
    357359static int Seek( sout_access_out_t *p_access, off_t i_pos ) 
    358360{ 
    359  
    360361    msg_Err( p_access, "udp sout access cannot seek" ); 
    361362    return( -1 ); 
  • modules/mux/mp4.c

    rd4dda46 r5c2cf08  
    33 ***************************************************************************** 
    44 * Copyright (C) 2001, 2002, 2003 VideoLAN 
    5  * $Id: mp4.c,v 1.9 2004/01/13 15:54:09 gbazin Exp $ 
     5 * $Id: mp4.c,v 1.10 2004/01/23 17:56:14 gbazin Exp $ 
    66 * 
    77 * Authors: Laurent Aimar <fenrir@via.ecp.fr> 
     
    4343 * Exported prototypes 
    4444 *****************************************************************************/ 
    45 static int     Open   ( vlc_object_t * ); 
    46 static void    Close  ( vlc_object_t * ); 
     45static int  Open   ( vlc_object_t * ); 
     46static void Close  ( vlc_object_t * ); 
    4747 
    4848static int Capability(sout_mux_t *, int, void *, void * ); 
     
    5454 * Module descriptor 
    5555 *****************************************************************************/ 
     56#define FASTSTART_TEXT N_("Create \"Fast start\" files") 
     57#define FASTSTART_LONGTEXT N_( \ 
     58    "When this option is turned on, \"Fast start\" files will be created. " \ 
     59    "(\"Fast start\" files are optimized for download, allowing the user " \ 
     60    "to start previewing the file while it is downloading).") 
     61 
    5662vlc_module_begin(); 
    5763    set_description( _("MP4/MOV muxer") ); 
     64 
     65    add_category_hint( "MP4/MOV muxer", NULL, VLC_TRUE ); 
     66        add_bool( "mp4-faststart", 1, NULL, FASTSTART_TEXT, FASTSTART_LONGTEXT, VLC_TRUE ); 
     67 
    5868    set_capability( "sout mux", 5 ); 
    5969    add_shortcut( "mp4" ); 
     
    6272vlc_module_end(); 
    6373 
     74/***************************************************************************** 
     75 * Local prototypes 
     76 *****************************************************************************/ 
    6477typedef struct 
    6578{ 
     
    8598    /* stats */ 
    8699    mtime_t      i_duration; 
     100 
     101    /* for later stco fix-up (fast start files) */ 
     102    uint64_t i_stco_pos; 
     103    vlc_bool_t b_stco64; 
     104 
    87105} mp4_stream_t; 
    88106 
     
    91109    vlc_bool_t b_mov; 
    92110    vlc_bool_t b_64_ext; 
     111    vlc_bool_t b_fast_start; 
    93112 
    94113    uint64_t i_mdat_pos; 
     
    101120}; 
    102121 
    103  
    104 typedef struct bo_t bo_t; 
    105 struct bo_t 
     122typedef struct bo_t 
    106123{ 
    107124    vlc_bool_t b_grow; 
     
    111128    uint8_t    *p_buffer; 
    112129 
    113 }
     130} bo_t
    114131 
    115132static void bo_init     ( bo_t *, int , uint8_t *, vlc_bool_t  ); 
     
    122139static void bo_add_bo   ( bo_t *, bo_t * ); 
    123140static void bo_add_mem  ( bo_t *, int , uint8_t * ); 
    124 static void bo_add_descr ( bo_t *, uint8_t , uint32_t ); 
     141static void bo_add_descr( bo_t *, uint8_t , uint32_t ); 
    125142 
    126143static void bo_fix_32be ( bo_t *, int , uint32_t ); 
     
    136153static int64_t get_timestamp(); 
    137154 
    138 static sout_buffer_t * bo_to_sout( sout_instance_t *p_sout,  bo_t *box ); 
     155static sout_buffer_t *bo_to_sout( sout_instance_t *p_sout,  bo_t *box ); 
    139156 
    140157/***************************************************************************** 
     
    155172    p_sys->i_start_dts  = 0; 
    156173 
    157     msg_Info( p_mux, "Open" ); 
     174    msg_Dbg( p_mux, "Open" ); 
    158175 
    159176    p_mux->pf_capacity  = Capability; 
     
    334351} 
    335352 
    336 /***************************************************************************** 
    337  * Close: 
    338  *****************************************************************************/ 
     353static bo_t *GetUdtaTag( sout_mux_t *p_mux ) 
     354
     355    sout_mux_sys_t *p_sys = p_mux->p_sys; 
     356    bo_t *udta = box_new( "udta" ); 
     357    int i_track; 
     358 
     359    /* Requirements */ 
     360    for( i_track = 0; i_track < p_sys->i_nb_streams; i_track++ ) 
     361    { 
     362        mp4_stream_t *p_stream = p_sys->pp_streams[i_track]; 
     363 
     364        if( p_stream->p_fmt->i_codec == VLC_FOURCC('m','p','4','v') || 
     365            p_stream->p_fmt->i_codec == VLC_FOURCC('m','p','4','a') ) 
     366        { 
     367            bo_t *box = box_new( "\251req" ); 
     368            /* String length */ 
     369            bo_add_16be( box, sizeof("QuickTime 6.0 or greater") - 1); 
     370            bo_add_16be( box, 0 ); 
     371            bo_add_mem( box, sizeof("QuickTime 6.0 or greater") - 1, 
     372                        "QuickTime 6.0 or greater" ); 
     373            box_fix( box ); 
     374            box_gather( udta, box ); 
     375            break; 
     376        } 
     377    } 
     378 
     379    /* Encoder */ 
     380    { 
     381        bo_t *box = box_new( "\251enc" ); 
     382        /* String length */ 
     383        bo_add_16be( box, sizeof(PACKAGE_STRING " stream output") - 1); 
     384        bo_add_16be( box, 0 ); 
     385        bo_add_mem( box, sizeof(PACKAGE_STRING " stream output") - 1, 
     386                    PACKAGE_STRING " stream output" ); 
     387        box_fix( box ); 
     388        box_gather( udta, box ); 
     389    } 
     390 
     391    box_fix( udta ); 
     392    return udta; 
     393
     394 
    339395static uint32_t mvhd_matrix[9] = 
    340396    { 0x10000, 0, 0, 0, 0x10000, 0, 0, 0, 0x40000000 }; 
    341397 
    342 static void Close( vlc_object_t * p_this ) 
    343 
    344     sout_mux_t *p_mux = (sout_mux_t*)p_this; 
    345     sout_mux_sys_t  *p_sys = p_mux->p_sys; 
    346     sout_buffer_t   *p_hdr; 
    347     bo_t            bo; 
     398static bo_t *GetMoovTag( sout_mux_t *p_mux ) 
     399
     400    sout_mux_sys_t *p_sys = p_mux->p_sys; 
     401 
    348402    bo_t            *moov, *mvhd; 
    349403    unsigned int    i; 
     
    352406    uint32_t        i_movie_timescale = 90000; 
    353407    int64_t         i_movie_duration  = 0; 
    354     msg_Info( p_mux, "Close" ); 
    355  
    356     /* create general info */ 
    357     for( i_trak = 0; i_trak < p_sys->i_nb_streams; i_trak++ ) 
    358     { 
    359         mp4_stream_t *p_stream; 
    360  
    361         p_stream = p_sys->pp_streams[i_trak]; 
    362  
    363         i_movie_duration = __MAX( i_movie_duration, p_stream->i_duration ); 
    364     } 
    365     msg_Dbg( p_mux, "movie duration %ds", 
    366              (uint32_t)( i_movie_duration / (mtime_t)1000000 ) ); 
    367  
    368     i_movie_duration = i_movie_duration * 
    369                        (int64_t)i_movie_timescale / (int64_t)1000000; 
    370  
    371     /* *** update mdat size *** */ 
    372     bo_init      ( &bo, 0, NULL, VLC_TRUE ); 
    373     if( p_sys->i_pos - p_sys->i_mdat_pos >= (((uint64_t)1)<<32) ) 
    374     { 
    375         /* Extended size */ 
    376         bo_add_32be  ( &bo, 1 ); 
    377         bo_add_fourcc( &bo, "mdat" ); 
    378         bo_add_64be  ( &bo, p_sys->i_pos - p_sys->i_mdat_pos ); 
    379     } 
    380     else 
    381     { 
    382         bo_add_32be  ( &bo, 8 ); 
    383         bo_add_fourcc( &bo, "wide" ); 
    384         bo_add_32be  ( &bo, p_sys->i_pos - p_sys->i_mdat_pos - 8 ); 
    385         bo_add_fourcc( &bo, "mdat" ); 
    386     } 
    387  
    388     p_hdr = bo_to_sout( p_mux->p_sout, &bo ); 
    389     free( bo.p_buffer ); 
    390  
    391     /* seek to mdat */ 
    392     sout_AccessOutSeek( p_mux->p_access, p_sys->i_mdat_pos ); 
    393     sout_AccessOutWrite( p_mux->p_access, p_hdr ); 
    394  
    395     /* Now create header */ 
    396     sout_AccessOutSeek( p_mux->p_access, p_sys->i_pos ); 
    397408 
    398409    moov = box_new( "moov" ); 
     
    455466        uint32_t     i_timescale; 
    456467        uint32_t     i_chunk_count; 
     468        unsigned int i_chunk; 
    457469 
    458470        bo_t *trak; 
     
    467479        bo_t *stsd; 
    468480        bo_t *stts; 
     481        bo_t *stco; 
     482        bo_t *stsc; 
    469483        bo_t *stsz; 
    470484 
     
    702716            bo_add_32be( soun, 0 );         // vendor 
    703717            bo_add_16be( soun, p_stream->p_fmt->audio.i_channels );   // channel-count 
    704             bo_add_16be( soun, 16);         // FIXME sample size 
     718            // sample size 
     719            bo_add_16be( soun, p_stream->p_fmt->audio.i_bitspersample ? 
     720                         p_stream->p_fmt->audio.i_bitspersample : 16 ); 
    705721            bo_add_16be( soun, -2 );        // compression id 
    706722            bo_add_16be( soun, 0 );         // packet size (0) 
     
    832848        box_gather( stbl, stsd ); 
    833849 
    834         /* we will create chunk table and stsc table FIXME optim stsc table FIXME */ 
     850        /* we will create chunk table and stsc table 
     851         * FIXME optim stsc table FIXME */ 
    835852        i_chunk_count = 0; 
    836853        for( i = 0; i < p_stream->i_entry_count; ) 
     
    852869 
    853870        /* chunk offset table */ 
     871        p_stream->i_stco_pos = stbl->i_buffer + 16; 
    854872        if( p_sys->i_pos >= (((uint64_t)0x1) << 32) ) 
    855873        { 
    856874            /* 64 bits version */ 
    857             bo_t *co64; 
    858             bo_t *stsc; 
    859  
    860             unsigned int  i_chunk; 
    861  
    862875            msg_Dbg( p_mux, "creating %d chunk (co64)", i_chunk_count ); 
    863  
    864             co64 = box_full_new( "co64", 0, 0 ); 
    865             bo_add_32be( co64, i_chunk_count ); 
    866  
    867             stsc = box_full_new( "stsc", 0, 0 ); 
    868             bo_add_32be( stsc, i_chunk_count );     // entry-count 
     876            p_stream->b_stco64 = VLC_TRUE; 
     877            stco = box_full_new( "co64", 0, 0 ); 
     878        } 
     879        else 
     880        { 
     881            /* 32 bits version */ 
     882            msg_Dbg( p_mux, "creating %d chunk (stco)", i_chunk_count ); 
     883            p_stream->b_stco64 = VLC_FALSE; 
     884            stco = box_full_new( "stco", 0, 0 ); 
     885        } 
     886 
     887        bo_add_32be( stco, i_chunk_count ); 
     888 
     889        stsc = box_full_new( "stsc", 0, 0 ); 
     890        bo_add_32be( stsc, i_chunk_count );     // entry-count 
     891        for( i_chunk = 0, i = 0; i < p_stream->i_entry_count; i_chunk++ ) 
     892        { 
     893            int i_first; 
     894 
     895            if( p_stream->b_stco64 ) 
     896                bo_add_64be( stco, p_stream->entry[i].i_pos ); 
     897            else 
     898                bo_add_32be( stco, p_stream->entry[i].i_pos ); 
     899 
     900            i_first = i; 
     901 
     902            while( i < p_stream->i_entry_count ) 
     903            { 
     904                if( i + 1 < p_stream->i_entry_count && 
     905                    p_stream->entry[i].i_pos + p_stream->entry[i].i_size 
     906                    != p_stream->entry[i + 1].i_pos ) 
     907                { 
     908                    i++; 
     909                    break; 
     910                } 
     911 
     912                i++; 
     913            } 
     914            bo_add_32be( stsc, 1 + i_chunk );   // first-chunk 
     915            bo_add_32be( stsc, i - i_first ) ;  // samples-per-chunk 
     916            bo_add_32be( stsc, 1 );             // sample-descr-index 
     917        } 
     918 
     919        /* append stco to stbl */ 
     920        box_fix( stco ); 
     921        box_gather( stbl, stco ); 
     922 
     923        /* append stsc to stbl */ 
     924        box_fix( stsc ); 
     925        box_gather( stbl, stsc ); 
     926 
     927        /* add stts */ 
     928        stts = box_full_new( "stts", 0, 0 ); 
     929        bo_add_32be( stts, 0 );     // fixed latter 
     930        for( i = 0, i_index = 0; i < p_stream->i_entry_count; i_index++) 
     931        { 
     932            int64_t i_delta; 
     933            int     i_first; 
     934 
     935            i_first = i; 
     936            i_delta = p_stream->entry[i].i_length; 
     937 
     938            while( i < p_stream->i_entry_count ) 
     939            { 
     940                if( i + 1 < p_stream->i_entry_count && 
     941                    p_stream->entry[i + 1].i_length != i_delta ) 
     942                { 
     943                    i++; 
     944                    break; 
     945                } 
     946 
     947                i++; 
     948            } 
     949 
     950            bo_add_32be( stts, i - i_first );           // sample-count 
     951            bo_add_32be( stts, i_delta * (int64_t)i_timescale / 
     952                               (int64_t)1000000 );      // sample-delta 
     953        } 
     954        bo_fix_32be( stts, 12, i_index ); 
     955 
     956        /* append stts to stbl */ 
     957        box_fix( stts ); 
     958        box_gather( stbl, stts ); 
     959 
     960        /* FIXME add ctts ?? FIXME */ 
     961 
     962        stsz = box_full_new( "stsz", 0, 0 ); 
     963        bo_add_32be( stsz, 0 );                             // sample-size 
     964        bo_add_32be( stsz, p_stream->i_entry_count );       // sample-count 
     965        for( i = 0; i < p_stream->i_entry_count; i++ ) 
     966        { 
     967            bo_add_32be( stsz, p_stream->entry[i].i_size ); // sample-size 
     968        } 
     969        /* append stsz to stbl */ 
     970        box_fix( stsz ); 
     971        box_gather( stbl, stsz ); 
     972 
     973        /* append stbl to minf */ 
     974        box_fix( stbl ); 
     975        p_stream->i_stco_pos += minf->i_buffer; 
     976        box_gather( minf, stbl ); 
     977 
     978        /* append minf to mdia */ 
     979        box_fix( minf ); 
     980        p_stream->i_stco_pos += mdia->i_buffer; 
     981        box_gather( mdia, minf ); 
     982 
     983        /* append mdia to trak */ 
     984        box_fix( mdia ); 
     985        p_stream->i_stco_pos += trak->i_buffer; 
     986        box_gather( trak, mdia ); 
     987 
     988        /* append trak to moov */ 
     989        box_fix( trak ); 
     990        p_stream->i_stco_pos += moov->i_buffer; 
     991        box_gather( moov, trak ); 
     992    } 
     993 
     994    /* Add user data tags */ 
     995    box_gather( moov, GetUdtaTag( p_mux ) ); 
     996 
     997    box_fix( moov ); 
     998    return moov; 
     999
     1000 
     1001/***************************************************************************** 
     1002 * Close: 
     1003 *****************************************************************************/ 
     1004static void Close( vlc_object_t * p_this ) 
     1005
     1006    sout_mux_t      *p_mux = (sout_mux_t*)p_this; 
     1007    sout_mux_sys_t  *p_sys = p_mux->p_sys; 
     1008    sout_buffer_t   *p_hdr; 
     1009    bo_t            bo, *moov; 
     1010    vlc_value_t     val; 
     1011 
     1012    int             i_trak; 
     1013    uint64_t        i_moov_pos; 
     1014 
     1015    uint32_t        i_movie_timescale = 90000; 
     1016    int64_t         i_movie_duration  = 0; 
     1017 
     1018    msg_Dbg( p_mux, "Close" ); 
     1019 
     1020    /* Create general info */ 
     1021    for( i_trak = 0; i_trak < p_sys->i_nb_streams; i_trak++ ) 
     1022    { 
     1023        mp4_stream_t *p_stream = p_sys->pp_streams[i_trak]; 
     1024        i_movie_duration = __MAX( i_movie_duration, p_stream->i_duration ); 
     1025    } 
     1026    msg_Dbg( p_mux, "movie duration %ds", 
     1027             (uint32_t)( i_movie_duration / (mtime_t)1000000 ) ); 
     1028 
     1029    i_movie_duration = i_movie_duration * i_movie_timescale / 1000000; 
     1030 
     1031    /* Update mdat size */ 
     1032    bo_init( &bo, 0, NULL, VLC_TRUE ); 
     1033    if( p_sys->i_pos - p_sys->i_mdat_pos >= (((uint64_t)1)<<32) ) 
     1034    { 
     1035        /* Extended size */ 
     1036        bo_add_32be  ( &bo, 1 ); 
     1037        bo_add_fourcc( &bo, "mdat" ); 
     1038        bo_add_64be  ( &bo, p_sys->i_pos - p_sys->i_mdat_pos ); 
     1039    } 
     1040    else 
     1041    { 
     1042        bo_add_32be  ( &bo, 8 ); 
     1043        bo_add_fourcc( &bo, "wide" ); 
     1044        bo_add_32be  ( &bo, p_sys->i_pos - p_sys->i_mdat_pos - 8 ); 
     1045        bo_add_fourcc( &bo, "mdat" ); 
     1046    } 
     1047    p_hdr = bo_to_sout( p_mux->p_sout, &bo ); 
     1048    free( bo.p_buffer ); 
     1049 
     1050    sout_AccessOutSeek( p_mux->p_access, p_sys->i_mdat_pos ); 
     1051    sout_AccessOutWrite( p_mux->p_access, p_hdr ); 
     1052 
     1053    /* Create MOOV header */ 
     1054    i_moov_pos = p_sys->i_pos; 
     1055    moov = GetMoovTag( p_mux ); 
     1056 
     1057    /* Check we need to create "fast start" files */ 
     1058    var_Create( p_this, "mp4-faststart", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); 
     1059    var_Get( p_this, "mp4-faststart", &val ); 
     1060    p_sys->b_fast_start = val.b_bool; 
     1061    while( p_sys->b_fast_start ) 
     1062    { 
     1063        /* Move data to the end of the file so we can fit the moov header 
     1064         * at the start */ 
     1065        sout_buffer_t *p_buf; 
     1066        int64_t i_chunk, i_size = p_sys->i_pos - p_sys->i_mdat_pos; 
     1067        int i_moov_size = moov->i_buffer; 
     1068 
     1069        while( i_size > 0 ) 
     1070        { 
     1071            i_chunk = __MIN( 32768, i_size ); 
     1072            p_buf = sout_BufferNew( p_mux->p_sout, i_chunk ); 
     1073            sout_AccessOutSeek( p_mux->p_access, 
     1074                                p_sys->i_mdat_pos + i_size - i_chunk ); 
     1075            if( sout_AccessOutRead( p_mux->p_access, p_buf ) < i_chunk ) 
     1076            { 
     1077                msg_Warn( p_this, "read() not supported by acces output, " 
     1078                          "won't create a fast start file" ); 
     1079                p_sys->b_fast_start = VLC_FALSE; 
     1080                break; 
     1081            } 
     1082            sout_AccessOutSeek( p_mux->p_access, p_sys->i_mdat_pos + i_size + 
     1083                                i_moov_size - i_chunk ); 
     1084            sout_AccessOutWrite( p_mux->p_access, p_buf ); 
     1085            i_size -= i_chunk; 
     1086        } 
     1087 
     1088        if( !p_sys->b_fast_start ) break; 
     1089 
     1090        /* Fix-up samples to chunks table in MOOV header */ 
     1091        for( i_trak = 0; i_trak < p_sys->i_nb_streams; i_trak++ ) 
     1092        { 
     1093            mp4_stream_t *p_stream = p_sys->pp_streams[i_trak]; 
     1094            unsigned int i; 
     1095            int i_chunk; 
     1096 
     1097            moov->i_buffer = p_stream->i_stco_pos; 
    8691098            for( i_chunk = 0, i = 0; i < p_stream->i_entry_count; i_chunk++ ) 
    8701099            { 
    871                 int i_first; 
    872                 bo_add_64be( co64, p_stream->entry[i].i_pos ); 
    873  
    874                 i_first = i
     1100                if( p_stream->b_stco64 ) 
     1101                    bo_add_64be( moov, p_stream->entry[i].i_pos + i_moov_size); 
     1102                else 
     1103                    bo_add_32be( moov, p_stream->entry[i].i_pos + i_moov_size)
    8751104 
    8761105                while( i < p_stream->i_entry_count ) 
     
    8861115                    i++; 
    8871116                } 
    888                 bo_add_32be( stsc, 1 + i_chunk );   // first-chunk 
    889                 bo_add_32be( stsc, i - i_first ) ;  // samples-per-chunk 
    890                 bo_add_32be( stsc, 1 );             // sample-descr-index 
    891             } 
    892             /* append co64 to stbl */ 
    893             box_fix( co64 ); 
    894             box_gather( stbl, co64 ); 
    895  
    896             /* append stsc to stbl */ 
    897             box_fix( stsc ); 
    898             box_gather( stbl, stsc ); 
    899         } 
    900         else 
    901         { 
    902             /* 32 bits version */ 
    903             bo_t *stco; 
    904             bo_t *stsc; 
    905  
    906             unsigned int  i_chunk; 
    907  
    908             msg_Dbg( p_mux, "creating %d chunk (stco)", i_chunk_count ); 
    909  
    910             stco = box_full_new( "stco", 0, 0 ); 
    911             bo_add_32be( stco, i_chunk_count ); 
    912  
    913             stsc = box_full_new( "stsc", 0, 0 ); 
    914             bo_add_32be( stsc, i_chunk_count );     // entry-count 
    915             for( i_chunk = 0, i = 0; i < p_stream->i_entry_count; i_chunk++ ) 
    916             { 
    917                 int i_first; 
    918                 bo_add_32be( stco, p_stream->entry[i].i_pos ); 
    919  
    920                 i_first = i; 
    921  
    922                 while( i < p_stream->i_entry_count ) 
    923                 { 
    924                     if( i + 1 < p_stream->i_entry_count && 
    925                         p_stream->entry[i].i_pos + p_stream->entry[i].i_size 
    926                         != p_stream->entry[i + 1].i_pos ) 
    927                     { 
    928                         i++; 
    929                         break; 
    930                     } 
    931  
    932                     i++; 
    933                 } 
    934                 bo_add_32be( stsc, 1 + i_chunk );   // first-chunk 
    935                 bo_add_32be( stsc, i - i_first ) ;  // samples-per-chunk 
    936                 bo_add_32be( stsc, 1 );             // sample-descr-index 
    937             } 
    938             /* append stco to stbl */ 
    939             box_fix( stco ); 
    940             box_gather( stbl, stco ); 
    941  
    942             /* append stsc to stbl */ 
    943             box_fix( stsc ); 
    944             box_gather( stbl, stsc ); 
    945         } 
    946  
    947  
    948         /* add stts */ 
    949         stts = box_full_new( "stts", 0, 0 ); 
    950         bo_add_32be( stts, 0 );     // fixed latter 
    951         for( i = 0, i_index = 0; i < p_stream->i_entry_count; i_index++) 
    952         { 
    953             int64_t i_delta; 
    954             int     i_first; 
    955  
    956             i_first = i; 
    957             i_delta = p_stream->entry[i].i_length; 
    958  
    959             while( i < p_stream->i_entry_count ) 
    960             { 
    961                 if( i + 1 < p_stream->i_entry_count && 
    962                     p_stream->entry[i + 1].i_length != i_delta ) 
    963                 { 
    964                     i++; 
    965                     break; 
    966                 } 
    967  
    968                 i++; 
    969             } 
    970  
    971             bo_add_32be( stts, i - i_first );           // sample-count 
    972             bo_add_32be( stts, i_delta * (int64_t)i_timescale / 
    973                                (int64_t)1000000 );      // sample-delta 
    974         } 
    975         bo_fix_32be( stts, 12, i_index ); 
    976  
    977         /* append stts to stbl */ 
    978         box_fix( stts ); 
    979         box_gather( stbl, stts ); 
    980  
    981         /* FIXME add ctts ?? FIXME */ 
    982  
    983         stsz = box_full_new( "stsz", 0, 0 ); 
    984         bo_add_32be( stsz, 0 );                             // sample-size 
    985         bo_add_32be( stsz, p_stream->i_entry_count );       // sample-count 
    986         for( i = 0; i < p_stream->i_entry_count; i++ ) 
    987         { 
    988             bo_add_32be( stsz, p_stream->entry[i].i_size ); // sample-size 
    989         } 
    990         /* append stsz to stbl */ 
    991         box_fix( stsz ); 
    992         box_gather( stbl, stsz ); 
    993  
    994         /* append stbl to minf */ 
    995         box_fix( stbl ); 
    996         box_gather( minf, stbl ); 
    997  
    998         /* append minf to mdia */ 
    999         box_fix( minf ); 
    1000         box_gather( mdia, minf ); 
    1001  
    1002         /* append mdia to trak */ 
    1003         box_fix( mdia ); 
    1004         box_gather( trak, mdia ); 
    1005  
    1006         /* append trak to moov */ 
    1007         box_fix( trak ); 
    1008         box_gather( moov, trak ); 
    1009     } 
    1010  
    1011     box_fix( moov ); 
     1117            } 
     1118        } 
     1119 
     1120        moov->i_buffer = i_moov_size; 
     1121        i_moov_pos = p_sys->i_mdat_pos; 
     1122        p_sys->b_fast_start = VLC_FALSE; 
     1123    } 
     1124 
     1125    /* Write MOOV header */ 
     1126    sout_AccessOutSeek( p_mux->p_access, i_moov_pos ); 
    10121127    box_send( p_mux, moov ); 
    10131128 
    1014     /* *** release memory *** */ 
     1129    /* Clean-up */ 
    10151130    for( i_trak = 0; i_trak < p_sys->i_nb_streams; i_trak++ ) 
    10161131    { 
    1017         mp4_stream_t *p_stream; 
    1018  
    1019         p_stream = p_sys->pp_streams[i_trak]; 
     1132        mp4_stream_t *p_stream = p_sys->pp_streams[i_trak]; 
    10201133 
    10211134        if( p_stream->p_fmt->p_extra ) 
     
    13971510} 
    13981511 
    1399  
    14001512static sout_buffer_t * bo_to_sout( sout_instance_t *p_sout,  bo_t *box ) 
    14011513{ 
  • src/stream_output/stream_output.c

    r25cd132 r5c2cf08  
    33 ***************************************************************************** 
    44 * Copyright (C) 2002-2004 VideoLAN 
    5  * $Id: stream_output.c,v 1.37 2004/01/06 12:02:06 zorglub Exp $ 
     5 * $Id: stream_output.c,v 1.38 2004/01/23 17:56:14 gbazin Exp $ 
    66 * 
    77 * Authors: Christophe Massiot <massiot@via.ecp.fr> 
     
    239239 
    240240 
    241 int sout_InputSendBuffer( sout_packetizer_input_t *p_input, sout_buffer_t *p_buffer ) 
     241int sout_InputSendBuffer( sout_packetizer_input_t *p_input, 
     242                          sout_buffer_t *p_buffer ) 
    242243{ 
    243244    sout_instance_t     *p_sout = p_input->p_sout; 
     
    273274    } 
    274275 
    275     psz_next = sout_cfg_parser( &p_access->psz_access, &p_access->p_cfg, psz_access ); 
     276    psz_next = sout_cfg_parser( &p_access->psz_access, &p_access->p_cfg, 
     277                                psz_access ); 
    276278    if( psz_next ) 
    277279    { 
     
    282284    p_access->p_sys = NULL; 
    283285    p_access->pf_seek    = NULL; 
     286    p_access->pf_read    = NULL; 
    284287    p_access->pf_write   = NULL; 
    285288 
     
    318321 * sout_AccessSeek: 
    319322 *****************************************************************************/ 
    320 int  sout_AccessOutSeek( sout_access_out_t *p_access, off_t i_pos ) 
    321 
    322     return( p_access->pf_seek( p_access, i_pos ) ); 
     323int sout_AccessOutSeek( sout_access_out_t *p_access, off_t i_pos ) 
     324
     325    return p_access->pf_seek( p_access, i_pos ); 
     326
     327 
     328/***************************************************************************** 
     329 * sout_AccessRead: 
     330 *****************************************************************************/ 
     331int sout_AccessOutRead( sout_access_out_t *p_access, sout_buffer_t *p_buffer ) 
     332
     333    return ( p_access->pf_read ? 
     334             p_access->pf_read( p_access, p_buffer ) : VLC_EGENERIC ); 
    323335} 
    324336 
     
    326338 * sout_AccessWrite: 
    327339 *****************************************************************************/ 
    328 int  sout_AccessOutWrite( sout_access_out_t *p_access, sout_buffer_t *p_buffer ) 
    329 
    330     return( p_access->pf_write( p_access, p_buffer ) ); 
    331 
    332  
     340int sout_AccessOutWrite( sout_access_out_t *p_access, sout_buffer_t *p_buffer ) 
     341
     342    return p_access->pf_write( p_access, p_buffer ); 
     343
    333344 
    334345/*****************************************************************************