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