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

📄 mp4.c

📁 uclinux 下的vlc播放器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/***************************************************************************** * mp4.c: mp4/mov muxer ***************************************************************************** * Copyright (C) 2001, 2002, 2003, 2006 the VideoLAN team * $Id: mp4.c 16767 2006-09-21 14:32:45Z hartman $ * * Authors: Laurent Aimar <fenrir@via.ecp.fr> *          Gildas Bazin <gbazin at videolan dot org> * * 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#include <stdlib.h>#include <string.h>#include <vlc/vlc.h>#include <vlc/input.h>#include <vlc/sout.h>#ifdef HAVE_TIME_H#include <time.h>#endif#include "iso_lang.h"#include "vlc_meta.h"/***************************************************************************** * Module descriptor *****************************************************************************/#define FASTSTART_TEXT N_("Create \"Fast Start\" files")#define FASTSTART_LONGTEXT N_( \    "Create \"Fast Start\" files. " \    "\"Fast Start\" files are optimized for downloads and allow the user " \    "to start previewing the file while it is downloading.")static int  Open   ( vlc_object_t * );static void Close  ( vlc_object_t * );#define SOUT_CFG_PREFIX "sout-mp4-"vlc_module_begin();    set_description( _("MP4/MOV muxer") );    set_category( CAT_SOUT );    set_subcategory( SUBCAT_SOUT_MUX );    set_shortname( "MP4" );    add_bool( SOUT_CFG_PREFIX "faststart", 1, NULL,              FASTSTART_TEXT, FASTSTART_LONGTEXT,              VLC_TRUE );    set_capability( "sout mux", 5 );    add_shortcut( "mp4" );    add_shortcut( "mov" );    add_shortcut( "3gp" );    set_callbacks( Open, Close );vlc_module_end();/***************************************************************************** * Exported prototypes *****************************************************************************/static const char *ppsz_sout_options[] = {    "faststart", NULL};static int Control( sout_mux_t *, int, va_list );static int AddStream( sout_mux_t *, sout_input_t * );static int DelStream( sout_mux_t *, sout_input_t * );static int Mux      ( sout_mux_t * );/***************************************************************************** * Local prototypes *****************************************************************************/typedef struct{    uint64_t i_pos;    int      i_size;    mtime_t  i_pts_dts;    mtime_t  i_length;    unsigned int i_flags;} mp4_entry_t;typedef struct{    es_format_t   fmt;    int           i_track_id;    /* index */    unsigned int i_entry_count;    unsigned int i_entry_max;    mp4_entry_t  *entry;    int64_t      i_length_neg;    /* stats */    int64_t      i_dts_start;    int64_t      i_duration;    /* for later stco fix-up (fast start files) */    uint64_t i_stco_pos;    vlc_bool_t b_stco64;    /* for h264 */    struct    {        int     i_profile;        int     i_profile_compat;        int     i_level;        int     i_sps;        uint8_t *sps;        int     i_pps;        uint8_t *pps;    } avc;    /* for spu */    int64_t i_last_dts;} mp4_stream_t;struct sout_mux_sys_t{    vlc_bool_t b_mov;    vlc_bool_t b_3gp;    vlc_bool_t b_64_ext;    vlc_bool_t b_fast_start;    uint64_t i_mdat_pos;    uint64_t i_pos;    int64_t  i_dts_start;    int          i_nb_streams;    mp4_stream_t **pp_streams;};typedef struct bo_t{    vlc_bool_t b_grow;    int        i_buffer_size;    int        i_buffer;    uint8_t    *p_buffer;} bo_t;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_add_descr( bo_t *, uint8_t , uint32_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 block_t *bo_to_sout( sout_instance_t *p_sout,  bo_t *box );static bo_t *GetMoovBox( sout_mux_t *p_mux );static block_t *ConvertSUBT( sout_mux_t *, mp4_stream_t *, block_t *);static void ConvertAVC1( sout_mux_t *, mp4_stream_t *, block_t * );/***************************************************************************** * 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;    msg_Dbg( p_mux, "Mp4 muxer opend" );    sout_CfgParse( p_mux, SOUT_CFG_PREFIX, ppsz_sout_options, p_mux->p_cfg );    p_mux->pf_control   = Control;    p_mux->pf_addstream = AddStream;    p_mux->pf_delstream = DelStream;    p_mux->pf_mux       = Mux;    p_mux->p_sys        = 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" );    p_sys->b_3gp        = p_mux->psz_mux && !strcmp( p_mux->psz_mux, "3gp" );    p_sys->i_dts_start  = 0;    if( !p_sys->b_mov )    {        /* Now add ftyp header */        box = box_new( "ftyp" );        if( p_sys->b_3gp ) bo_add_fourcc( box, "3gp4" );        else bo_add_fourcc( box, "isom" );        bo_add_32be  ( box, 0 );        if( p_sys->b_3gp ) bo_add_fourcc( box, "3gp4" );        else 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 );    }    /* FIXME FIXME     * Quicktime actually doesn't like the 64 bits extensions !!! */    p_sys->b_64_ext = VLC_FALSE;    /* 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;}/***************************************************************************** * Close: *****************************************************************************/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;    block_t   *p_hdr;    bo_t            bo, *moov;    vlc_value_t     val;    int             i_trak;    uint64_t        i_moov_pos;    msg_Dbg( p_mux, "Close" );    /* 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 );    sout_AccessOutSeek( p_mux->p_access, p_sys->i_mdat_pos );    sout_AccessOutWrite( p_mux->p_access, p_hdr );    /* Create MOOV header */    i_moov_pos = p_sys->i_pos;    moov = GetMoovBox( p_mux );    /* Check we need to create "fast start" files */    var_Get( p_this, SOUT_CFG_PREFIX "faststart", &val );    p_sys->b_fast_start = val.b_bool;    while( p_sys->b_fast_start )    {        /* Move data to the end of the file so we can fit the moov header         * at the start */        block_t *p_buf;        int64_t i_chunk, i_size = p_sys->i_pos - p_sys->i_mdat_pos;        int i_moov_size = moov->i_buffer;        while( i_size > 0 )        {            i_chunk = __MIN( 32768, i_size );            p_buf = block_New( p_mux, i_chunk );            sout_AccessOutSeek( p_mux->p_access,                                p_sys->i_mdat_pos + i_size - i_chunk );            if( sout_AccessOutRead( p_mux->p_access, p_buf ) < i_chunk )            {                msg_Warn( p_this, "read() not supported by access output, "                          "won't create a fast start file" );                p_sys->b_fast_start = VLC_FALSE;                block_Release( p_buf );                break;            }            sout_AccessOutSeek( p_mux->p_access, p_sys->i_mdat_pos + i_size +                                i_moov_size - i_chunk );            sout_AccessOutWrite( p_mux->p_access, p_buf );            i_size -= i_chunk;        }        if( !p_sys->b_fast_start ) break;        /* Fix-up samples to chunks table in MOOV header */        for( i_trak = 0; i_trak < p_sys->i_nb_streams; i_trak++ )        {            mp4_stream_t *p_stream = p_sys->pp_streams[i_trak];            unsigned int i;            int i_chunk;            moov->i_buffer = p_stream->i_stco_pos;            for( i_chunk = 0, i = 0; i < p_stream->i_entry_count; i_chunk++ )            {                if( p_stream->b_stco64 )                    bo_add_64be( moov, p_stream->entry[i].i_pos + i_moov_size);                else                    bo_add_32be( moov, p_stream->entry[i].i_pos + i_moov_size);                while( i < p_stream->i_entry_count )                {                    if( i + 1 < p_stream->i_entry_count &&                        p_stream->entry[i].i_pos + p_stream->entry[i].i_size                        != p_stream->entry[i + 1].i_pos )                    {                        i++;                        break;                    }                    i++;                }            }        }        moov->i_buffer = i_moov_size;        i_moov_pos = p_sys->i_mdat_pos;        p_sys->b_fast_start = VLC_FALSE;    }    /* Write MOOV header */    sout_AccessOutSeek( p_mux->p_access, i_moov_pos );    box_send( p_mux, moov );    /* Clean-up */    for( i_trak = 0; i_trak < p_sys->i_nb_streams; i_trak++ )    {        mp4_stream_t *p_stream = p_sys->pp_streams[i_trak];        es_format_Clean( &p_stream->fmt );        if( p_stream->avc.i_sps ) free( p_stream->avc.sps );        if( p_stream->avc.i_pps ) free( p_stream->avc.pps );        free( p_stream->entry );        free( p_stream );    }    if( p_sys->i_nb_streams ) free( p_sys->pp_streams );    free( p_sys );}/***************************************************************************** * Control: *****************************************************************************/static int Control( sout_mux_t *p_mux, int i_query, va_list args ){    vlc_bool_t *pb_bool;   switch( i_query )   {       case MUX_CAN_ADD_STREAM_WHILE_MUXING:           pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t * );           *pb_bool = VLC_FALSE;           return VLC_SUCCESS;       case MUX_GET_ADD_STREAM_WAIT:           pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t * );           *pb_bool = VLC_TRUE;           return VLC_SUCCESS;       case MUX_GET_MIME:   /* Not needed, as not streamable */        default:            return VLC_EGENERIC;   }}/***************************************************************************** * AddStream: *****************************************************************************/static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input ){    sout_mux_sys_t  *p_sys = p_mux->p_sys;    mp4_stream_t    *p_stream;    switch( p_input->p_fmt->i_codec )    {        case VLC_FOURCC( 'm', 'p', '4', 'a' ):        case VLC_FOURCC( 'm', 'p', '4', 'v' ):        case VLC_FOURCC( 'm', 'p', 'g', 'a' ):        case VLC_FOURCC( 'm', 'p', 'g', 'v' ):        case VLC_FOURCC( 'M', 'J', 'P', 'G' ):        case VLC_FOURCC( 'm', 'j', 'p', 'b' ):        case VLC_FOURCC( 'S', 'V', 'Q', '1' ):        case VLC_FOURCC( 'S', 'V', 'Q', '3' ):        case VLC_FOURCC( 'H', '2', '6', '3' ):        case VLC_FOURCC( 'h', '2', '6', '4' ):        case VLC_FOURCC( 's', 'a', 'm', 'r' ):        case VLC_FOURCC( 's', 'a', 'w', 'b' ):            break;        case VLC_FOURCC( 's', 'u', 'b', 't' ):            msg_Warn( p_mux, "subtitle track added like in .mov (even when creating .mp4)" );            break;        default:            msg_Err( p_mux, "unsupported codec %4.4s in mp4",                     (char*)&p_input->p_fmt->i_codec );            return VLC_EGENERIC;    }

⌨️ 快捷键说明

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