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