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

📄 nut.c

📁 arm平台下的H264编码和解码源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
    /* main header */    put_be64(bc, MAIN_STARTCODE);    put_packetheader(nut, bc, 120+5*256, 1);    put_v(bc, 1); /* version */    put_v(bc, s->nb_streams);        build_frame_code(s);    assert(nut->frame_code['N'].flags == 1);    for(i=0; i<256;){        int tmp_flags = nut->frame_code[i].flags;        int tmp_stream= nut->frame_code[i].stream_id_plus1;        int tmp_mul   = nut->frame_code[i].size_mul;        int tmp_size  = nut->frame_code[i].size_lsb;        put_v(bc, tmp_flags);        put_v(bc, tmp_stream);        put_v(bc, tmp_mul);        put_v(bc, tmp_size);        for(j=0; i<256; j++,i++){            if(nut->frame_code[i].flags           != tmp_flags ) break;            if(nut->frame_code[i].stream_id_plus1 != tmp_stream) break;            if(nut->frame_code[i].size_mul        != tmp_mul   ) break;            if(nut->frame_code[i].size_lsb        != tmp_size  ) break;            if(++tmp_size >= tmp_mul){                tmp_size=0;                tmp_stream++;            }        }        put_v(bc, j);    }    update_packetheader(nut, bc, 0, 1);        /* stream headers */    for (i = 0; i < s->nb_streams; i++)    {	int nom, denom, gcd;	codec = &s->streams[i]->codec;		put_be64(bc, STREAM_STARTCODE);	put_packetheader(nut, bc, 120 + codec->extradata_size, 1);	put_v(bc, i /*s->streams[i]->index*/);	put_v(bc, (codec->codec_type == CODEC_TYPE_AUDIO) ? 32 : 0);	if (codec->codec_tag)	    put_vb(bc, codec->codec_tag);	else if (codec->codec_type == CODEC_TYPE_VIDEO)	{	    put_vb(bc, codec_get_bmp_tag(codec->codec_id));	}	else if (codec->codec_type == CODEC_TYPE_AUDIO)	{	    put_vb(bc, codec_get_wav_tag(codec->codec_id));	}        else            put_vb(bc, 0);	if (codec->codec_type == CODEC_TYPE_VIDEO)	{	    nom = codec->frame_rate;	    denom = codec->frame_rate_base;	}	else	{	    nom = codec->sample_rate;            if(codec->frame_size>0)                denom= codec->frame_size;            else                denom= 1; //unlucky	}        gcd= ff_gcd(nom, denom);        nom   /= gcd;        denom /= gcd;        nut->stream[i].rate_num= nom;        nut->stream[i].rate_den= denom;	put_v(bc, codec->bit_rate);	put_vb(bc, 0); /* no language code */	put_v(bc, nom);	put_v(bc, denom);        if(nom / denom < 1000)	    nut->stream[i].msb_timestamp_shift = 7;        else	    nut->stream[i].msb_timestamp_shift = 14;	put_v(bc, nut->stream[i].msb_timestamp_shift);	for(j=0; j<3; j++)		put_v(bc, nut->stream[i].initial_pts_predictor[j]);	for(j=0; j<2; j++)		put_v(bc, nut->stream[i].initial_size_predictor[j]);	put_byte(bc, 0); /* flags: 0x1 - fixed_fps, 0x2 - index_present */	        if(codec->extradata_size){            put_v(bc, 1);            put_v(bc, codec->extradata_size);            put_buffer(bc, codec->extradata, codec->extradata_size);                    }	put_v(bc, 0); /* end of codec specific headers */		switch(codec->codec_type)	{	    case CODEC_TYPE_AUDIO:		put_v(bc, (codec->sample_rate * denom) / nom);		put_v(bc, codec->channels);		break;	    case CODEC_TYPE_VIDEO:		put_v(bc, codec->width);		put_v(bc, codec->height);		put_v(bc, codec->sample_aspect_ratio.num);		put_v(bc, codec->sample_aspect_ratio.den);		put_v(bc, 0); /* csp type -- unknown */		break;            default:                break;	}        update_packetheader(nut, bc, 0, 1);    }    /* info header */    put_be64(bc, INFO_STARTCODE);    put_packetheader(nut, bc, 30+strlen(s->author)+strlen(s->title)+        strlen(s->comment)+strlen(s->copyright)+strlen(LIBAVFORMAT_IDENT), 1);     if (s->author[0])    {        put_v(bc, 9); /* type */        put_str(bc, s->author);    }    if (s->title[0])    {        put_v(bc, 10); /* type */        put_str(bc, s->title);    }    if (s->comment[0])    {        put_v(bc, 11); /* type */        put_str(bc, s->comment);    }    if (s->copyright[0])    {        put_v(bc, 12); /* type */        put_str(bc, s->copyright);    }    /* encoder */    if(!(s->streams[0]->codec.flags & CODEC_FLAG_BITEXACT)){        put_v(bc, 13); /* type */        put_str(bc, LIBAVFORMAT_IDENT);    }        put_v(bc, 0); /* eof info */    update_packetheader(nut, bc, 0, 1);            put_flush_packet(bc);        return 0;}static int nut_write_packet(AVFormatContext *s, int stream_index, 			    const uint8_t *buf, int size, int64_t pts){    NUTContext *nut = s->priv_data;    StreamContext *stream= &nut->stream[stream_index];    ByteIOContext *bc = &s->pb;    int key_frame = 0, full_pts=0;    AVCodecContext *enc;    int64_t lsb_pts, delta_pts;    int frame_type, best_length, frame_code, flags, i, size_mul, size_lsb;    const int64_t frame_start= url_ftell(bc);    if (stream_index > s->nb_streams)	return 1;            pts= (av_rescale(pts, stream->rate_num, stream->rate_den) + AV_TIME_BASE/2) / AV_TIME_BASE;    enc = &s->streams[stream_index]->codec;    key_frame = enc->coded_frame->key_frame;    if(enc->coded_frame->pts != AV_NOPTS_VALUE)        pts= (av_rescale(enc->coded_frame->pts, stream->rate_num, stream->rate_den) + AV_TIME_BASE/2) / AV_TIME_BASE; //FIXME XXX HACK    delta_pts= pts - stream->last_pts;        frame_type=0;    if(frame_start + size + 20 - FFMAX(nut->last_frame_start[1], nut->last_frame_start[2]) > MAX_TYPE1_DISTANCE)        frame_type=1;    if(key_frame){        if(frame_type==1 && frame_start + size - nut->last_frame_start[2] > MAX_TYPE2_DISTANCE)            frame_type=2;        if(!stream->last_key_frame)            frame_type=2;    }    if(frame_type>0){        update_packetheader(nut, bc, 0, 0);        reset(s);        full_pts=1;    }    //FIXME ensure that the timestamp can be represented by either delta or lsb or full_pts=1    lsb_pts = pts & ((1 << stream->msb_timestamp_shift)-1);    best_length=INT_MAX;    frame_code= -1;    for(i=0; i<256; i++){        int stream_id_plus1= nut->frame_code[i].stream_id_plus1;        int fc_key_frame;        int length=0;        size_mul= nut->frame_code[i].size_mul;        size_lsb= nut->frame_code[i].size_lsb;        flags= nut->frame_code[i].flags;        if(stream_id_plus1 == 0) length+= get_length(stream_index);        else if(stream_id_plus1 - 1 != stream_index)            continue;        fc_key_frame= !!(flags & FLAG_KEY_FRAME);        assert(key_frame==0 || key_frame==1);        if(fc_key_frame != key_frame)            continue;        if((!!(flags & FLAG_FRAME_TYPE)) != (frame_type > 0))            continue;                if(size_mul <= size_lsb){            int p= stream->lru_size[size_lsb - size_mul];            if(p != size)                continue;        }else{            if(size % size_mul != size_lsb)                continue;            if(flags & FLAG_DATA_SIZE)                length += get_length(size / size_mul);            else if(size/size_mul)                continue;        }        if(full_pts != ((flags & FLAG_PTS) && (flags & FLAG_FULL_PTS)))            continue;                    if(flags&FLAG_PTS){            if(flags&FLAG_FULL_PTS){                length += get_length(pts);            }else{                length += get_length(lsb_pts);            }        }else{            int delta= stream->lru_pts_delta[(flags & 12)>>2];            if(delta != pts - stream->last_pts)                continue;            assert(frame_type == 0);        }        if(length < best_length){            best_length= length;            frame_code=i;        }//    av_log(s, AV_LOG_DEBUG, "%d %d %d %d %d %d %d %d %d %d\n", key_frame, frame_type, full_pts, size, stream_index, flags, size_mul, size_lsb, stream_id_plus1, length);    }    assert(frame_code != -1);    flags= nut->frame_code[frame_code].flags;    size_mul= nut->frame_code[frame_code].size_mul;    size_lsb= nut->frame_code[frame_code].size_lsb;#if 0    best_length /= 7;    best_length ++; //frame_code    if(frame_type>0){        best_length += 4; //packet header        if(frame_type>1)            best_length += 8; // startcode    }    av_log(s, AV_LOG_DEBUG, "kf:%d ft:%d pt:%d fc:%2X len:%2d size:%d stream:%d flag:%d mul:%d lsb:%d s+1:%d pts_delta:%d\n", key_frame, frame_type, full_pts ? 2 : ((flags & FLAG_PTS) ? 1 : 0), frame_code, best_length, size, stream_index, flags, size_mul, size_lsb, nut->frame_code[frame_code].stream_id_plus1,(int)(pts - stream->last_pts));#endif    if (frame_type==2)	put_be64(bc, KEYFRAME_STARTCODE);    put_byte(bc, frame_code);    if(frame_type>0)        put_packetheader(nut, bc, FFMAX(size+20, MAX_TYPE1_DISTANCE), 0);    if(nut->frame_code[frame_code].stream_id_plus1 == 0)        put_v(bc, stream_index);    if (flags & FLAG_PTS){        if (flags & FLAG_FULL_PTS)            put_v(bc, pts);        else            put_v(bc, lsb_pts);    }    if(flags & FLAG_DATA_SIZE)        put_v(bc, size / size_mul);    if(size > MAX_TYPE1_DISTANCE){        assert(frame_type > 0);        update_packetheader(nut, bc, size, 0);    }        put_buffer(bc, buf, size);    update(nut, stream_index, frame_start, frame_type, frame_code, key_frame, size, pts);        return 0;}static int nut_write_trailer(AVFormatContext *s){    NUTContext *nut = s->priv_data;    ByteIOContext *bc = &s->pb;    update_packetheader(nut, bc, 0, 0);#if 0    int i;    /* WRITE INDEX */    for (i = 0; s->nb_streams; i++)    {	put_be64(bc, INDEX_STARTCODE);	put_packetheader(nut, bc, 64, 1);	put_v(bc, s->streams[i]->id);	put_v(bc, ...);        update_packetheader(nut, bc, 0, 1);    }#endif    put_flush_packet(bc);        av_freep(&nut->stream);    return 0;}#endif //CONFIG_ENCODERSstatic int nut_probe(AVProbeData *p){    int i;    uint64_t code;    code = 0xff;    for (i = 0; i < p->buf_size; i++) {        int c = p->buf[i];        code = (code << 8) | c;        if (code == MAIN_STARTCODE)            return AVPROBE_SCORE_MAX;    }    return 0;}static int decode_main_header(NUTContext *nut){    AVFormatContext *s= nut->avf;    ByteIOContext *bc = &s->pb;    uint64_t tmp;    int i, j;        get_packetheader(nut, bc, 8, 1);    tmp = get_v(bc);    if (tmp != 1){	av_log(s, AV_LOG_ERROR, "bad version (%Ld)\n", tmp);        return -1;    }        nut->stream_count = get_v(bc);    for(i=0; i<256;){        int tmp_flags = get_v(bc);        int tmp_stream= get_v(bc);        int tmp_mul   = get_v(bc);        int tmp_size  = get_v(bc);        int count     = get_v(bc);        if(count == 0 || i+count > 256){            av_log(s, AV_LOG_ERROR, "illegal count %d at %d\n", count, i);            return -1;        }        if((tmp_flags & FLAG_FRAME_TYPE) && tmp_flags != 1){            if(!(tmp_flags & FLAG_PTS) || !(tmp_flags & FLAG_FULL_PTS) ){                av_log(s, AV_LOG_ERROR, "no full pts in non 0 frame type\n");                return -1;            }        }        for(j=0; j<count; j++,i++){            if(tmp_stream > nut->stream_count + 1){                av_log(s, AV_LOG_ERROR, "illegal stream number\n");                return -1;            }            nut->frame_code[i].flags           = tmp_flags ;            nut->frame_code[i].stream_id_plus1 = tmp_stream;            nut->frame_code[i].size_mul        = tmp_mul   ;            nut->frame_code[i].size_lsb        = tmp_size  ;            if(++tmp_size >= tmp_mul){                tmp_size=0;                tmp_stream++;            }        }    }    if(nut->frame_code['N'].flags != 1){        av_log(s, AV_LOG_ERROR, "illegal frame_code table\n");        return -1;    }    if(check_checksum(bc)){        av_log(s, AV_LOG_ERROR, "Main header checksum missmatch\n");        return -1;    }    return 0;}static int decode_stream_header(NUTContext *nut){    AVFormatContext *s= nut->avf;    ByteIOContext *bc = &s->pb;    int class, nom, denom, stream_id, i;    uint64_t tmp;    AVStream *st;        get_packetheader(nut, bc, 8, 1);    stream_id= get_v(bc);    if(stream_id >= nut->stream_count || s->streams[stream_id])        return -1;        st = av_new_stream(s, stream_id);    if (!st)        return AVERROR_NOMEM;    class = get_v(bc);    tmp = get_vb(bc);    st->codec.codec_tag= tmp;    switch(class)    {        case 0:            st->codec.codec_type = CODEC_TYPE_VIDEO;            st->codec.codec_id = codec_get_bmp_id(tmp);            if (st->codec.codec_id == CODEC_ID_NONE)                av_log(s, AV_LOG_ERROR, "Unknown codec?!\n");            break;        case 32:            st->codec.codec_type = CODEC_TYPE_AUDIO;            st->codec.codec_id = codec_get_wav_id(tmp);            if (st->codec.codec_id == CODEC_ID_NONE)                av_log(s, AV_LOG_ERROR, "Unknown codec?!\n");            break;        default:            av_log(s, AV_LOG_ERROR, "Unknown stream class (%d)\n", class);            return -1;    }    s->bit_rate += get_v(bc);    get_vb(bc); /* language code */    nom = get_v(bc);    denom = get_v(bc);    nut->stream[stream_id].msb_timestamp_shift = get_v(bc);    for(i=0; i<3; i++)            nut->stream[stream_id].initial_pts_predictor[i]= get_v(bc);    for(i=0; i<2; i++)            nut->stream[stream_id].initial_size_predictor[i]= get_v(bc);    get_byte(bc); /* flags */    /* codec specific data headers */    while(get_v(bc) != 0){        st->codec.extradata_size= get_v(bc);        st->codec.extradata= av_mallocz(st->codec.extradata_size);        get_buffer(bc, st->codec.extradata, st->codec.extradata_size);            //	    url_fskip(bc, get_v(bc));    }        if (class == 0) /* VIDEO */    {        st->codec.width = get_v(bc);        st->codec.height = get_v(bc);        st->codec.sample_aspect_ratio.num= get_v(bc);        st->codec.sample_aspect_ratio.den= get_v(bc);        get_v(bc); /* csp type */        st->codec.frame_rate = nom;        st->codec.frame_rate_base = denom;    }

⌨️ 快捷键说明

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