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

📄 movenc.c

📁 现在关于h.264的源码很多
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * MOV, 3GP, MP4 encoder. * Copyright (c) 2003 Thomas Raivio. * Copyright (c) 2004 Gildas Bazin <gbazin at videolan dot org>. * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */#include "avformat.h"#include "avi.h"#include "avio.h"#include "mov.h"#undef NDEBUG#include <assert.h>#define MOV_INDEX_CLUSTER_SIZE 16384#define globalTimescale 1000#define MODE_MP4 0#define MODE_MOV 1#define MODE_3GP 2#define MODE_PSP 3 // example working PSP command line:// ffmpeg -i testinput.avi  -f psp -r 14.985 -s 320x240 -b 768 -ar 24000 -ab 32 M4V00001.MP4#define MODE_3G2 4typedef struct MOVIentry {    unsigned int flags, size;    uint64_t     pos;    unsigned int samplesInChunk;    char         key_frame;    unsigned int entries;    int64_t      cts;} MOVIentry;typedef struct MOVIndex {    int         mode;    int         entry;    uint64_t    mdat_size;    int         ents_allocated;    long        timescale;    long        time;    int64_t     trackDuration;    long        sampleCount;    long        sampleDuration;    int         hasKeyframes;    int         hasBframes;    int         language;    int         trackID;    AVCodecContext *enc;    int         vosLen;    uint8_t     *vosData;    MOVIentry** cluster;} MOVTrack;typedef struct MOVContext {    int     mode;    int64_t time;    int     nb_streams;    int     mdat_written;    offset_t mdat_pos;    long    timescale;    MOVTrack tracks[MAX_STREAMS];} MOVContext;static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack* track);/* output language code from iso639 language name */extern int ff_mov_iso639_to_lang(const char *lang, int mp4);//FIXME supprt 64bit varaint with wide placeholdersstatic offset_t updateSize (ByteIOContext *pb, offset_t pos){    offset_t 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 mode64 = 0; //   use 32 bit size variant if possible    offset_t pos = url_ftell(pb);    put_be32(pb, 0); /* size */    if (pos > UINT32_MAX) {        mode64 = 1;        put_tag(pb, "co64");    } else        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;        if(mode64 == 1)            put_be64(pb, track->cluster[cl][id].pos);        else            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;    offset_t 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;    offset_t entryPos, curpos;    offset_t 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){    offset_t curpos, entryPos;    int i, index = 0;    offset_t 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_wave_tag(ByteIOContext *pb, MOVTrack* track){    offset_t pos = url_ftell(pb);    put_be32(pb, 0);     /* size */    put_tag(pb, "wave");    put_be32(pb, 12);    /* size */    put_tag(pb, "frma");    put_tag(pb, "mp4a");    put_be32(pb, 12);    /* size */    put_tag(pb, "mp4a");    put_be32(pb, 0);    mov_write_esds_tag(pb, track);    put_be32(pb, 12);    /* size */    put_tag(pb, "srcq");    put_be32(pb, 0x40);    put_be32(pb, 8);     /* size */    put_be32(pb, 0);     /* null tag */    return updateSize (pb, pos);}static const CodecTag codec_movaudio_tags[] = {    { CODEC_ID_PCM_MULAW, MKTAG('u', 'l', 'a', 'w') },    { CODEC_ID_PCM_ALAW, MKTAG('a', 'l', 'a', 'w') },    { CODEC_ID_ADPCM_IMA_QT, MKTAG('i', 'm', 'a', '4') },    { CODEC_ID_MACE3, MKTAG('M', 'A', 'C', '3') },    { CODEC_ID_MACE6, MKTAG('M', 'A', 'C', '6') },    { CODEC_ID_AAC, MKTAG('m', 'p', '4', 'a') },    { CODEC_ID_AMR_NB, MKTAG('s', 'a', 'm', 'r') },    { CODEC_ID_AMR_WB, MKTAG('s', 'a', 'w', 'b') },    { CODEC_ID_PCM_S16BE, MKTAG('t', 'w', 'o', 's') },    { CODEC_ID_PCM_S16LE, MKTAG('s', 'o', 'w', 't') },    { CODEC_ID_MP3, MKTAG('.', 'm', 'p', '3') },    { CODEC_ID_NONE, 0 },};static int mov_write_audio_tag(ByteIOContext *pb, MOVTrack* track){    offset_t pos = url_ftell(pb);    int tag;    put_be32(pb, 0); /* size */    tag = track->enc->codec_tag;    if (!tag)    tag = codec_get_tag(codec_movaudio_tags, track->enc->codec_id);    // if no mac fcc found, try with Microsoft tags    if (!tag)    {        int tmp = codec_get_tag(codec_wav_tags, track->enc->codec_id);        tag = MKTAG('m', 's', ((tmp >> 8) & 0xff), (tmp & 0xff));    }    put_le32(pb, tag); // store it byteswapped    put_be32(pb, 0); /* Reserved */    put_be16(pb, 0); /* Reserved */    put_be16(pb, 1); /* Data-reference index, XXX  == 1 */    /* SoundDescription */    if(track->mode == MODE_MOV && track->enc->codec_id == CODEC_ID_AAC)        put_be16(pb, 1); /* Version 1 */    else        put_be16(pb, 0); /* Version 0 */    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 */    if(track->enc->codec_id == CODEC_ID_AAC ||       track->enc->codec_id == CODEC_ID_MP3)    {        put_be16(pb, 0xfffe); /* compression ID (vbr)*/    }    else    {        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->mode == MODE_MOV && track->enc->codec_id == CODEC_ID_AAC)    {        /* SoundDescription V1 extended info */        put_be32(pb, track->enc->frame_size); /* Samples per packet  */        put_be32(pb, 1536); /* Bytes per packet */        put_be32(pb, 2); /* Bytes per frame */        put_be32(pb, 2); /* Bytes per sample */    }    if(track->enc->codec_id == CODEC_ID_AAC) {        if( track->mode == MODE_MOV ) mov_write_wave_tag(pb, track);        else 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 uint8_t *avc_find_startcode( uint8_t *p, uint8_t *end ){    uint8_t *a = p + 4 - ((int)p & 3);    for( end -= 3; p < a && p < end; p++ ) {        if( p[0] == 0 && p[1] == 0 && p[2] == 1 )            return p;    }    for( end -= 3; p < end; p += 4 ) {        uint32_t x = *(uint32_t*)p;//      if( (x - 0x01000100) & (~x) & 0x80008000 ) // little endian//      if( (x - 0x00010001) & (~x) & 0x00800080 ) // big endian        if( (x - 0x01010101) & (~x) & 0x80808080 ) { // generic            if( p[1] == 0 ) {                if( p[0] == 0 && p[2] == 1 )                    return p;                if( p[2] == 0 && p[3] == 1 )                    return p+1;            }            if( p[3] == 0 ) {                if( p[2] == 0 && p[4] == 1 )                    return p+2;                if( p[4] == 0 && p[5] == 1 )                    return p+3;            }        }    }    for( end += 3; p < end; p++ ) {        if( p[0] == 0 && p[1] == 0 && p[2] == 1 )            return p;    }    return end + 3;}static void avc_parse_nal_units(uint8_t **buf, int *size){    ByteIOContext pb;    uint8_t *p = *buf;    uint8_t *end = p + *size;    uint8_t *nal_start, *nal_end;    url_open_dyn_buf(&pb);    nal_start = avc_find_startcode(p, end);    while (nal_start < end) {        while(!*(nal_start++));        nal_end = avc_find_startcode(nal_start, end);        put_be32(&pb, nal_end - nal_start);        put_buffer(&pb, nal_start, nal_end - nal_start);        nal_start = nal_end;    }    av_freep(buf);    *size = url_close_dyn_buf(&pb, buf);}static int mov_write_avcc_tag(ByteIOContext *pb, MOVTrack *track){    offset_t pos = url_ftell(pb);    put_be32(pb, 0);    put_tag(pb, "avcC");    if (track->vosLen > 6) {        /* check for h264 start code */        if (BE_32(track->vosData) == 0x00000001) {            uint8_t *buf, *end;            uint32_t sps_size=0, pps_size=0;            uint8_t *sps=0, *pps=0;            avc_parse_nal_units(&track->vosData, &track->vosLen);            buf = track->vosData;            end = track->vosData + track->vosLen;            put_byte(pb, 1); /* version */            put_byte(pb, 77); /* profile */            put_byte(pb, 64); /* profile compat */            put_byte(pb, 30); /* level */            put_byte(pb, 0xff); /* 6 bits reserved (111111) + 2 bits nal size length - 1 (11) */            put_byte(pb, 0xe1); /* 3 bits reserved (111) + 5 bits number of sps (00001) */            /* look for sps and pps */            while (buf < end) {                unsigned int size;                uint8_t nal_type;                size = BE_32(buf);                nal_type = buf[4] & 0x1f;                if (nal_type == 7) { /* SPS */                    sps = buf + 4;                    sps_size = size;                } else if (nal_type == 8) { /* PPS */                    pps = buf + 4;                    pps_size = size;                }                buf += size + 4;            }            assert(sps);            assert(pps);            put_be16(pb, sps_size);            put_buffer(pb, sps, sps_size);            put_byte(pb, 1); /* number of pps */            put_be16(pb, pps_size);

⌨️ 快捷键说明

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