-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_ENCODERS
-
-static 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);
- 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 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:
- 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);
- nut->stream[stream_id].decode_delay= get_v(bc);
- get_byte(bc); /* flags */
-
- /* codec specific data headers */
- while(get_v(bc) != 0){
- st->codec.extradata_size= get_v(bc);
- if((unsigned)st->codec.extradata_size > (1<<30))
- return -1;
- st->codec.extradata= av_mallocz(st->codec.extradata_size + FF_INPUT_BUFFER_PADDING_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;
- }
- if (class == 32) /* AUDIO */
- {
- st->codec.sample_rate = get_v(bc);
- get_v(bc); // samplerate_den
- st->codec.channels = get_v(bc);
- }
- if(check_checksum(bc)){
- av_log(s, AV_LOG_ERROR, "Stream header %d checksum missmatch\n", stream_id);
- return -1;
- }
- av_set_pts_info(s->streams[stream_id], 60, denom, nom);
- nut->stream[stream_id].rate_num= nom;
- nut->stream[stream_id].rate_den= denom;
- return 0;
-}
-
-static int decode_info_header(NUTContext *nut){
- AVFormatContext *s= nut->avf;
- ByteIOContext *bc = &s->pb;
-
- get_packetheader(nut, bc, 1);
-
- for(;;){
- int id= get_v(bc);
- char *name, *type, custom_name[256], custom_type[256];
-
- if(!id)
- break;
- else if(id >= sizeof(info_table)/sizeof(info_table[0])){
- av_log(s, AV_LOG_ERROR, "info id is too large %d %d\n", id, sizeof(info_table)/sizeof(info_table[0]));
- return -1;
- }
-
- type= info_table[id][1];
- name= info_table[id][0];
-//av_log(s, AV_LOG_DEBUG, "%d %s %s\n", id, type, name);
-
- if(!type){
- get_str(bc, custom_type, sizeof(custom_type));
- type= custom_type;
- }
- if(!name){
- get_str(bc, custom_name, sizeof(custom_name));
- name= custom_name;
- }
-
- if(!strcmp(type, "v")){
- int value= get_v(bc);
- }else{
- if(!strcmp(name, "Author"))
- get_str(bc, s->author, sizeof(s->author));
- else if(!strcmp(name, "Title"))
- get_str(bc, s->title, sizeof(s->title));
- else if(!strcmp(name, "Copyright"))
- get_str(bc, s->copyright, sizeof(s->copyright));
- else if(!strcmp(name, "Description"))
- get_str(bc, s->comment, sizeof(s->comment));
- else
- get_str(bc, NULL, 0);
- }
- }
- if(check_checksum(bc)){
- av_log(s, AV_LOG_ERROR, "Info header checksum missmatch\n");
- return -1;
- }
- return 0;
-}
-
-static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap)
-{
- NUTContext *nut = s->priv_data;
- ByteIOContext *bc = &s->pb;
- int64_t pos;
- int inited_stream_count;
-
- nut->avf= s;
-
- /* main header */
- pos=0;
- for(;;){
- pos= find_startcode(bc, MAIN_STARTCODE, pos)+1;
- if (pos<0){
- av_log(s, AV_LOG_ERROR, "no main startcode found\n");
- return -1;
- }
- if(decode_main_header(nut) >= 0)
- break;
- }
-
-
- s->bit_rate = 0;
-
- nut->stream = av_malloc(sizeof(StreamContext)*nut->stream_count);
-
- /* stream headers */
- pos=0;
- for(inited_stream_count=0; inited_stream_count < nut->stream_count;){
- pos= find_startcode(bc, STREAM_STARTCODE, pos)+1;
- if (pos<0){
- av_log(s, AV_LOG_ERROR, "not all stream headers found\n");
- return -1;
- }
- if(decode_stream_header(nut) >= 0)
- inited_stream_count++;
- }
-
- /* info headers */
- pos=0;
- for(;;){
- uint64_t startcode= find_any_startcode(bc, pos);
- pos= url_ftell(bc);
-
- if(startcode==0){
- av_log(s, AV_LOG_ERROR, "EOF before video frames\n");
- return -1;
- }else if(startcode == KEYFRAME_STARTCODE){
- nut->next_startcode= startcode;
- break;
- }else if(startcode != INFO_STARTCODE){
- continue;
- }
-
- decode_info_header(nut);
- }
-
- return 0;