00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <strings.h>
00024 #include "libavutil/avstring.h"
00025 #include "libavutil/bswap.h"
00026 #include "libavutil/dict.h"
00027 #include "libavutil/tree.h"
00028 #include "avio_internal.h"
00029 #include "nut.h"
00030
00031 #undef NDEBUG
00032 #include <assert.h>
00033
00034 #if FF_API_MAX_STREAMS
00035 #define NUT_MAX_STREAMS MAX_STREAMS
00036 #else
00037 #define NUT_MAX_STREAMS 256
00038 #endif
00039
00040 static int get_str(AVIOContext *bc, char *string, unsigned int maxlen){
00041 unsigned int len= ffio_read_varlen(bc);
00042
00043 if(len && maxlen)
00044 avio_read(bc, string, FFMIN(len, maxlen));
00045 while(len > maxlen){
00046 avio_r8(bc);
00047 len--;
00048 }
00049
00050 if(maxlen)
00051 string[FFMIN(len, maxlen-1)]= 0;
00052
00053 if(maxlen == len)
00054 return -1;
00055 else
00056 return 0;
00057 }
00058
00059 static int64_t get_s(AVIOContext *bc){
00060 int64_t v = ffio_read_varlen(bc) + 1;
00061
00062 if (v&1) return -(v>>1);
00063 else return (v>>1);
00064 }
00065
00066 static uint64_t get_fourcc(AVIOContext *bc){
00067 unsigned int len= ffio_read_varlen(bc);
00068
00069 if (len==2) return avio_rl16(bc);
00070 else if(len==4) return avio_rl32(bc);
00071 else return -1;
00072 }
00073
00074 #ifdef TRACE
00075 static inline uint64_t get_v_trace(AVIOContext *bc, char *file, char *func, int line){
00076 uint64_t v= ffio_read_varlen(bc);
00077
00078 av_log(NULL, AV_LOG_DEBUG, "get_v %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line);
00079 return v;
00080 }
00081
00082 static inline int64_t get_s_trace(AVIOContext *bc, char *file, char *func, int line){
00083 int64_t v= get_s(bc);
00084
00085 av_log(NULL, AV_LOG_DEBUG, "get_s %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line);
00086 return v;
00087 }
00088
00089 static inline uint64_t get_vb_trace(AVIOContext *bc, char *file, char *func, int line){
00090 uint64_t v= get_vb(bc);
00091
00092 av_log(NULL, AV_LOG_DEBUG, "get_vb %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line);
00093 return v;
00094 }
00095 #define ffio_read_varlen(bc) get_v_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__)
00096 #define get_s(bc) get_s_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__)
00097 #define get_vb(bc) get_vb_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__)
00098 #endif
00099
00100 static int get_packetheader(NUTContext *nut, AVIOContext *bc, int calculate_checksum, uint64_t startcode)
00101 {
00102 int64_t size;
00103
00104
00105 startcode= av_be2ne64(startcode);
00106 startcode= ff_crc04C11DB7_update(0, (uint8_t*)&startcode, 8);
00107
00108 ffio_init_checksum(bc, ff_crc04C11DB7_update, startcode);
00109 size= ffio_read_varlen(bc);
00110 if(size > 4096)
00111 avio_rb32(bc);
00112 if(ffio_get_checksum(bc) && size > 4096)
00113 return -1;
00114
00115 ffio_init_checksum(bc, calculate_checksum ? ff_crc04C11DB7_update : NULL, 0);
00116
00117 return size;
00118 }
00119
00120 static uint64_t find_any_startcode(AVIOContext *bc, int64_t pos){
00121 uint64_t state=0;
00122
00123 if(pos >= 0)
00124 avio_seek(bc, pos, SEEK_SET);
00125
00126 while(!url_feof(bc)){
00127 state= (state<<8) | avio_r8(bc);
00128 if((state>>56) != 'N')
00129 continue;
00130 switch(state){
00131 case MAIN_STARTCODE:
00132 case STREAM_STARTCODE:
00133 case SYNCPOINT_STARTCODE:
00134 case INFO_STARTCODE:
00135 case INDEX_STARTCODE:
00136 return state;
00137 }
00138 }
00139
00140 return 0;
00141 }
00142
00149 static int64_t find_startcode(AVIOContext *bc, uint64_t code, int64_t pos){
00150 for(;;){
00151 uint64_t startcode= find_any_startcode(bc, pos);
00152 if(startcode == code)
00153 return avio_tell(bc) - 8;
00154 else if(startcode == 0)
00155 return -1;
00156 pos=-1;
00157 }
00158 }
00159
00160 static int nut_probe(AVProbeData *p){
00161 int i;
00162 uint64_t code= 0;
00163
00164 for (i = 0; i < p->buf_size; i++) {
00165 code = (code << 8) | p->buf[i];
00166 if (code == MAIN_STARTCODE)
00167 return AVPROBE_SCORE_MAX;
00168 }
00169 return 0;
00170 }
00171
00172 #define GET_V(dst, check) \
00173 tmp= ffio_read_varlen(bc);\
00174 if(!(check)){\
00175 av_log(s, AV_LOG_ERROR, "Error " #dst " is (%"PRId64")\n", tmp);\
00176 return -1;\
00177 }\
00178 dst= tmp;
00179
00180 static int skip_reserved(AVIOContext *bc, int64_t pos){
00181 pos -= avio_tell(bc);
00182 if(pos<0){
00183 avio_seek(bc, pos, SEEK_CUR);
00184 return -1;
00185 }else{
00186 while(pos--)
00187 avio_r8(bc);
00188 return 0;
00189 }
00190 }
00191
00192 static int decode_main_header(NUTContext *nut){
00193 AVFormatContext *s= nut->avf;
00194 AVIOContext *bc = s->pb;
00195 uint64_t tmp, end;
00196 unsigned int stream_count;
00197 int i, j, tmp_stream, tmp_mul, tmp_pts, tmp_size, count, tmp_res, tmp_head_idx;
00198
00199 end= get_packetheader(nut, bc, 1, MAIN_STARTCODE);
00200 end += avio_tell(bc);
00201
00202 GET_V(tmp , tmp >=2 && tmp <= 3)
00203 GET_V(stream_count , tmp > 0 && tmp <= NUT_MAX_STREAMS)
00204
00205 nut->max_distance = ffio_read_varlen(bc);
00206 if(nut->max_distance > 65536){
00207 av_log(s, AV_LOG_DEBUG, "max_distance %d\n", nut->max_distance);
00208 nut->max_distance= 65536;
00209 }
00210
00211 GET_V(nut->time_base_count, tmp>0 && tmp<INT_MAX / sizeof(AVRational))
00212 nut->time_base= av_malloc(nut->time_base_count * sizeof(AVRational));
00213
00214 for(i=0; i<nut->time_base_count; i++){
00215 GET_V(nut->time_base[i].num, tmp>0 && tmp<(1ULL<<31))
00216 GET_V(nut->time_base[i].den, tmp>0 && tmp<(1ULL<<31))
00217 if(av_gcd(nut->time_base[i].num, nut->time_base[i].den) != 1){
00218 av_log(s, AV_LOG_ERROR, "time base invalid\n");
00219 return AVERROR_INVALIDDATA;
00220 }
00221 }
00222 tmp_pts=0;
00223 tmp_mul=1;
00224 tmp_stream=0;
00225 tmp_head_idx= 0;
00226 for(i=0; i<256;){
00227 int tmp_flags = ffio_read_varlen(bc);
00228 int tmp_fields= ffio_read_varlen(bc);
00229 if(tmp_fields>0) tmp_pts = get_s(bc);
00230 if(tmp_fields>1) tmp_mul = ffio_read_varlen(bc);
00231 if(tmp_fields>2) tmp_stream= ffio_read_varlen(bc);
00232 if(tmp_fields>3) tmp_size = ffio_read_varlen(bc);
00233 else tmp_size = 0;
00234 if(tmp_fields>4) tmp_res = ffio_read_varlen(bc);
00235 else tmp_res = 0;
00236 if(tmp_fields>5) count = ffio_read_varlen(bc);
00237 else count = tmp_mul - tmp_size;
00238 if(tmp_fields>6) get_s(bc);
00239 if(tmp_fields>7) tmp_head_idx= ffio_read_varlen(bc);
00240
00241 while(tmp_fields-- > 8)
00242 ffio_read_varlen(bc);
00243
00244 if(count == 0 || i+count > 256){
00245 av_log(s, AV_LOG_ERROR, "illegal count %d at %d\n", count, i);
00246 return AVERROR_INVALIDDATA;
00247 }
00248 if(tmp_stream >= stream_count){
00249 av_log(s, AV_LOG_ERROR, "illegal stream number\n");
00250 return AVERROR_INVALIDDATA;
00251 }
00252
00253 for(j=0; j<count; j++,i++){
00254 if (i == 'N') {
00255 nut->frame_code[i].flags= FLAG_INVALID;
00256 j--;
00257 continue;
00258 }
00259 nut->frame_code[i].flags = tmp_flags ;
00260 nut->frame_code[i].pts_delta = tmp_pts ;
00261 nut->frame_code[i].stream_id = tmp_stream;
00262 nut->frame_code[i].size_mul = tmp_mul ;
00263 nut->frame_code[i].size_lsb = tmp_size+j;
00264 nut->frame_code[i].reserved_count = tmp_res ;
00265 nut->frame_code[i].header_idx = tmp_head_idx;
00266 }
00267 }
00268 assert(nut->frame_code['N'].flags == FLAG_INVALID);
00269
00270 if(end > avio_tell(bc) + 4){
00271 int rem= 1024;
00272 GET_V(nut->header_count, tmp<128U)
00273 nut->header_count++;
00274 for(i=1; i<nut->header_count; i++){
00275 GET_V(nut->header_len[i], tmp>0 && tmp<256);
00276 rem -= nut->header_len[i];
00277 if(rem < 0){
00278 av_log(s, AV_LOG_ERROR, "invalid elision header\n");
00279 return AVERROR_INVALIDDATA;
00280 }
00281 nut->header[i]= av_malloc(nut->header_len[i]);
00282 avio_read(bc, nut->header[i], nut->header_len[i]);
00283 }
00284 assert(nut->header_len[0]==0);
00285 }
00286
00287 if(skip_reserved(bc, end) || ffio_get_checksum(bc)){
00288 av_log(s, AV_LOG_ERROR, "main header checksum mismatch\n");
00289 return AVERROR_INVALIDDATA;
00290 }
00291
00292 nut->stream = av_mallocz(sizeof(StreamContext)*stream_count);
00293 for(i=0; i<stream_count; i++){
00294 av_new_stream(s, i);
00295 }
00296
00297 return 0;
00298 }
00299
00300 static int decode_stream_header(NUTContext *nut){
00301 AVFormatContext *s= nut->avf;
00302 AVIOContext *bc = s->pb;
00303 StreamContext *stc;
00304 int class, stream_id;
00305 uint64_t tmp, end;
00306 AVStream *st;
00307
00308 end= get_packetheader(nut, bc, 1, STREAM_STARTCODE);
00309 end += avio_tell(bc);
00310
00311 GET_V(stream_id, tmp < s->nb_streams && !nut->stream[tmp].time_base);
00312 stc= &nut->stream[stream_id];
00313
00314 st = s->streams[stream_id];
00315 if (!st)
00316 return AVERROR(ENOMEM);
00317
00318 class = ffio_read_varlen(bc);
00319 tmp = get_fourcc(bc);
00320 st->codec->codec_tag= tmp;
00321 switch(class)
00322 {
00323 case 0:
00324 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00325 st->codec->codec_id = av_codec_get_id(
00326 (const AVCodecTag * const []) { ff_codec_bmp_tags, ff_nut_video_tags, 0 },
00327 tmp);
00328 break;
00329 case 1:
00330 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00331 st->codec->codec_id = ff_codec_get_id(ff_codec_wav_tags, tmp);
00332 break;
00333 case 2:
00334 st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
00335 st->codec->codec_id = ff_codec_get_id(ff_nut_subtitle_tags, tmp);
00336 break;
00337 case 3:
00338 st->codec->codec_type = AVMEDIA_TYPE_DATA;
00339 break;
00340 default:
00341 av_log(s, AV_LOG_ERROR, "unknown stream class (%d)\n", class);
00342 return -1;
00343 }
00344 if(class<3 && st->codec->codec_id == CODEC_ID_NONE)
00345 av_log(s, AV_LOG_ERROR, "Unknown codec tag '0x%04x' for stream number %d\n",
00346 (unsigned int)tmp, stream_id);
00347
00348 GET_V(stc->time_base_id , tmp < nut->time_base_count);
00349 GET_V(stc->msb_pts_shift , tmp < 16);
00350 stc->max_pts_distance= ffio_read_varlen(bc);
00351 GET_V(stc->decode_delay , tmp < 1000);
00352 st->codec->has_b_frames= stc->decode_delay;
00353 ffio_read_varlen(bc);
00354
00355 GET_V(st->codec->extradata_size, tmp < (1<<30));
00356 if(st->codec->extradata_size){
00357 st->codec->extradata= av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
00358 avio_read(bc, st->codec->extradata, st->codec->extradata_size);
00359 }
00360
00361 if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO){
00362 GET_V(st->codec->width , tmp > 0)
00363 GET_V(st->codec->height, tmp > 0)
00364 st->sample_aspect_ratio.num= ffio_read_varlen(bc);
00365 st->sample_aspect_ratio.den= ffio_read_varlen(bc);
00366 if((!st->sample_aspect_ratio.num) != (!st->sample_aspect_ratio.den)){
00367 av_log(s, AV_LOG_ERROR, "invalid aspect ratio %d/%d\n", st->sample_aspect_ratio.num, st->sample_aspect_ratio.den);
00368 return -1;
00369 }
00370 ffio_read_varlen(bc);
00371 }else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO){
00372 GET_V(st->codec->sample_rate , tmp > 0)
00373 ffio_read_varlen(bc);
00374 GET_V(st->codec->channels, tmp > 0)
00375 }
00376 if(skip_reserved(bc, end) || ffio_get_checksum(bc)){
00377 av_log(s, AV_LOG_ERROR, "stream header %d checksum mismatch\n", stream_id);
00378 return -1;
00379 }
00380 stc->time_base= &nut->time_base[stc->time_base_id];
00381 av_set_pts_info(s->streams[stream_id], 63, stc->time_base->num, stc->time_base->den);
00382 return 0;
00383 }
00384
00385 static void set_disposition_bits(AVFormatContext* avf, char* value, int stream_id){
00386 int flag = 0, i;
00387 for (i=0; ff_nut_dispositions[i].flag; ++i) {
00388 if (!strcmp(ff_nut_dispositions[i].str, value))
00389 flag = ff_nut_dispositions[i].flag;
00390 }
00391 if (!flag)
00392 av_log(avf, AV_LOG_INFO, "unknown disposition type '%s'\n", value);
00393 for (i = 0; i < avf->nb_streams; ++i)
00394 if (stream_id == i || stream_id == -1)
00395 avf->streams[i]->disposition |= flag;
00396 }
00397
00398 static int decode_info_header(NUTContext *nut){
00399 AVFormatContext *s= nut->avf;
00400 AVIOContext *bc = s->pb;
00401 uint64_t tmp, chapter_start, chapter_len;
00402 unsigned int stream_id_plus1, count;
00403 int chapter_id, i;
00404 int64_t value, end;
00405 char name[256], str_value[1024], type_str[256];
00406 const char *type;
00407 AVChapter *chapter= NULL;
00408 AVStream *st= NULL;
00409 AVDictionary **metadata = NULL;
00410
00411 end= get_packetheader(nut, bc, 1, INFO_STARTCODE);
00412 end += avio_tell(bc);
00413
00414 GET_V(stream_id_plus1, tmp <= s->nb_streams)
00415 chapter_id = get_s(bc);
00416 chapter_start= ffio_read_varlen(bc);
00417 chapter_len = ffio_read_varlen(bc);
00418 count = ffio_read_varlen(bc);
00419
00420 if(chapter_id && !stream_id_plus1){
00421 int64_t start= chapter_start / nut->time_base_count;
00422 chapter= ff_new_chapter(s, chapter_id,
00423 nut->time_base[chapter_start % nut->time_base_count],
00424 start, start + chapter_len, NULL);
00425 metadata = &chapter->metadata;
00426 } else if(stream_id_plus1) {
00427 st= s->streams[stream_id_plus1 - 1];
00428 metadata = &st->metadata;
00429 } else
00430 metadata = &s->metadata;
00431
00432 for(i=0; i<count; i++){
00433 get_str(bc, name, sizeof(name));
00434 value= get_s(bc);
00435 if(value == -1){
00436 type= "UTF-8";
00437 get_str(bc, str_value, sizeof(str_value));
00438 }else if(value == -2){
00439 get_str(bc, type_str, sizeof(type_str));
00440 type= type_str;
00441 get_str(bc, str_value, sizeof(str_value));
00442 }else if(value == -3){
00443 type= "s";
00444 value= get_s(bc);
00445 }else if(value == -4){
00446 type= "t";
00447 value= ffio_read_varlen(bc);
00448 }else if(value < -4){
00449 type= "r";
00450 get_s(bc);
00451 }else{
00452 type= "v";
00453 }
00454
00455 if (stream_id_plus1 > s->nb_streams) {
00456 av_log(s, AV_LOG_ERROR, "invalid stream id for info packet\n");
00457 continue;
00458 }
00459
00460 if(!strcmp(type, "UTF-8")){
00461 if(chapter_id==0 && !strcmp(name, "Disposition")) {
00462 set_disposition_bits(s, str_value, stream_id_plus1 - 1);
00463 continue;
00464 }
00465 if(metadata && strcasecmp(name,"Uses")
00466 && strcasecmp(name,"Depends") && strcasecmp(name,"Replaces"))
00467 av_dict_set(metadata, name, str_value, 0);
00468 }
00469 }
00470
00471 if(skip_reserved(bc, end) || ffio_get_checksum(bc)){
00472 av_log(s, AV_LOG_ERROR, "info header checksum mismatch\n");
00473 return -1;
00474 }
00475 return 0;
00476 }
00477
00478 static int decode_syncpoint(NUTContext *nut, int64_t *ts, int64_t *back_ptr){
00479 AVFormatContext *s= nut->avf;
00480 AVIOContext *bc = s->pb;
00481 int64_t end, tmp;
00482
00483 nut->last_syncpoint_pos= avio_tell(bc)-8;
00484
00485 end= get_packetheader(nut, bc, 1, SYNCPOINT_STARTCODE);
00486 end += avio_tell(bc);
00487
00488 tmp= ffio_read_varlen(bc);
00489 *back_ptr= nut->last_syncpoint_pos - 16*ffio_read_varlen(bc);
00490 if(*back_ptr < 0)
00491 return -1;
00492
00493 ff_nut_reset_ts(nut, nut->time_base[tmp % nut->time_base_count], tmp / nut->time_base_count);
00494
00495 if(skip_reserved(bc, end) || ffio_get_checksum(bc)){
00496 av_log(s, AV_LOG_ERROR, "sync point checksum mismatch\n");
00497 return -1;
00498 }
00499
00500 *ts= tmp / s->nb_streams * av_q2d(nut->time_base[tmp % s->nb_streams])*AV_TIME_BASE;
00501 ff_nut_add_sp(nut, nut->last_syncpoint_pos, *back_ptr, *ts);
00502
00503 return 0;
00504 }
00505
00506 static int find_and_decode_index(NUTContext *nut){
00507 AVFormatContext *s= nut->avf;
00508 AVIOContext *bc = s->pb;
00509 uint64_t tmp, end;
00510 int i, j, syncpoint_count;
00511 int64_t filesize= avio_size(bc);
00512 int64_t *syncpoints;
00513 int8_t *has_keyframe;
00514 int ret= -1;
00515
00516 avio_seek(bc, filesize-12, SEEK_SET);
00517 avio_seek(bc, filesize-avio_rb64(bc), SEEK_SET);
00518 if(avio_rb64(bc) != INDEX_STARTCODE){
00519 av_log(s, AV_LOG_ERROR, "no index at the end\n");
00520 return -1;
00521 }
00522
00523 end= get_packetheader(nut, bc, 1, INDEX_STARTCODE);
00524 end += avio_tell(bc);
00525
00526 ffio_read_varlen(bc);
00527 GET_V(syncpoint_count, tmp < INT_MAX/8 && tmp > 0)
00528 syncpoints= av_malloc(sizeof(int64_t)*syncpoint_count);
00529 has_keyframe= av_malloc(sizeof(int8_t)*(syncpoint_count+1));
00530 for(i=0; i<syncpoint_count; i++){
00531 syncpoints[i] = ffio_read_varlen(bc);
00532 if(syncpoints[i] <= 0)
00533 goto fail;
00534 if(i)
00535 syncpoints[i] += syncpoints[i-1];
00536 }
00537
00538 for(i=0; i<s->nb_streams; i++){
00539 int64_t last_pts= -1;
00540 for(j=0; j<syncpoint_count;){
00541 uint64_t x= ffio_read_varlen(bc);
00542 int type= x&1;
00543 int n= j;
00544 x>>=1;
00545 if(type){
00546 int flag= x&1;
00547 x>>=1;
00548 if(n+x >= syncpoint_count + 1){
00549 av_log(s, AV_LOG_ERROR, "index overflow A\n");
00550 goto fail;
00551 }
00552 while(x--)
00553 has_keyframe[n++]= flag;
00554 has_keyframe[n++]= !flag;
00555 }else{
00556 while(x != 1){
00557 if(n>=syncpoint_count + 1){
00558 av_log(s, AV_LOG_ERROR, "index overflow B\n");
00559 goto fail;
00560 }
00561 has_keyframe[n++]= x&1;
00562 x>>=1;
00563 }
00564 }
00565 if(has_keyframe[0]){
00566 av_log(s, AV_LOG_ERROR, "keyframe before first syncpoint in index\n");
00567 goto fail;
00568 }
00569 assert(n<=syncpoint_count+1);
00570 for(; j<n && j<syncpoint_count; j++){
00571 if(has_keyframe[j]){
00572 uint64_t B, A= ffio_read_varlen(bc);
00573 if(!A){
00574 A= ffio_read_varlen(bc);
00575 B= ffio_read_varlen(bc);
00576
00577 }else
00578 B= 0;
00579 av_add_index_entry(
00580 s->streams[i],
00581 16*syncpoints[j-1],
00582 last_pts + A,
00583 0,
00584 0,
00585 AVINDEX_KEYFRAME);
00586 last_pts += A + B;
00587 }
00588 }
00589 }
00590 }
00591
00592 if(skip_reserved(bc, end) || ffio_get_checksum(bc)){
00593 av_log(s, AV_LOG_ERROR, "index checksum mismatch\n");
00594 goto fail;
00595 }
00596 ret= 0;
00597 fail:
00598 av_free(syncpoints);
00599 av_free(has_keyframe);
00600 return ret;
00601 }
00602
00603 static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap)
00604 {
00605 NUTContext *nut = s->priv_data;
00606 AVIOContext *bc = s->pb;
00607 int64_t pos;
00608 int initialized_stream_count;
00609
00610 nut->avf= s;
00611
00612
00613 pos=0;
00614 do{
00615 pos= find_startcode(bc, MAIN_STARTCODE, pos)+1;
00616 if (pos<0+1){
00617 av_log(s, AV_LOG_ERROR, "No main startcode found.\n");
00618 return AVERROR_INVALIDDATA;
00619 }
00620 }while(decode_main_header(nut) < 0);
00621
00622
00623 pos=0;
00624 for(initialized_stream_count=0; initialized_stream_count < s->nb_streams;){
00625 pos= find_startcode(bc, STREAM_STARTCODE, pos)+1;
00626 if (pos<0+1){
00627 av_log(s, AV_LOG_ERROR, "Not all stream headers found.\n");
00628 return AVERROR_INVALIDDATA;
00629 }
00630 if(decode_stream_header(nut) >= 0)
00631 initialized_stream_count++;
00632 }
00633
00634
00635 pos=0;
00636 for(;;){
00637 uint64_t startcode= find_any_startcode(bc, pos);
00638 pos= avio_tell(bc);
00639
00640 if(startcode==0){
00641 av_log(s, AV_LOG_ERROR, "EOF before video frames\n");
00642 return AVERROR_INVALIDDATA;
00643 }else if(startcode == SYNCPOINT_STARTCODE){
00644 nut->next_startcode= startcode;
00645 break;
00646 }else if(startcode != INFO_STARTCODE){
00647 continue;
00648 }
00649
00650 decode_info_header(nut);
00651 }
00652
00653 s->data_offset= pos-8;
00654
00655 if(bc->seekable){
00656 int64_t orig_pos= avio_tell(bc);
00657 find_and_decode_index(nut);
00658 avio_seek(bc, orig_pos, SEEK_SET);
00659 }
00660 assert(nut->next_startcode == SYNCPOINT_STARTCODE);
00661
00662 ff_metadata_conv_ctx(s, NULL, ff_nut_metadata_conv);
00663
00664 return 0;
00665 }
00666
00667 static int decode_frame_header(NUTContext *nut, int64_t *pts, int *stream_id, uint8_t *header_idx, int frame_code){
00668 AVFormatContext *s= nut->avf;
00669 AVIOContext *bc = s->pb;
00670 StreamContext *stc;
00671 int size, flags, size_mul, pts_delta, i, reserved_count;
00672 uint64_t tmp;
00673
00674 if(avio_tell(bc) > nut->last_syncpoint_pos + nut->max_distance){
00675 av_log(s, AV_LOG_ERROR, "Last frame must have been damaged %"PRId64" > %"PRId64" + %d\n", avio_tell(bc), nut->last_syncpoint_pos, nut->max_distance);
00676 return AVERROR_INVALIDDATA;
00677 }
00678
00679 flags = nut->frame_code[frame_code].flags;
00680 size_mul = nut->frame_code[frame_code].size_mul;
00681 size = nut->frame_code[frame_code].size_lsb;
00682 *stream_id = nut->frame_code[frame_code].stream_id;
00683 pts_delta = nut->frame_code[frame_code].pts_delta;
00684 reserved_count = nut->frame_code[frame_code].reserved_count;
00685 *header_idx = nut->frame_code[frame_code].header_idx;
00686
00687 if(flags & FLAG_INVALID)
00688 return AVERROR_INVALIDDATA;
00689 if(flags & FLAG_CODED)
00690 flags ^= ffio_read_varlen(bc);
00691 if(flags & FLAG_STREAM_ID){
00692 GET_V(*stream_id, tmp < s->nb_streams)
00693 }
00694 stc= &nut->stream[*stream_id];
00695 if(flags&FLAG_CODED_PTS){
00696 int coded_pts= ffio_read_varlen(bc);
00697
00698 if(coded_pts < (1<<stc->msb_pts_shift)){
00699 *pts=ff_lsb2full(stc, coded_pts);
00700 }else
00701 *pts=coded_pts - (1<<stc->msb_pts_shift);
00702 }else
00703 *pts= stc->last_pts + pts_delta;
00704 if(flags&FLAG_SIZE_MSB){
00705 size += size_mul*ffio_read_varlen(bc);
00706 }
00707 if(flags&FLAG_MATCH_TIME)
00708 get_s(bc);
00709 if(flags&FLAG_HEADER_IDX)
00710 *header_idx= ffio_read_varlen(bc);
00711 if(flags&FLAG_RESERVED)
00712 reserved_count= ffio_read_varlen(bc);
00713 for(i=0; i<reserved_count; i++)
00714 ffio_read_varlen(bc);
00715
00716 if(*header_idx >= (unsigned)nut->header_count){
00717 av_log(s, AV_LOG_ERROR, "header_idx invalid\n");
00718 return AVERROR_INVALIDDATA;
00719 }
00720 if(size > 4096)
00721 *header_idx=0;
00722 size -= nut->header_len[*header_idx];
00723
00724 if(flags&FLAG_CHECKSUM){
00725 avio_rb32(bc);
00726 }else if(size > 2*nut->max_distance || FFABS(stc->last_pts - *pts) > stc->max_pts_distance){
00727 av_log(s, AV_LOG_ERROR, "frame size > 2max_distance and no checksum\n");
00728 return AVERROR_INVALIDDATA;
00729 }
00730
00731 stc->last_pts= *pts;
00732 stc->last_flags= flags;
00733
00734 return size;
00735 }
00736
00737 static int decode_frame(NUTContext *nut, AVPacket *pkt, int frame_code){
00738 AVFormatContext *s= nut->avf;
00739 AVIOContext *bc = s->pb;
00740 int size, stream_id, discard;
00741 int64_t pts, last_IP_pts;
00742 StreamContext *stc;
00743 uint8_t header_idx;
00744
00745 size= decode_frame_header(nut, &pts, &stream_id, &header_idx, frame_code);
00746 if(size < 0)
00747 return size;
00748
00749 stc= &nut->stream[stream_id];
00750
00751 if (stc->last_flags & FLAG_KEY)
00752 stc->skip_until_key_frame=0;
00753
00754 discard= s->streams[ stream_id ]->discard;
00755 last_IP_pts= s->streams[ stream_id ]->last_IP_pts;
00756 if( (discard >= AVDISCARD_NONKEY && !(stc->last_flags & FLAG_KEY))
00757 ||(discard >= AVDISCARD_BIDIR && last_IP_pts != AV_NOPTS_VALUE && last_IP_pts > pts)
00758 || discard >= AVDISCARD_ALL
00759 || stc->skip_until_key_frame){
00760 avio_skip(bc, size);
00761 return 1;
00762 }
00763
00764 av_new_packet(pkt, size + nut->header_len[header_idx]);
00765 memcpy(pkt->data, nut->header[header_idx], nut->header_len[header_idx]);
00766 pkt->pos= avio_tell(bc);
00767 avio_read(bc, pkt->data + nut->header_len[header_idx], size);
00768
00769 pkt->stream_index = stream_id;
00770 if (stc->last_flags & FLAG_KEY)
00771 pkt->flags |= AV_PKT_FLAG_KEY;
00772 pkt->pts = pts;
00773
00774 return 0;
00775 }
00776
00777 static int nut_read_packet(AVFormatContext *s, AVPacket *pkt)
00778 {
00779 NUTContext *nut = s->priv_data;
00780 AVIOContext *bc = s->pb;
00781 int i, frame_code=0, ret, skip;
00782 int64_t ts, back_ptr;
00783
00784 for(;;){
00785 int64_t pos= avio_tell(bc);
00786 uint64_t tmp= nut->next_startcode;
00787 nut->next_startcode=0;
00788
00789 if(tmp){
00790 pos-=8;
00791 }else{
00792 frame_code = avio_r8(bc);
00793 if(url_feof(bc))
00794 return -1;
00795 if(frame_code == 'N'){
00796 tmp= frame_code;
00797 for(i=1; i<8; i++)
00798 tmp = (tmp<<8) + avio_r8(bc);
00799 }
00800 }
00801 switch(tmp){
00802 case MAIN_STARTCODE:
00803 case STREAM_STARTCODE:
00804 case INDEX_STARTCODE:
00805 skip= get_packetheader(nut, bc, 0, tmp);
00806 avio_skip(bc, skip);
00807 break;
00808 case INFO_STARTCODE:
00809 if(decode_info_header(nut)<0)
00810 goto resync;
00811 break;
00812 case SYNCPOINT_STARTCODE:
00813 if(decode_syncpoint(nut, &ts, &back_ptr)<0)
00814 goto resync;
00815 frame_code = avio_r8(bc);
00816 case 0:
00817 ret= decode_frame(nut, pkt, frame_code);
00818 if(ret==0)
00819 return 0;
00820 else if(ret==1)
00821 break;
00822 default:
00823 resync:
00824 av_log(s, AV_LOG_DEBUG, "syncing from %"PRId64"\n", pos);
00825 tmp= find_any_startcode(bc, nut->last_syncpoint_pos+1);
00826 if(tmp==0)
00827 return AVERROR_INVALIDDATA;
00828 av_log(s, AV_LOG_DEBUG, "sync\n");
00829 nut->next_startcode= tmp;
00830 }
00831 }
00832 }
00833
00834 static int64_t nut_read_timestamp(AVFormatContext *s, int stream_index, int64_t *pos_arg, int64_t pos_limit){
00835 NUTContext *nut = s->priv_data;
00836 AVIOContext *bc = s->pb;
00837 int64_t pos, pts, back_ptr;
00838 av_log(s, AV_LOG_DEBUG, "read_timestamp(X,%d,%"PRId64",%"PRId64")\n", stream_index, *pos_arg, pos_limit);
00839
00840 pos= *pos_arg;
00841 do{
00842 pos= find_startcode(bc, SYNCPOINT_STARTCODE, pos)+1;
00843 if(pos < 1){
00844 assert(nut->next_startcode == 0);
00845 av_log(s, AV_LOG_ERROR, "read_timestamp failed.\n");
00846 return AV_NOPTS_VALUE;
00847 }
00848 }while(decode_syncpoint(nut, &pts, &back_ptr) < 0);
00849 *pos_arg = pos-1;
00850 assert(nut->last_syncpoint_pos == *pos_arg);
00851
00852 av_log(s, AV_LOG_DEBUG, "return %"PRId64" %"PRId64"\n", pts,back_ptr );
00853 if (stream_index == -1) return pts;
00854 else if(stream_index == -2) return back_ptr;
00855
00856 assert(0);
00857 }
00858
00859 static int read_seek(AVFormatContext *s, int stream_index, int64_t pts, int flags){
00860 NUTContext *nut = s->priv_data;
00861 AVStream *st= s->streams[stream_index];
00862 Syncpoint dummy={.ts= pts*av_q2d(st->time_base)*AV_TIME_BASE};
00863 Syncpoint nopts_sp= {.ts= AV_NOPTS_VALUE, .back_ptr= AV_NOPTS_VALUE};
00864 Syncpoint *sp, *next_node[2]= {&nopts_sp, &nopts_sp};
00865 int64_t pos, pos2, ts;
00866 int i;
00867
00868 if(st->index_entries){
00869 int index= av_index_search_timestamp(st, pts, flags);
00870 if(index<0)
00871 return -1;
00872
00873 pos2= st->index_entries[index].pos;
00874 ts = st->index_entries[index].timestamp;
00875 }else{
00876 av_tree_find(nut->syncpoints, &dummy, (void *) ff_nut_sp_pts_cmp,
00877 (void **) next_node);
00878 av_log(s, AV_LOG_DEBUG, "%"PRIu64"-%"PRIu64" %"PRId64"-%"PRId64"\n", next_node[0]->pos, next_node[1]->pos,
00879 next_node[0]->ts , next_node[1]->ts);
00880 pos= av_gen_search(s, -1, dummy.ts, next_node[0]->pos, next_node[1]->pos, next_node[1]->pos,
00881 next_node[0]->ts , next_node[1]->ts, AVSEEK_FLAG_BACKWARD, &ts, nut_read_timestamp);
00882
00883 if(!(flags & AVSEEK_FLAG_BACKWARD)){
00884 dummy.pos= pos+16;
00885 next_node[1]= &nopts_sp;
00886 av_tree_find(nut->syncpoints, &dummy, (void *) ff_nut_sp_pos_cmp,
00887 (void **) next_node);
00888 pos2= av_gen_search(s, -2, dummy.pos, next_node[0]->pos , next_node[1]->pos, next_node[1]->pos,
00889 next_node[0]->back_ptr, next_node[1]->back_ptr, flags, &ts, nut_read_timestamp);
00890 if(pos2>=0)
00891 pos= pos2;
00892
00893 }
00894 dummy.pos= pos;
00895 sp= av_tree_find(nut->syncpoints, &dummy, (void *) ff_nut_sp_pos_cmp,
00896 NULL);
00897
00898 assert(sp);
00899 pos2= sp->back_ptr - 15;
00900 }
00901 av_log(NULL, AV_LOG_DEBUG, "SEEKTO: %"PRId64"\n", pos2);
00902 pos= find_startcode(s->pb, SYNCPOINT_STARTCODE, pos2);
00903 avio_seek(s->pb, pos, SEEK_SET);
00904 av_log(NULL, AV_LOG_DEBUG, "SP: %"PRId64"\n", pos);
00905 if(pos2 > pos || pos2 + 15 < pos){
00906 av_log(NULL, AV_LOG_ERROR, "no syncpoint at backptr pos\n");
00907 }
00908 for(i=0; i<s->nb_streams; i++)
00909 nut->stream[i].skip_until_key_frame=1;
00910
00911 return 0;
00912 }
00913
00914 static int nut_read_close(AVFormatContext *s)
00915 {
00916 NUTContext *nut = s->priv_data;
00917 int i;
00918
00919 av_freep(&nut->time_base);
00920 av_freep(&nut->stream);
00921 ff_nut_free_sp(nut);
00922 for(i = 1; i < nut->header_count; i++)
00923 av_freep(&nut->header[i]);
00924
00925 return 0;
00926 }
00927
00928 #if CONFIG_NUT_DEMUXER
00929 AVInputFormat ff_nut_demuxer = {
00930 "nut",
00931 NULL_IF_CONFIG_SMALL("NUT format"),
00932 sizeof(NUTContext),
00933 nut_probe,
00934 nut_read_header,
00935 nut_read_packet,
00936 nut_read_close,
00937 read_seek,
00938 .extensions = "nut",
00939 .codec_tag = (const AVCodecTag * const []) { ff_codec_bmp_tags, ff_nut_video_tags, ff_codec_wav_tags, ff_nut_subtitle_tags, 0 },
00940 };
00941 #endif