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

📄 nut.c

📁 F:图像处理资料264264书籍ffmpeg-0.4.9-pre1VideoStream.rar 一个视频解压缩源代码
💻 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>//#define TRACE//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 ID_STRING "nut/multimedia container\0"#define MAX_DISTANCE (1024*16-1)#define MAX_SHORT_DISTANCE (1024*4-1)#define FLAG_DATA_SIZE       1#define FLAG_KEY_FRAME       2#define FLAG_INVALID         4typedef struct {    uint8_t flags;    uint8_t stream_id_plus1;    uint16_t size_mul;    uint16_t size_lsb;    int16_t timestamp_delta;    uint8_t reserved_count;} FrameCode;typedef struct {    int last_key_frame;    int msb_timestamp_shift;    int rate_num;    int rate_den;    int64_t last_pts;    int64_t last_sync_pos;                    ///<pos of last 1/2 type frame    int decode_delay;} StreamContext;typedef struct {    AVFormatContext *avf;    int written_packet_size;    int64_t packet_start[3]; //0-> startcode less, 1-> short startcode 2-> long startcodes    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;    int max_distance;    int max_short_distance;    int rate_num;    int rate_den;    int short_startcode;} 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(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];        stream->last_key_frame= key_frame;    nut->packet_start[ frame_type ]= frame_start;    stream->last_pts= pts;}static void reset(AVFormatContext *s, int64_t global_ts){    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;        stream->last_pts= av_rescale(global_ts, stream->rate_num*(int64_t)nut->rate_den, stream->rate_den*(int64_t)nut->rate_num);    }}static void build_frame_code(AVFormatContext *s){    NUTContext *nut = s->priv_data;    int key_frame, index, pred, stream_id;    int start=0;    int end= 255;    int keyframe_0_esc= s->nb_streams > 2;    int pred_table[10];    if(keyframe_0_esc){        /* keyframe = 0 escape */        FrameCode *ft= &nut->frame_code[start];        ft->flags= FLAG_DATA_SIZE;        ft->stream_id_plus1= 0;        ft->size_mul=1;        ft->timestamp_delta=0;        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;                        {                FrameCode *ft= &nut->frame_code[start2];                ft->flags= FLAG_KEY_FRAME*key_frame;                ft->flags|= FLAG_DATA_SIZE;                ft->stream_id_plus1= stream_id + 1;                ft->size_mul=1;                ft->timestamp_delta=0;                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);            int pts;            for(pts=0; pts<2; pts++){                for(pred=0; pred<2; pred++){                    FrameCode *ft= &nut->frame_code[start2];                    ft->flags= FLAG_KEY_FRAME*key_frame;                    ft->stream_id_plus1= stream_id + 1;                    ft->size_mul=frame_bytes + 2;                    ft->size_lsb=frame_bytes + pred;                    ft->timestamp_delta=pts;                    start2++;                }            }        }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;            ft->timestamp_delta=1;            start2++;        }#endif        if(codec->has_b_frames){            pred_count=5;            pred_table[0]=-2;            pred_table[1]=-1;            pred_table[2]=1;            pred_table[3]=3;            pred_table[4]=4;        }else if(codec->codec_id == CODEC_ID_VORBIS){            pred_count=3;            pred_table[0]=2;            pred_table[1]=9;            pred_table[2]=16;        }else{            pred_count=1;            pred_table[0]=1;        }        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;                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;                ft->timestamp_delta= pred_table[pred];            }        }    }    memmove(&nut->frame_code['N'+1], &nut->frame_code['N'], sizeof(FrameCode)*(255-'N'));    nut->frame_code['N'].flags= FLAG_INVALID;}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{//av_log(NULL, AV_LOG_DEBUG, "get_v()= %lld\n", (val<<7) + tmp);	    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 int64_t get_s(ByteIOContext *bc){    int64_t v = get_v(bc) + 1;    if (v&1) return -(v>>1);    else     return  (v>>1);}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);    //av_log(NULL, AV_LOG_DEBUG, "get_vb()= %lld\n", val);    return val;}#ifdef TRACEstatic inline uint64_t get_v_trace(ByteIOContext *bc, char *file, char *func, int line){    uint64_t v= get_v(bc);    printf("get_v %5lld / %llX in %s %s:%d\n", v, v, file, func, line);    return v;}static inline int64_t get_s_trace(ByteIOContext *bc, char *file, char *func, int line){    int64_t v= get_s(bc);    printf("get_s %5lld / %llX in %s %s:%d\n", v, v, file, func, line);    return v;}static inline uint64_t get_vb_trace(ByteIOContext *bc, char *file, char *func, int line){    uint64_t v= get_vb(bc);    printf("get_vb %5lld / %llX in %s %s:%d\n", v, v, file, func, line);    return v;}#define get_v(bc)  get_v_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__)#define get_s(bc)  get_s_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__)#define get_vb(bc)  get_vb_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__)#endifstatic int get_packetheader(NUTContext *nut, ByteIOContext *bc, int calculate_checksum){    int64_t start, size;    start= url_ftell(bc) - 8;    init_checksum(bc, calculate_checksum ? update_adler32 : NULL, 0);    size= get_v(bc);    nut->packet_start[2] = 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;//av_log(NULL, AV_LOG_DEBUG, "put_v()= %lld\n", val);    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_s(ByteIOContext *bc, uint64_t val){    if (val<=0) put_v(bc, -2*val  );    else        put_v(bc,  2*val-1);}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);}#ifdef TRACEstatic inline void put_v_trace(ByteIOContext *bc, uint64_t v, char *file, char *func, int line){    printf("get_v %5lld / %llX in %s %s:%d\n", v, v, file, func, line);        put_v(bc, v);}static inline void put_s_trace(ByteIOContext *bc, int64_t v, char *file, char *func, int line){    printf("get_s %5lld / %llX in %s %s:%d\n", v, v, file, func, line);        put_s(bc, v);}static inline void put_vb_trace(ByteIOContext *bc, uint64_t v, char *file, char *func, int line){    printf("get_vb %5lld / %llX in %s %s:%d\n", v, v, file, func, line);        put_vb(bc, v);}#define put_v(bc, v)  put_v_trace(bc, v, __FILE__, __PRETTY_FUNCTION__, __LINE__)#define put_s(bc, v)  put_s_trace(bc, v, __FILE__, __PRETTY_FUNCTION__, __LINE__)#define put_vb(bc, v)  put_vb_trace(bc, v, __FILE__, __PRETTY_FUNCTION__, __LINE__)#endifstatic int put_packetheader(NUTContext *nut, ByteIOContext *bc, int max_size, int calculate_checksum){    put_flush_packet(bc);    nut->packet_start[2]+= nut->written_packet_size;    assert(url_ftell(bc) - 8 == nut->packet_start[2]);    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 */    return 0;}static int update_packetheader(NUTContext *nut, ByteIOContext *bc, int additional_size, int calculate_checksum){    int64_t start= nut->packet_start[2];    int64_t cur= url_ftell(bc);    int size= cur - start + additional_size;        if(calculate_checksum)

⌨️ 快捷键说明

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