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

📄 movenc.c

📁 Trolltech公司发布的图形界面操作系统。可在qt-embedded-2.3.10平台上编译为嵌入式图形界面操作系统。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * MOV, 3GP, MP4 encoder. * Copyright (c) 2003 Thomas Raivio. * Enhancements by Gildas Bazin <gbazin@netcourrier.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#include "avformat.h"#include "avi.h"#include "avio.h"#undef NDEBUG#include <assert.h>#define MOV_INDEX_CLUSTER_SIZE 16384#define globalTimescale 1000typedef struct MOVIentry {    unsigned int flags, pos, size;    unsigned int samplesInChunk;    char         key_frame;    unsigned int entries;} MOVIentry;typedef struct MOVIndex {    int         entry;    int         mdat_size;    int         ents_allocated;    long        timescale;    long        time;    long        trackDuration;    long        sampleCount;    long        sampleDuration;    int         hasKeyframes;    int         trackID;    AVCodecContext *enc;    int         vosLen;    uint8_t     *vosData;    MOVIentry** cluster;} MOVTrack;typedef struct {    long    time;    int     nb_streams;    int     mdat_written;    offset_t mdat_pos;    offset_t movi_list;    long    timescale;    MOVTrack tracks[MAX_STREAMS];} MOVContext;static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack* track);//FIXME supprt 64bit varaint with wide placeholdersstatic int updateSize (ByteIOContext *pb, int pos){    long curpos = url_ftell(pb);    url_fseek(pb, pos, SEEK_SET);    put_be32(pb, curpos - pos); /* rewrite size */    url_fseek(pb, curpos, SEEK_SET);    return curpos - pos;}/* Chunk offset atom */static int mov_write_stco_tag(ByteIOContext *pb, MOVTrack* track){    int i;    int pos = url_ftell(pb);    put_be32(pb, 0); /* size */    put_tag(pb, "stco");    put_be32(pb, 0); /* version & flags */    put_be32(pb, track->entry); /* entry count */    for (i=0; i<track->entry; i++) {        int cl = i / MOV_INDEX_CLUSTER_SIZE;        int id = i % MOV_INDEX_CLUSTER_SIZE;        put_be32(pb, track->cluster[cl][id].pos);    }    return updateSize (pb, pos);}/* Sample size atom */static int mov_write_stsz_tag(ByteIOContext *pb, MOVTrack* track){    int equalChunks = 1;    int i, j, entries = 0, tst = -1, oldtst = -1;    int pos = url_ftell(pb);    put_be32(pb, 0); /* size */    put_tag(pb, "stsz");    put_be32(pb, 0); /* version & flags */    for (i=0; i<track->entry; i++) {        int cl = i / MOV_INDEX_CLUSTER_SIZE;        int id = i % MOV_INDEX_CLUSTER_SIZE;        tst = track->cluster[cl][id].size/track->cluster[cl][id].entries;        if(oldtst != -1 && tst != oldtst) {            equalChunks = 0;        }        oldtst = tst;        entries += track->cluster[cl][id].entries;    }    if (equalChunks) {        int sSize = track->cluster[0][0].size/track->cluster[0][0].entries;        put_be32(pb, sSize); // sample size         put_be32(pb, entries); // sample count    }    else {        put_be32(pb, 0); // sample size         put_be32(pb, entries); // sample count         for (i=0; i<track->entry; i++) {            int cl = i / MOV_INDEX_CLUSTER_SIZE;            int id = i % MOV_INDEX_CLUSTER_SIZE;            for ( j=0; j<track->cluster[cl][id].entries; j++) {                put_be32(pb, track->cluster[cl][id].size /                         track->cluster[cl][id].entries);            }        }    }    return updateSize (pb, pos);}/* Sample to chunk atom */static int mov_write_stsc_tag(ByteIOContext *pb, MOVTrack* track){    int index = 0, oldval = -1, i, entryPos, curpos;    int pos = url_ftell(pb);    put_be32(pb, 0); /* size */    put_tag(pb, "stsc");    put_be32(pb, 0); // version & flags     entryPos = url_ftell(pb);    put_be32(pb, track->entry); // entry count     for (i=0; i<track->entry; i++) {        int cl = i / MOV_INDEX_CLUSTER_SIZE;        int id = i % MOV_INDEX_CLUSTER_SIZE;        if(oldval != track->cluster[cl][id].samplesInChunk)        {            put_be32(pb, i+1); // first chunk             put_be32(pb, track->cluster[cl][id].samplesInChunk); // samples per chunk            put_be32(pb, 0x1); // sample description index             oldval = track->cluster[cl][id].samplesInChunk;            index++;        }    }    curpos = url_ftell(pb);    url_fseek(pb, entryPos, SEEK_SET);    put_be32(pb, index); // rewrite size     url_fseek(pb, curpos, SEEK_SET);    return updateSize (pb, pos);}/* Sync sample atom */static int mov_write_stss_tag(ByteIOContext *pb, MOVTrack* track){    long curpos;    int i, index = 0, entryPos;    int pos = url_ftell(pb);    put_be32(pb, 0); // size     put_tag(pb, "stss");    put_be32(pb, 0); // version & flags     entryPos = url_ftell(pb);    put_be32(pb, track->entry); // entry count     for (i=0; i<track->entry; i++) {        int cl = i / MOV_INDEX_CLUSTER_SIZE;        int id = i % MOV_INDEX_CLUSTER_SIZE;        if(track->cluster[cl][id].key_frame == 1) {            put_be32(pb, i+1);            index++;        }    }    curpos = url_ftell(pb);    url_fseek(pb, entryPos, SEEK_SET);    put_be32(pb, index); // rewrite size     url_fseek(pb, curpos, SEEK_SET);    return updateSize (pb, pos);}static int mov_write_damr_tag(ByteIOContext *pb){    put_be32(pb, 0x11); /* size */    put_tag(pb, "damr");    put_tag(pb, "FFMP");    put_byte(pb, 0);    put_be16(pb, 0x80); /* Mode set (all modes for AMR_NB) */    put_be16(pb, 0xa); /* Mode change period (no restriction) */    //put_be16(pb, 0x81ff); /* Mode set (all modes for AMR_NB) */    //put_be16(pb, 1); /* Mode change period (no restriction) */    return 0x11;}static int mov_write_audio_tag(ByteIOContext *pb, MOVTrack* track){    int pos = url_ftell(pb);    put_be32(pb, 0); /* size */    if(track->enc->codec_id == CODEC_ID_PCM_MULAW)      put_tag(pb, "ulaw");    else if(track->enc->codec_id == CODEC_ID_PCM_ALAW)      put_tag(pb, "alaw");    else if(track->enc->codec_id == CODEC_ID_ADPCM_IMA_QT)      put_tag(pb, "ima4");    else if(track->enc->codec_id == CODEC_ID_MACE3)      put_tag(pb, "MAC3");    else if(track->enc->codec_id == CODEC_ID_MACE6)      put_tag(pb, "MAC6");    else if(track->enc->codec_id == CODEC_ID_AAC)      put_tag(pb, "mp4a");    else if(track->enc->codec_id == CODEC_ID_AMR_NB)      put_tag(pb, "samr");    else      put_tag(pb, "    ");    put_be32(pb, 0); /* Reserved */    put_be16(pb, 0); /* Reserved */    put_be16(pb, 1); /* Data-reference index, XXX  == 1 */    /* SoundDescription */    put_be16(pb, 0); /* Version */    put_be16(pb, 0); /* Revision level */    put_be32(pb, 0); /* Reserved */    put_be16(pb, track->enc->channels); /* Number of channels */    /* TODO: Currently hard-coded to 16-bit, there doesn't seem                 to be a good way to get number of bits of audio */    put_be16(pb, 0x10); /* Reserved */    put_be16(pb, 0); /* compression ID (= 0) */    put_be16(pb, 0); /* packet size (= 0) */    put_be16(pb, track->timescale); /* Time scale */    put_be16(pb, 0); /* Reserved */    if(track->enc->codec_id == CODEC_ID_AAC)        mov_write_esds_tag(pb, track);    if(track->enc->codec_id == CODEC_ID_AMR_NB)        mov_write_damr_tag(pb);    return updateSize (pb, pos);}static int mov_write_d263_tag(ByteIOContext *pb){    put_be32(pb, 0xf); /* size */    put_tag(pb, "d263");    put_tag(pb, "FFMP");    put_be16(pb, 0x0a);    put_byte(pb, 0);    return 0xf;}/* TODO: No idea about these values */static int mov_write_svq3_tag(ByteIOContext *pb){    put_be32(pb, 0x15);    put_tag(pb, "SMI ");    put_tag(pb, "SEQH");    put_be32(pb, 0x5);    put_be32(pb, 0xe2c0211d);    put_be32(pb, 0xc0000000);    put_byte(pb, 0);       return 0x15;}static unsigned int descrLength(unsigned int len){    if (len < 0x00000080)        return 2 + len;    else if (len < 0x00004000)        return 3 + len;    else if(len < 0x00200000)        return 4 + len;    else        return 5 + len;}static void putDescr(ByteIOContext *pb, int tag, int size){    uint32_t len;    uint8_t  vals[4];    len = size;    vals[3] = (uint8_t)(len & 0x7f);    len >>= 7;    vals[2] = (uint8_t)((len & 0x7f) | 0x80);     len >>= 7;    vals[1] = (uint8_t)((len & 0x7f) | 0x80);     len >>= 7;    vals[0] = (uint8_t)((len & 0x7f) | 0x80);    put_byte(pb, tag); // DescriptorTag    if (size < 0x00000080)    {        put_byte(pb, vals[3]);    }    else if (size < 0x00004000)    {        put_byte(pb, vals[2]);        put_byte(pb, vals[3]);    }    else if (size < 0x00200000)    {        put_byte(pb, vals[1]);        put_byte(pb, vals[2]);        put_byte(pb, vals[3]);    }    else if (size < 0x10000000)    {        put_byte(pb, vals[0]);        put_byte(pb, vals[1]);        put_byte(pb, vals[2]);        put_byte(pb, vals[3]);    }}static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack* track) // Basic{    int decoderSpecificInfoLen = track->vosLen ? descrLength(track->vosLen):0;    int pos = url_ftell(pb);    put_be32(pb, 0);               // size    put_tag(pb, "esds");    put_be32(pb, 0);               // Version    // ES descriptor    putDescr(pb, 0x03, 3 + descrLength(13 + decoderSpecificInfoLen) +             descrLength(1));    put_be16(pb, 0x0001);          // ID (= 1)    put_byte(pb, 0x00);            // flags (= no flags)    // DecoderConfig descriptor    putDescr(pb, 0x04, 13 + decoderSpecificInfoLen);    if(track->enc->codec_id == CODEC_ID_AAC)        put_byte(pb, 0x40);        // Object type indication    else if(track->enc->codec_id == CODEC_ID_MPEG4)        put_byte(pb, 0x20);        // Object type indication (Visual 14496-2)    if(track->enc->codec_type == CODEC_TYPE_AUDIO)        put_byte(pb, 0x15);            // flags (= Audiostream)    else        put_byte(pb, 0x11);            // flags (= Visualstream)    put_byte(pb, 0x0);             // Buffersize DB (24 bits)    put_be16(pb, 0x0dd2);          // Buffersize DB    // TODO: find real values for these    put_be32(pb, 0x0002e918);     // maxbitrate    put_be32(pb, 0x00017e6b);     // avg bitrate    if (track->vosLen)    {        // DecoderSpecific info descriptor        putDescr(pb, 0x05, track->vosLen);        put_buffer(pb, track->vosData, track->vosLen);    }    // SL descriptor    putDescr(pb, 0x06, descrLength(1));    put_byte(pb, 0x02);    return updateSize (pb, pos);}static int mov_write_video_tag(ByteIOContext *pb, MOVTrack* track){    int pos = url_ftell(pb);    put_be32(pb, 0); /* size */    if(track->enc->codec_id == CODEC_ID_SVQ1)      put_tag(pb, "SVQ1");    else if(track->enc->codec_id == CODEC_ID_SVQ3)      put_tag(pb, "SVQ3");    else if(track->enc->codec_id == CODEC_ID_MPEG4)      put_tag(pb, "mp4v");    else if(track->enc->codec_id == CODEC_ID_H263)      put_tag(pb, "s263");    else      put_tag(pb, "    "); /* Unknown tag */    put_be32(pb, 0); /* Reserved */    put_be16(pb, 0); /* Reserved */    put_be16(pb, 1); /* Data-reference index */    put_be32(pb, 0); /* Reserved (= 02000c) */    put_be32(pb, 0); /* Reserved ("SVis")*/    put_be32(pb, 0); /* Reserved */    put_be32(pb, 0); /* Reserved (400)*/    put_be16(pb, track->enc->width); /* Video width */    put_be16(pb, track->enc->height); /* Video height */    put_be32(pb, 0x00480000); /* Reserved */    put_be32(pb, 0x00480000); /* Reserved */    put_be32(pb, 0); /* Reserved */    put_be32(pb, 0); /* Reserved */    put_be32(pb, 0); /* Reserved */    put_be32(pb, 0); /* Reserved */    put_be32(pb, 0); /* Reserved */    put_be32(pb, 0); /* Reserved */    put_be16(pb, 0); /* Reserved */    put_be32(pb, 0); /* Reserved */    put_be32(pb, 0); /* Reserved */    put_be32(pb, 0); /* Reserved */    put_be16(pb, 0x18); /* Reserved */    put_be16(pb, 0xffff); /* Reserved */    if(track->enc->codec_id == CODEC_ID_MPEG4)        mov_write_esds_tag(pb, track);    else if(track->enc->codec_id == CODEC_ID_H263)        mov_write_d263_tag(pb);    else if(track->enc->codec_id == CODEC_ID_SVQ3)        mov_write_svq3_tag(pb);        return updateSize (pb, pos);}static int mov_write_stsd_tag(ByteIOContext *pb, MOVTrack* track){    int pos = url_ftell(pb);    put_be32(pb, 0); /* size */    put_tag(pb, "stsd");    put_be32(pb, 0); /* version & flags */    put_be32(pb, 1); /* entry count */    if (track->enc->codec_type == CODEC_TYPE_VIDEO)        mov_write_video_tag(pb, track);    else if (track->enc->codec_type == CODEC_TYPE_AUDIO)        mov_write_audio_tag(pb, track);    return updateSize(pb, pos);}/* TODO?: Currently all samples/frames seem to have same duration *//* Time to sample atom */static int mov_write_stts_tag(ByteIOContext *pb, MOVTrack* track){    put_be32(pb, 0x18); /* size */    put_tag(pb, "stts");    put_be32(pb, 0); /* version & flags */    put_be32(pb, 1); /* entry count */    put_be32(pb, track->sampleCount); /* sample count */    put_be32(pb, track->sampleDuration); /* sample duration */    return 0x18;}static int mov_write_dref_tag(ByteIOContext *pb){    put_be32(pb, 28); /* size */    put_tag(pb, "dref");    put_be32(pb, 0); /* version & flags */    put_be32(pb, 1); /* entry count */    put_be32(pb, 0xc); /* size */    put_tag(pb, "url ");    put_be32(pb, 1); /* version & flags */    return 28;}static int mov_write_stbl_tag(ByteIOContext *pb, MOVTrack* track){    int pos = url_ftell(pb);    put_be32(pb, 0); /* size */    put_tag(pb, "stbl");    mov_write_stsd_tag(pb, track);    mov_write_stts_tag(pb, track);    if (track->enc->codec_type == CODEC_TYPE_VIDEO &&

⌨️ 快捷键说明

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