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

📄 nut.c

📁 ffmpeg源码分析
💻 C
📖 第 1 页 / 共 3 页
字号:
    int64_t cur= url_ftell(bc);    int size= cur - start - get_length(nut->written_packet_size)/7 - 8;    if(calculate_checksum)        size += 4;    if(size != nut->written_packet_size){        int i;        assert( size <= nut->written_packet_size );        url_fseek(bc, start + 8, 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, tmp_time, tmp_flags,tmp_stream, tmp_mul, tmp_size, tmp_fields;    nut->avf= s;    nut->stream =        av_mallocz(sizeof(StreamContext)*s->nb_streams);    put_buffer(bc, ID_STRING, strlen(ID_STRING));    put_byte(bc, 0);    nut->packet_start[2]= url_ftell(bc);    /* main header */    put_be64(bc, MAIN_STARTCODE);    put_packetheader(nut, bc, 120+5*256, 1);    put_v(bc, 2); /* version */    put_v(bc, s->nb_streams);    put_v(bc, MAX_DISTANCE);    put_v(bc, MAX_SHORT_DISTANCE);    put_v(bc, nut->rate_num=1);    put_v(bc, nut->rate_den=2);    put_v(bc, nut->short_startcode=0x4EFE79);    build_frame_code(s);    assert(nut->frame_code['N'].flags == FLAG_INVALID);    tmp_time= tmp_flags= tmp_stream= tmp_mul= tmp_size= /*tmp_res=*/ INT_MAX;    for(i=0; i<256;){        tmp_fields=0;        tmp_size= 0;        if(tmp_time   != nut->frame_code[i].timestamp_delta) tmp_fields=1;        if(tmp_mul    != nut->frame_code[i].size_mul       ) tmp_fields=2;        if(tmp_stream != nut->frame_code[i].stream_id_plus1) tmp_fields=3;        if(tmp_size   != nut->frame_code[i].size_lsb       ) tmp_fields=4;//        if(tmp_res    != nut->frame_code[i].res            ) tmp_fields=5;        tmp_time  = nut->frame_code[i].timestamp_delta;        tmp_flags = nut->frame_code[i].flags;        tmp_stream= nut->frame_code[i].stream_id_plus1;        tmp_mul   = nut->frame_code[i].size_mul;        tmp_size  = nut->frame_code[i].size_lsb;//        tmp_res   = nut->frame_code[i].res;        for(j=0; i<256; j++,i++){            if(nut->frame_code[i].timestamp_delta != tmp_time  ) break;            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+j) break;//            if(nut->frame_code[i].res             != tmp_res   ) break;        }        if(j != tmp_mul - tmp_size) tmp_fields=6;        put_v(bc, tmp_flags);        put_v(bc, tmp_fields);        if(tmp_fields>0) put_s(bc, tmp_time);        if(tmp_fields>1) put_v(bc, tmp_mul);        if(tmp_fields>2) put_v(bc, tmp_stream);        if(tmp_fields>3) put_v(bc, tmp_size);        if(tmp_fields>4) put_v(bc, 0 /*tmp_res*/);        if(tmp_fields>5) put_v(bc, j);    }    update_packetheader(nut, bc, 0, 1);    /* stream headers */    for (i = 0; i < s->nb_streams; i++)    {        int nom, denom, ssize;        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*/);        switch(codec->codec_type){        case CODEC_TYPE_VIDEO: put_v(bc, 0); break;        case CODEC_TYPE_AUDIO: put_v(bc, 1); break;//        case CODEC_TYPE_TEXT : put_v(bc, 2); break;        case CODEC_TYPE_DATA : put_v(bc, 3); break;        default: return -1;        }        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);        ff_parse_specific_params(codec, &nom, &ssize, &denom);        nut->stream[i].rate_num= nom;        nut->stream[i].rate_den= denom;        av_set_pts_info(s->streams[i], 60, denom, nom);        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);        put_v(bc, codec->has_b_frames);        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);                put_v(bc, 1);                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, AVPacket *pkt){    NUTContext *nut = s->priv_data;    StreamContext *stream= &nut->stream[pkt->stream_index];    ByteIOContext *bc = &s->pb;    int key_frame = 0, full_pts=0;    AVCodecContext *enc;    int64_t coded_pts;    int frame_type, best_length, frame_code, flags, i, size_mul, size_lsb, time_delta;    const int64_t frame_start= url_ftell(bc);    int64_t pts= pkt->pts;    int size= pkt->size;    int stream_index= pkt->stream_index;    enc = s->streams[stream_index]->codec;    key_frame = !!(pkt->flags & PKT_FLAG_KEY);    frame_type=0;    if(frame_start + size + 20 - FFMAX(nut->packet_start[1], nut->packet_start[2]) > MAX_DISTANCE)        frame_type=2;    if(key_frame && !stream->last_key_frame)        frame_type=2;    if(frame_type>1){        int64_t global_ts= av_rescale(pts, stream->rate_den*(int64_t)nut->rate_num, stream->rate_num*(int64_t)nut->rate_den);        reset(s, global_ts);        put_be64(bc, KEYFRAME_STARTCODE);        put_v(bc, global_ts);    }    assert(stream->last_pts != AV_NOPTS_VALUE);    coded_pts = pts & ((1<<stream->msb_timestamp_shift)-1);    if(lsb2full(stream, coded_pts) != pts)        full_pts=1;    if(full_pts)        coded_pts= pts + (1<<stream->msb_timestamp_shift);    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;        time_delta= nut->frame_code[i].timestamp_delta;        flags= nut->frame_code[i].flags;        assert(size_mul > size_lsb);        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_DATA_SIZE){            if(size % size_mul != size_lsb)                continue;            length += get_length(size / size_mul);        }else if(size != size_lsb)            continue;        if(full_pts && time_delta)            continue;        if(!time_delta){            length += get_length(coded_pts);        }else{            if(time_delta != pts - stream->last_pts)                continue;        }        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;    time_delta= nut->frame_code[frame_code].timestamp_delta;#ifdef TRACE    best_length /= 7;    best_length ++; //frame_code    if(frame_type==2){        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 pts:%lld fs:%lld\n", key_frame, frame_type, full_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), pts, frame_start);//    av_log(s, AV_LOG_DEBUG, "%d %d %d\n", stream->lru_pts_delta[0], stream->lru_pts_delta[1], stream->lru_pts_delta[2]);#endif    assert(frame_type != 1); //short startcode not implemented yet    put_byte(bc, frame_code);    if(nut->frame_code[frame_code].stream_id_plus1 == 0)        put_v(bc, stream_index);    if (!time_delta){        put_v(bc, coded_pts);    }    if(flags & FLAG_DATA_SIZE)        put_v(bc, size / size_mul);    else        assert(size == size_lsb);    if(size > MAX_DISTANCE){        assert(frame_type > 1);    }    put_buffer(bc, pkt->data, 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;#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_MUXERSstatic int nut_probe(AVProbeData *p){    int i;    uint64_t code= 0xff;    for (i = 0; i < p->buf_size; i++) {        code = (code << 8) | p->buf[i];        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, tmp_stream, tmp_mul, tmp_time, tmp_size, count, tmp_res;    get_packetheader(nut, bc, 1);    tmp = get_v(bc);    if (tmp != 2){        av_log(s, AV_LOG_ERROR, "bad version (%"PRId64")\n", tmp);        return -1;    }    nut->stream_count = get_v(bc);    if(nut->stream_count > MAX_STREAMS){        av_log(s, AV_LOG_ERROR, "too many streams\n");        return -1;    }    nut->max_distance = get_v(bc);    nut->max_short_distance = get_v(bc);    nut->rate_num= get_v(bc);    nut->rate_den= get_v(bc);    nut->short_startcode= get_v(bc);    if(nut->short_startcode>>16 != 'N'){        av_log(s, AV_LOG_ERROR, "invalid short startcode %X\n", nut->short_startcode);        return -1;    }    for(i=0; i<256;){        int tmp_flags = get_v(bc);        int tmp_fields= get_v(bc);        if(tmp_fields>0) tmp_time  = get_s(bc);        if(tmp_fields>1) tmp_mul   = get_v(bc);        if(tmp_fields>2) tmp_stream= get_v(bc);        if(tmp_fields>3) tmp_size  = get_v(bc);        else             tmp_size  = 0;        if(tmp_fields>4) tmp_res   = get_v(bc);        else             tmp_res   = 0;        if(tmp_fields>5) count     = get_v(bc);        else             count     = tmp_mul - tmp_size;        while(tmp_fields-- > 6)           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_stream > nut->stream_count + 1){            av_log(s, AV_LOG_ERROR, "illegal stream number\n");            return -1;        }        for(j=0; j<count; j++,i++){            nut->frame_code[i].flags           = tmp_flags ;            nut->frame_code[i].timestamp_delta = tmp_time  ;            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+j;            nut->frame_code[i].reserved_count  = tmp_res   ;        }    }    if(nut->frame_code['N'].flags != FLAG_INVALID){        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 mismatch\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;    uint64_t tmp;    AVStream *st;    get_packetheader(nut, bc, 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 1:        case 32: //compatibility            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;        case 2://            st->codec->codec_type = CODEC_TYPE_TEXT;//            break;        case 3:            st->codec->codec_type = CODEC_TYPE_DATA;            break;

⌨️ 快捷键说明

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