📄 nut.c
字号:
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); 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; } 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;}static int decode_frame_header(NUTContext *nut, int *key_frame_ret, int64_t *pts_ret, int *stream_id_ret, int frame_code, int frame_type, int64_t frame_start){ AVFormatContext *s= nut->avf; StreamContext *stream; ByteIOContext *bc = &s->pb; int size, flags, size_mul, size_lsb, stream_id, time_delta; int64_t pts = 0; if(frame_type < 2 && frame_start - nut->packet_start[2] > nut->max_distance){ av_log(s, AV_LOG_ERROR, "last frame must have been damaged\n"); return -1; } if(frame_type) nut->packet_start[ frame_type ]= frame_start; //otherwise 1 goto 1 may happen 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; stream_id= nut->frame_code[frame_code].stream_id_plus1 - 1; time_delta= nut->frame_code[frame_code].timestamp_delta; if(stream_id==-1) stream_id= get_v(bc); if(stream_id >= s->nb_streams){ av_log(s, AV_LOG_ERROR, "illegal stream_id\n"); return -1; } stream= &nut->stream[stream_id];// av_log(s, AV_LOG_DEBUG, "ft:%d ppts:%d %d %d\n", frame_type, stream->lru_pts_delta[0], stream->lru_pts_delta[1], stream->lru_pts_delta[2]); *key_frame_ret= !!(flags & FLAG_KEY_FRAME); if(!time_delta){ int64_t mask = (1<<stream->msb_timestamp_shift)-1; pts= get_v(bc); if(pts > mask){ pts -= mask+1; }else{ if(stream->last_pts == AV_NOPTS_VALUE){ av_log(s, AV_LOG_ERROR, "no reference pts available\n"); return -1; } pts= lsb2full(stream, pts); } }else{ if(stream->last_pts == AV_NOPTS_VALUE){ av_log(s, AV_LOG_ERROR, "no reference pts available\n"); return -1; } pts= stream->last_pts + time_delta; } if(*key_frame_ret){// av_log(s, AV_LOG_DEBUG, "stream:%d start:%lld pts:%lld length:%lld\n",stream_id, frame_start, av_pts, frame_start - nut->stream[stream_id].last_sync_pos); av_add_index_entry( s->streams[stream_id], frame_start, pts, frame_start - nut->stream[stream_id].last_sync_pos, AVINDEX_KEYFRAME); nut->stream[stream_id].last_sync_pos= frame_start;// assert(nut->packet_start == frame_start); } assert(size_mul > size_lsb); size= size_lsb; if(flags & FLAG_DATA_SIZE) size+= size_mul*get_v(bc); #ifdef TRACEav_log(s, AV_LOG_DEBUG, "fs:%lld fc:%d ft:%d kf:%d pts:%lld size:%d mul:%d lsb:%d flags:%d delta:%d\n", frame_start, frame_code, frame_type, *key_frame_ret, pts, size, size_mul, size_lsb, flags, time_delta);#endif if(frame_type==0 && url_ftell(bc) - nut->packet_start[2] + size > nut->max_distance){ av_log(s, AV_LOG_ERROR, "frame size too large\n"); return -1; } *stream_id_ret = stream_id; *pts_ret = pts; update(nut, stream_id, frame_start, frame_type, frame_code, *key_frame_ret, size, pts); return size;}static int decode_frame(NUTContext *nut, AVPacket *pkt, int frame_code, int frame_type, int64_t frame_start){ AVFormatContext *s= nut->avf; ByteIOContext *bc = &s->pb; int size, stream_id, key_frame; int64_t pts; size= decode_frame_header(nut, &key_frame, &pts, &stream_id, frame_code, frame_type, frame_start); if(size < 0) return -1; av_new_packet(pkt, size); get_buffer(bc, pkt->data, size); pkt->stream_index = stream_id; if (key_frame) pkt->flags |= PKT_FLAG_KEY; pkt->pts = pts; return 0;}static int nut_read_packet(AVFormatContext *s, AVPacket *pkt){ NUTContext *nut = s->priv_data; ByteIOContext *bc = &s->pb; int i, frame_code=0; for(;;){ int64_t pos= url_ftell(bc); int frame_type= 0; uint64_t tmp= nut->next_startcode; nut->next_startcode=0; if (url_feof(bc)) return -1; if(tmp){ pos-=8; }else{ frame_code = get_byte(bc); if(frame_code == 'N'){ tmp= frame_code; for(i=1; i<8; i++) tmp = (tmp<<8) + get_byte(bc); } } switch(tmp){ case MAIN_STARTCODE: case STREAM_STARTCODE: case INDEX_STARTCODE: get_packetheader(nut, bc, 0); assert(nut->packet_start[2] == pos); url_fseek(bc, nut->written_packet_size + nut->packet_start[2], SEEK_SET); break; case INFO_STARTCODE: if(decode_info_header(nut)<0) goto resync; break; case KEYFRAME_STARTCODE: frame_type = 2; reset(s, get_v(bc)); frame_code = get_byte(bc); case 0: if(decode_frame(nut, pkt, frame_code, frame_type, pos)>=0) return 0; default:resync:av_log(s, AV_LOG_DEBUG, "syncing from %lld\n", nut->packet_start[2]+1); tmp= find_any_startcode(bc, nut->packet_start[2]+1); if(tmp==0) return -1;av_log(s, AV_LOG_DEBUG, "sync\n"); nut->next_startcode= tmp; } }}static int64_t nut_read_timestamp(AVFormatContext *s, int stream_index, int64_t *pos_arg, int64_t pos_limit){ NUTContext *nut = s->priv_data; StreamContext *stream; ByteIOContext *bc = &s->pb; int64_t pos, pts; uint64_t code; int frame_code,step, stream_id, i,size, key_frame;av_log(s, AV_LOG_DEBUG, "read_timestamp(X,%d,%lld,%lld)\n", stream_index, *pos_arg, pos_limit); if(*pos_arg < 0) return AV_NOPTS_VALUE; pos= *pos_arg; step= FFMIN(16*1024, pos); do{ pos-= step; code= find_any_startcode(bc, pos); if(code && url_ftell(bc) - 8 <= *pos_arg) break; step= FFMIN(2*step, pos); }while(step); if(!code) //nothing found, not even after pos_arg return AV_NOPTS_VALUE; url_fseek(bc, -8, SEEK_CUR); for(i=0; i<s->nb_streams; i++) nut->stream[i].last_sync_pos= url_ftell(bc); for(;;){ int frame_type=0; int64_t pos= url_ftell(bc); uint64_t tmp=0; if(pos > pos_limit || url_feof(bc)) return AV_NOPTS_VALUE; frame_code = get_byte(bc); if(frame_code == 'N'){ tmp= frame_code; for(i=1; i<8; i++) tmp = (tmp<<8) + get_byte(bc); }//av_log(s, AV_LOG_DEBUG, "before switch %llX at=%lld\n", tmp, pos); switch(tmp){ case MAIN_STARTCODE: case STREAM_STARTCODE: case INDEX_STARTCODE: case INFO_STARTCODE: get_packetheader(nut, bc, 0); assert(nut->packet_start[2]==pos); url_fseek(bc, nut->written_packet_size + pos, SEEK_SET); break; case KEYFRAME_STARTCODE: frame_type=2; reset(s, get_v(bc)); frame_code = get_byte(bc); case 0: size= decode_frame_header(nut, &key_frame, &pts, &stream_id, frame_code, frame_type, pos); if(size < 0) goto resync; stream= &nut->stream[stream_id]; if(stream_id != stream_index || !key_frame || pos < *pos_arg){ url_fseek(bc, size, SEEK_CUR); break; } *pos_arg= pos; return pts; default:resync:av_log(s, AV_LOG_DEBUG, "syncing from %lld\n", nut->packet_start[2]+1); if(!find_any_startcode(bc, nut->packet_start[2]+1)) return AV_NOPTS_VALUE; url_fseek(bc, -8, SEEK_CUR); } } return AV_NOPTS_VALUE;}static int nut_read_seek(AVFormatContext *s, int stream_index, int64_t target_ts){// NUTContext *nut = s->priv_data; int64_t pos; if(av_seek_frame_binary(s, stream_index, target_ts) < 0) return -1; pos= url_ftell(&s->pb); nut_read_timestamp(s, stream_index, &pos, pos-1); return 0;}static int nut_read_close(AVFormatContext *s){ NUTContext *nut = s->priv_data; int i; for(i=0;i<s->nb_streams;i++) { av_freep(&s->streams[i]->codec.extradata); } av_freep(&nut->stream); return 0;}static AVInputFormat nut_iformat = { "nut", "nut format", sizeof(NUTContext), nut_probe, nut_read_header, nut_read_packet, nut_read_close, nut_read_seek, nut_read_timestamp, .extensions = "nut",};#ifdef CONFIG_ENCODERSstatic AVOutputFormat nut_oformat = { "nut", "nut format", "video/x-nut", "nut", sizeof(NUTContext),#ifdef CONFIG_VORBIS CODEC_ID_VORBIS,#elif defined(CONFIG_MP3LAME) CODEC_ID_MP3,#else CODEC_ID_MP2, /* AC3 needs liba52 decoder */#endif CODEC_ID_MPEG4, nut_write_header, nut_write_packet, nut_write_trailer,};#endif //CONFIG_ENCODERSint nut_init(void){ av_register_input_format(&nut_iformat);#ifdef CONFIG_ENCODERS av_register_output_format(&nut_oformat);#endif //CONFIG_ENCODERS return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -