📄 nut.c
字号:
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, 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; 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 int64_t lsb2full(StreamContext *stream, int64_t lsb){ int64_t mask = (1<<stream->msb_timestamp_shift)-1; int64_t delta= stream->last_pts - mask/2; return ((lsb - delta)&mask) + delta;}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_ENCODERSstatic 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 (%Ld)\n", tmp); return -1; } nut->stream_count = get_v(bc); 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 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; 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 32:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -