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

📄 nut.c

📁 arm平台下的H264编码和解码源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * "NUT" Container Format muxer and demuxer (DRAFT-200403??) * Copyright (c) 2003 Alex Beregszaszi * Copyright (c) 2004 Michael Niedermayer * * 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 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 * * NUT DRAFT can be found in MPlayer CVS at DOCS/tech/mpcf.txt * * AND http://people.fsn.hu/~alex/nut/ (TeX, pdf, ps, dvi, ..) * *//* * TODO: * - index writing * - index packet reading support*///#define DEBUG 1#include <limits.h>#include "avformat.h"#include "mpegaudio.h"#include "avi.h"#undef NDEBUG#include <assert.h>//from /dev/random#define     MAIN_STARTCODE (0x7A561F5F04ADULL + (((uint64_t)('N'<<8) + 'M')<<48)) #define   STREAM_STARTCODE (0x11405BF2F9DBULL + (((uint64_t)('N'<<8) + 'S')<<48)) #define KEYFRAME_STARTCODE (0xE4ADEECA4569ULL + (((uint64_t)('N'<<8) + 'K')<<48)) #define    INDEX_STARTCODE (0xDD672F23E64EULL + (((uint64_t)('N'<<8) + 'X')<<48)) #define     INFO_STARTCODE (0xAB68B596BA78ULL + (((uint64_t)('N'<<8) + 'I')<<48)) #define MAX_TYPE1_DISTANCE (1024*16-1)#define MAX_TYPE2_DISTANCE (1024*64-1)#define MAX_SIZE_LRU 2#define MAX_PTS_LRU 3#define FLAG_FRAME_TYPE      1#define FLAG_DATA_SIZE       2#define FLAG_PTS            16#define FLAG_FULL_PTS        4#define FLAG_KEY_FRAME      32typedef struct {    uint8_t flags;    uint8_t stream_id_plus1;    uint8_t size_mul;    uint8_t size_lsb;} FrameCode;typedef struct {    int last_key_frame;    int msb_timestamp_shift;    int rate_num;    int rate_den;    int64_t last_pts;    int64_t last_full_pts;    int lru_pts_delta[MAX_PTS_LRU];    int lru_size[MAX_SIZE_LRU];    int initial_pts_predictor[MAX_PTS_LRU];    int initial_size_predictor[MAX_SIZE_LRU];    int64_t last_sync_pos;                    ///<pos of last 1/2 type frame} StreamContext;typedef struct {    AVFormatContext *avf;    int64_t packet_start;    int64_t last_packet_start;    int written_packet_size;    int64_t packet_size_pos;    int64_t last_frame_start[3];    FrameCode frame_code[256];    int stream_count;    uint64_t next_startcode;     ///< stores the next startcode if it has alraedy been parsed but the stream isnt seekable    StreamContext *stream;} NUTContext;static char *info_table[][2]={	{NULL			,  NULL }, // end	{NULL			,  NULL },	{NULL			, "UTF8"},	{NULL			, "v"},	{NULL			, "s"},	{"StreamId"		, "v"},	{"SegmentId"		, "v"},	{"StartTimestamp"	, "v"},	{"EndTimestamp"		, "v"},	{"Author"		, "UTF8"},	{"Title"		, "UTF8"},	{"Description"		, "UTF8"},	{"Copyright"		, "UTF8"},	{"Encoder"		, "UTF8"},	{"Keyword"		, "UTF8"},	{"Cover"		, "JPEG"},	{"Cover"		, "PNG"},};static void update_lru(int *lru, int current, int count){    int i;    for(i=0; i<count-1; i++){        if(lru[i] == current)            break;    }    for(; i; i--){        lru[i]= lru[i-1];    }    lru[0]= current;}static void update(NUTContext *nut, int stream_index, int64_t frame_start, int frame_type, int frame_code, int key_frame, int size, int64_t pts){    StreamContext *stream= &nut->stream[stream_index];    const int flags=nut->frame_code[frame_code].flags;         stream->last_key_frame= key_frame;    nut->last_frame_start[ frame_type ]= frame_start;    if(frame_type == 0)        update_lru(stream->lru_pts_delta, pts - stream->last_pts, 3);    update_lru(stream->lru_size, size, 2);    stream->last_pts= pts;    if((flags & FLAG_PTS) && (flags & FLAG_FULL_PTS))        stream->last_full_pts= pts;}static void reset(AVFormatContext *s/*, int frame_type*/){    NUTContext *nut = s->priv_data;    int i;        for(i=0; i<s->nb_streams; i++){        StreamContext *stream= &nut->stream[i];            stream->last_key_frame= 1;        memcpy(stream->lru_pts_delta, stream->initial_pts_predictor, sizeof(int)*MAX_PTS_LRU);        memcpy(stream->lru_size, stream->initial_size_predictor, sizeof(int)*MAX_SIZE_LRU);    }}static void build_frame_code(AVFormatContext *s){    NUTContext *nut = s->priv_data;    int key_frame, frame_type, full_pts, index, pred, stream_id;    int start=0;    int end= 255;    int keyframe_0_esc= s->nb_streams > 2;    if(keyframe_0_esc){        /* keyframe = 0 escapes, 3 codes */        for(frame_type=0; frame_type<2; frame_type++){            for(full_pts=frame_type; full_pts<2; full_pts++){                FrameCode *ft= &nut->frame_code[start];                ft->flags= FLAG_FRAME_TYPE*frame_type + FLAG_FULL_PTS*full_pts;                ft->flags|= FLAG_DATA_SIZE | FLAG_PTS;                 ft->stream_id_plus1= 0;                ft->size_mul=1;                start++;            }        }    }    for(stream_id= 0; stream_id<s->nb_streams; stream_id++){        int start2= start + (end-start)*stream_id / s->nb_streams;        int end2  = start + (end-start)*(stream_id+1) / s->nb_streams;        AVCodecContext *codec = &s->streams[stream_id]->codec;        int is_audio= codec->codec_type == CODEC_TYPE_AUDIO;        int intra_only= /*codec->intra_only || */is_audio;        int pred_count;        for(key_frame=0; key_frame<2; key_frame++){            if(intra_only && keyframe_0_esc && key_frame==0)                continue;                        for(frame_type=0; frame_type<2; frame_type++){                for(full_pts=frame_type; full_pts<2; full_pts++){                    FrameCode *ft= &nut->frame_code[start2];                    ft->flags= FLAG_FRAME_TYPE*frame_type + FLAG_FULL_PTS*full_pts + FLAG_KEY_FRAME*key_frame;                    ft->flags|= FLAG_DATA_SIZE | FLAG_PTS;                    ft->stream_id_plus1= stream_id + 1;                    ft->size_mul=1;                    start2++;                }            }        }        key_frame= intra_only;#if 1        if(is_audio){            int frame_bytes= codec->frame_size*(int64_t)codec->bit_rate / (8*codec->sample_rate);            for(pred=0; pred<MAX_SIZE_LRU; pred++){                for(frame_type=0; frame_type<1; frame_type++){                    FrameCode *ft= &nut->frame_code[start2];                    ft->flags= FLAG_KEY_FRAME*key_frame + (FLAG_FULL_PTS+FLAG_PTS+FLAG_FRAME_TYPE)*frame_type;                    ft->stream_id_plus1= stream_id + 1;                    ft->size_mul=1;                    ft->size_lsb=1 + pred;                    start2++;                }                nut->stream[stream_id].initial_size_predictor[pred]= frame_bytes + pred;            }        }else{            FrameCode *ft= &nut->frame_code[start2];            ft->flags= FLAG_KEY_FRAME | FLAG_DATA_SIZE;            ft->stream_id_plus1= stream_id + 1;            ft->size_mul=1;            start2++;        }#endif        pred_count= 2 + codec->has_b_frames + (codec->codec_id == CODEC_ID_VORBIS);        for(pred=0; pred<pred_count; pred++){            int start3= start2 + (end2-start2)*pred / pred_count;            int end3  = start2 + (end2-start2)*(pred+1) / pred_count;            for(index=start3; index<end3; index++){                FrameCode *ft= &nut->frame_code[index];                ft->flags= FLAG_KEY_FRAME*key_frame + pred*4;                ft->flags|= FLAG_DATA_SIZE;                ft->stream_id_plus1= stream_id + 1;//FIXME use single byte size and pred from last                ft->size_mul= end3-start3;                ft->size_lsb= index - start3;            }            nut->stream[stream_id].initial_pts_predictor[pred]= pred+1;        }    }    memmove(&nut->frame_code['N'+1], &nut->frame_code['N'], sizeof(FrameCode)*(255-'N'));    nut->frame_code['N'].flags= 1;}static uint64_t get_v(ByteIOContext *bc){    uint64_t val = 0;    for(;;)    {	int tmp = get_byte(bc);	if (tmp&0x80)	    val= (val<<7) + tmp - 0x80;	else	    return (val<<7) + tmp;    }    return -1;}static int get_str(ByteIOContext *bc, char *string, int maxlen){    int len= get_v(bc);        if(len && maxlen)        get_buffer(bc, string, FFMIN(len, maxlen));    while(len > maxlen){        get_byte(bc);        len--;    }    if(maxlen)        string[FFMIN(len, maxlen-1)]= 0;        if(maxlen == len)        return -1;    else        return 0;}static uint64_t get_vb(ByteIOContext *bc){    uint64_t val=0;    int i= get_v(bc);        if(i>8)        return UINT64_MAX;        while(i--)        val = (val<<8) + get_byte(bc);        return val;}static int get_packetheader(NUTContext *nut, ByteIOContext *bc, int prefix_length, int calculate_checksum){    int64_t start, size, last_size;    start= url_ftell(bc) - prefix_length;    if(nut->written_packet_size >= 0 && start != nut->packet_start + nut->written_packet_size){        av_log(nut->avf, AV_LOG_ERROR, "get_packetheader called at weird position\n");        if(prefix_length<8)            return -1;    }        init_checksum(bc, calculate_checksum ? update_adler32 : NULL, 0);    size= get_v(bc);    last_size= get_v(bc);    if(nut->written_packet_size >= 0 && nut->written_packet_size != last_size){        av_log(nut->avf, AV_LOG_ERROR, "packet size missmatch %d != %lld at %lld\n", nut->written_packet_size, last_size, start);        if(prefix_length<8)            return -1;    }    nut->last_packet_start = nut->packet_start;    nut->packet_start = start;    nut->written_packet_size= size;    return size;}static int check_checksum(ByteIOContext *bc){    unsigned long checksum= get_checksum(bc);    return checksum != get_be32(bc);}/** *  */static int get_length(uint64_t val){    int i;    for (i=7; val>>i; i+=7);    return i;}static uint64_t find_any_startcode(ByteIOContext *bc, int64_t pos){    uint64_t state=0;        if(pos >= 0)        url_fseek(bc, pos, SEEK_SET); //note, this may fail if the stream isnt seekable, but that shouldnt matter, as in this case we simply start where we are currently    while(!url_feof(bc)){        state= (state<<8) | get_byte(bc);        if((state>>56) != 'N')            continue;        switch(state){        case MAIN_STARTCODE:        case STREAM_STARTCODE:        case KEYFRAME_STARTCODE:        case INFO_STARTCODE:        case INDEX_STARTCODE:            return state;        }    }    return 0;}/** * find the given startcode. * @param code the startcode * @param pos the start position of the search, or -1 if the current position * @returns the position of the startcode or -1 if not found */static int64_t find_startcode(ByteIOContext *bc, uint64_t code, int64_t pos){    for(;;){        uint64_t startcode= find_any_startcode(bc, pos);        if(startcode == code)            return url_ftell(bc) - 8;        else if(startcode == 0)            return -1;        pos=-1;    }}#ifdef CONFIG_ENCODERSstatic void put_v(ByteIOContext *bc, uint64_t val){    int i;    val &= 0x7FFFFFFFFFFFFFFFULL; // FIXME can only encode upto 63 bits currently    i= get_length(val);    for (i-=7; i>0; i-=7){	put_byte(bc, 0x80 | (val>>i));    }    put_byte(bc, val&0x7f);}/** * stores a string as vb. */static void put_str(ByteIOContext *bc, const char *string){    int len= strlen(string);        put_v(bc, len);    put_buffer(bc, string, len);}static void put_vb(ByteIOContext *bc, uint64_t val){    int i;        for (i=8; val>>i; i+=8);    put_v(bc, i>>3);    for(i-=8; i>=0; i-=8)        put_byte(bc, (val>>i)&0xFF);}static int put_packetheader(NUTContext *nut, ByteIOContext *bc, int max_size, int calculate_checksum){    put_flush_packet(bc);    nut->last_packet_start= nut->packet_start;    nut->packet_start+= nut->written_packet_size;    nut->packet_size_pos = url_ftell(bc);    nut->written_packet_size = max_size;        if(calculate_checksum)        init_checksum(bc, update_adler32, 0);    /* packet header */    put_v(bc, nut->written_packet_size); /* forward ptr */    put_v(bc, nut->packet_start - nut->last_packet_start); /* backward ptr */    return 0;}static int update_packetheader(NUTContext *nut, ByteIOContext *bc, int additional_size, int calculate_checksum){    int64_t start= nut->packet_start;    int64_t cur= url_ftell(bc);    int size= cur - start + additional_size;        if(calculate_checksum)        size += 4;        if(size != nut->written_packet_size){        int i;        assert( size <= nut->written_packet_size );            url_fseek(bc, nut->packet_size_pos, SEEK_SET);        for(i=get_length(size); i < get_length(nut->written_packet_size); i+=7)            put_byte(bc, 0x80);        put_v(bc, size);        url_fseek(bc, cur, SEEK_SET);        nut->written_packet_size= size; //FIXME may fail if multiple updates with differing sizes, as get_length may differ                if(calculate_checksum)            put_be32(bc, get_checksum(bc));    }        return 0;}static int nut_write_header(AVFormatContext *s){    NUTContext *nut = s->priv_data;    ByteIOContext *bc = &s->pb;    AVCodecContext *codec;    int i, j;    nut->avf= s;        nut->stream =		av_mallocz(sizeof(StreamContext)*s->nb_streams);        av_set_pts_info(s, 60, 1, AV_TIME_BASE);    

⌨️ 快捷键说明

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