📄 nut.c
字号:
/* 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 + -