⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mp4.c

📁 这不是一个完整的工程
💻 C
📖 第 1 页 / 共 3 页
字号:
/***************************************************************************** * mp4.c ***************************************************************************** * Copyright (C) 2001, 2002, 2003 VideoLAN * $Id: mp4.c,v 1.3 2003/08/01 20:06:43 gbazin Exp $ * * Authors: Laurent Aimar <fenrir@via.ecp.fr> * * 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 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#include <stdlib.h>#include <string.h>#include <errno.h>#include <vlc/vlc.h>#include <vlc/input.h>#include <vlc/sout.h>#ifdef HAVE_TIME_H#include <time.h>#endif#include "codecs.h"/***************************************************************************** * Exported prototypes *****************************************************************************/static int     Open   ( vlc_object_t * );static void    Close  ( vlc_object_t * );static int Capability(sout_mux_t *, int, void *, void * );static int AddStream( sout_mux_t *, sout_input_t * );static int DelStream( sout_mux_t *, sout_input_t * );static int Mux      ( sout_mux_t * );/***************************************************************************** * Module descriptor *****************************************************************************/vlc_module_begin();    set_description( _("MP4/MOV muxer") );    set_capability( "sout mux", 5 );    add_shortcut( "mp4" );    add_shortcut( "mov" );    set_callbacks( Open, Close );vlc_module_end();typedef struct{    uint64_t i_pos;    int      i_size;    mtime_t  i_pts;    mtime_t  i_dts;    mtime_t  i_length;} mp4_entry_t;typedef struct{    sout_format_t *p_fmt;    int           i_track_id;    /* index */    unsigned int i_entry_count;    unsigned int i_entry_max;    mp4_entry_t  *entry;    /* stats */    mtime_t      i_duration;} mp4_stream_t;struct sout_mux_sys_t{    vlc_bool_t b_mov;    uint64_t i_mdat_pos;    uint64_t i_pos;    int          i_nb_streams;    mp4_stream_t **pp_streams;};typedef struct bo_t bo_t;struct bo_t{    vlc_bool_t b_grow;    int        i_buffer_size;    int        i_buffer;    uint8_t    *p_buffer;};static void bo_init     ( bo_t *, int , uint8_t *, vlc_bool_t  );static void bo_add_8    ( bo_t *, uint8_t );static void bo_add_16be ( bo_t *, uint16_t );static void bo_add_24be ( bo_t *, uint32_t );static void bo_add_32be ( bo_t *, uint32_t );static void bo_add_64be ( bo_t *, uint64_t );static void bo_add_fourcc(bo_t *, char * );static void bo_add_bo   ( bo_t *, bo_t * );static void bo_add_mem  ( bo_t *, int , uint8_t * );static void bo_fix_32be ( bo_t *, int , uint32_t );static bo_t *box_new     ( char *fcc );static bo_t *box_full_new( char *fcc, uint8_t v, uint32_t f );static void  box_fix     ( bo_t *box );static void  box_free    ( bo_t *box );static void  box_gather  ( bo_t *box, bo_t *box2 );static void box_send( sout_mux_t *p_mux,  bo_t *box );static int64_t get_timestamp();static sout_buffer_t * bo_to_sout( sout_instance_t *p_sout,  bo_t *box );/***************************************************************************** * Open: *****************************************************************************/static int Open( vlc_object_t *p_this ){    sout_mux_t      *p_mux = (sout_mux_t*)p_this;    sout_mux_sys_t  *p_sys;    bo_t            *box;    p_sys = malloc( sizeof( sout_mux_sys_t ) );    p_sys->i_pos        = 0;    p_sys->i_nb_streams = 0;    p_sys->pp_streams   = NULL;    p_sys->i_mdat_pos   = 0;    p_sys->b_mov        = p_mux->psz_mux && !strcmp( p_mux->psz_mux, "mov" );    msg_Info( p_mux, "Open" );    p_mux->pf_capacity  = Capability;    p_mux->pf_addstream = AddStream;    p_mux->pf_delstream = DelStream;    p_mux->pf_mux       = Mux;    p_mux->p_sys        = p_sys;    if( !p_sys->b_mov )    {        /* Now add ftyp header */        box = box_new( "ftyp" );        bo_add_fourcc( box, "isom" );        bo_add_32be  ( box, 0 );        bo_add_fourcc( box, "mp41" );        box_fix( box );        p_sys->i_pos += box->i_buffer;        p_sys->i_mdat_pos = p_sys->i_pos;        box_send( p_mux, box );    }    /* Now add mdat header */    box = box_new( "mdat" );    bo_add_64be  ( box, 0 ); // enough to store an extended size    p_sys->i_pos += box->i_buffer;    box_send( p_mux, box );    return VLC_SUCCESS;}static uint32_t GetDescriptorLength24b( int i_length ){    uint32_t    i_l1, i_l2, i_l3;    i_l1 = i_length&0x7f;    i_l2 = ( i_length >> 7 )&0x7f;    i_l3 = ( i_length >> 14 )&0x7f;    return( 0x808000 | ( i_l3 << 16 ) | ( i_l2 << 8 ) | i_l1 );}static bo_t *GetESDS( mp4_stream_t *p_stream ){    bo_t *esds;    int  i_stream_type;    int  i_object_type_indication;    int  i_decoder_specific_info_size;    if( p_stream->p_fmt->i_extra_data > 0 )    {        i_decoder_specific_info_size = p_stream->p_fmt->i_extra_data + 4;    }    else    {        i_decoder_specific_info_size = 0;    }    esds = box_full_new( "esds", 0, 0 );    bo_add_8   ( esds, 0x03 );      // ES_DescrTag    bo_add_24be( esds,                 GetDescriptorLength24b( 25 + i_decoder_specific_info_size ) );    bo_add_16be( esds, p_stream->i_track_id );    bo_add_8   ( esds, 0x1f );      // flags=0|streamPriority=0x1f    bo_add_8   ( esds, 0x04 );      // DecoderConfigDescrTag    bo_add_24be( esds,                 GetDescriptorLength24b( 13 + i_decoder_specific_info_size ) );    switch( p_stream->p_fmt->i_fourcc )    {        case VLC_FOURCC( 'm', 'p', '4', 'v' ):            i_object_type_indication = 0x20;            break;        case VLC_FOURCC( 'm', 'p', 'g', 'v' ):            /* FIXME MPEG-I=0x6b, MPEG-II = 0x60 -> 0x65 */            i_object_type_indication = 0x60;            break;        case VLC_FOURCC( 'm', 'p', '4', 'a' ):            /* FIXME for mpeg2-aac == 0x66->0x68 */            i_object_type_indication = 0x40;            break;        case VLC_FOURCC( 'm', 'p', 'g', 'a' ):            i_object_type_indication =                p_stream->p_fmt->i_sample_rate < 32000 ? 0x69 : 0x6b;            break;        default:            i_object_type_indication = 0x00;            break;    }    i_stream_type = p_stream->p_fmt->i_cat == VIDEO_ES ? 0x04 : 0x05;    bo_add_8   ( esds, i_object_type_indication );    bo_add_8   ( esds, ( i_stream_type << 2 ) | 1 );    bo_add_24be( esds, 1024 * 1024 );       // bufferSizeDB    bo_add_32be( esds, 0x7fffffff );        // maxBitrate    bo_add_32be( esds, 0 );                 // avgBitrate    if( p_stream->p_fmt->i_extra_data > 0 )    {        int i;        bo_add_8   ( esds, 0x05 );  // DecoderSpecificInfo        bo_add_24be( esds,                     GetDescriptorLength24b( p_stream->p_fmt->i_extra_data ) );        for( i = 0; i < p_stream->p_fmt->i_extra_data; i++ )        {            bo_add_8( esds, p_stream->p_fmt->p_extra_data[i] );        }    }    /* SL_Descr mandatory */    bo_add_8   ( esds, 0x06 );  // SLConfigDescriptorTag    bo_add_24be( esds, GetDescriptorLength24b( 1 ) );    bo_add_8   ( esds, 0x02 );  // sl_predefined    box_fix( esds );    return esds;}/***************************************************************************** * Close: *****************************************************************************/static uint32_t mvhd_matrix[9] =    { 0x10000, 0, 0, 0, 0x10000, 0, 0, 0, 0x40000000 };static void Close( vlc_object_t * p_this ){    sout_mux_t *p_mux = (sout_mux_t*)p_this;    sout_mux_sys_t  *p_sys = p_mux->p_sys;    sout_buffer_t   *p_hdr;    bo_t            bo;    bo_t            *moov, *mvhd;    unsigned int    i;    int             i_trak, i_index;    uint32_t        i_movie_timescale = 90000;    int64_t         i_movie_duration  = 0;    msg_Info( p_mux, "Close" );    /* create general info */    for( i_trak = 0; i_trak < p_sys->i_nb_streams; i_trak++ )    {        mp4_stream_t *p_stream;        p_stream = p_sys->pp_streams[i_trak];        i_movie_duration = __MAX( i_movie_duration, p_stream->i_duration );    }    msg_Dbg( p_mux, "movie duration %ds",             (uint32_t)( i_movie_duration / (mtime_t)1000000 ) );    i_movie_duration = i_movie_duration *                       (int64_t)i_movie_timescale / (int64_t)1000000;    /* *** update mdat size *** */    bo_init      ( &bo, 0, NULL, VLC_TRUE );    if( p_sys->i_pos - p_sys->i_mdat_pos >= (((uint64_t)1)<<32) )    {        /* Extended size */        bo_add_32be  ( &bo, 1 );        bo_add_fourcc( &bo, "mdat" );        bo_add_64be  ( &bo, p_sys->i_pos - p_sys->i_mdat_pos );    }    else    {        bo_add_32be  ( &bo, 8 );        bo_add_fourcc( &bo, "wide" );        bo_add_32be  ( &bo, p_sys->i_pos - p_sys->i_mdat_pos - 8 );        bo_add_fourcc( &bo, "mdat" );    }    p_hdr = bo_to_sout( p_mux->p_sout, &bo );    free( bo.p_buffer );    /* seek to mdat */    sout_AccessOutSeek( p_mux->p_access, p_sys->i_mdat_pos );    sout_AccessOutWrite( p_mux->p_access, p_hdr );    /* Now create header */    sout_AccessOutSeek( p_mux->p_access, p_sys->i_pos );    moov = box_new( "moov" );    /* *** add /moov/mvhd *** */    if( p_sys->b_mov )    {        mvhd = box_full_new( "mvhd", 0, 0 );        bo_add_32be( mvhd, get_timestamp() );   // creation time        bo_add_32be( mvhd, get_timestamp() );   // modification time        bo_add_32be( mvhd, i_movie_timescale);  // timescale        bo_add_32be( mvhd, i_movie_duration );  // duration    }    else    {        mvhd = box_full_new( "mvhd", 1, 0 );        bo_add_64be( mvhd, get_timestamp() );   // creation time        bo_add_64be( mvhd, get_timestamp() );   // modification time        bo_add_32be( mvhd, i_movie_timescale);  // timescale        bo_add_64be( mvhd, i_movie_duration );  // duration    }    bo_add_32be( mvhd, 0x10000 );           // rate    bo_add_16be( mvhd, 0x100 );             // volume    bo_add_16be( mvhd, 0 );                 // reserved    for( i = 0; i < 2; i++ )    {        bo_add_32be( mvhd, 0 );             // reserved    }    for( i = 0; i < 9; i++ )    {        bo_add_32be( mvhd, mvhd_matrix[i] );// matrix    }    for( i = 0; i < 6; i++ )    {        bo_add_32be( mvhd, 0 );             // pre-defined    }    /* Find the 1st track id */    for( i_trak = 0; i_trak < p_sys->i_nb_streams; i_trak++ )    {        mp4_stream_t *p_stream = p_sys->pp_streams[i_trak];        if( p_stream->p_fmt->i_cat == AUDIO_ES ||            p_stream->p_fmt->i_cat == VIDEO_ES )        {            /* Found it */            bo_add_32be( mvhd, p_stream->i_track_id ); // next-track-id            break;        }    }    if( i_trak == p_sys->i_nb_streams ) /* Just for sanity reasons */        bo_add_32be( mvhd, 0xffffffff );    box_fix( mvhd );    box_gather( moov, mvhd );    for( i_trak = 0; i_trak < p_sys->i_nb_streams; i_trak++ )    {        mp4_stream_t *p_stream;        uint32_t     i_timescale;        uint32_t     i_chunk_count;        bo_t *trak;        bo_t *tkhd;        bo_t *mdia;        bo_t *mdhd, *hdlr;        bo_t *minf;        bo_t *dinf;        bo_t *dref;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -