nutdec.c
Go to the documentation of this file.
1 /*
2  * "NUT" Container Format demuxer
3  * Copyright (c) 2004-2006 Michael Niedermayer
4  * Copyright (c) 2003 Alex Beregszaszi
5  *
6  * This file is part of Libav.
7  *
8  * Libav is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * Libav is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with Libav; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 #include "libavutil/avstring.h"
24 #include "libavutil/bswap.h"
25 #include "libavutil/dict.h"
26 #include "libavutil/mathematics.h"
27 #include "libavutil/tree.h"
28 #include "avio_internal.h"
29 #include "nut.h"
30 
31 #undef NDEBUG
32 #include <assert.h>
33 
34 #define NUT_MAX_STREAMS 256 /* arbitrary sanity check value */
35 
36 static int get_str(AVIOContext *bc, char *string, unsigned int maxlen){
37  unsigned int len= ffio_read_varlen(bc);
38 
39  if(len && maxlen)
40  avio_read(bc, string, FFMIN(len, maxlen));
41  while(len > maxlen){
42  avio_r8(bc);
43  len--;
44  }
45 
46  if(maxlen)
47  string[FFMIN(len, maxlen-1)]= 0;
48 
49  if(maxlen == len)
50  return -1;
51  else
52  return 0;
53 }
54 
55 static int64_t get_s(AVIOContext *bc){
56  int64_t v = ffio_read_varlen(bc) + 1;
57 
58  if (v&1) return -(v>>1);
59  else return (v>>1);
60 }
61 
62 static uint64_t get_fourcc(AVIOContext *bc){
63  unsigned int len= ffio_read_varlen(bc);
64 
65  if (len==2) return avio_rl16(bc);
66  else if(len==4) return avio_rl32(bc);
67  else return -1;
68 }
69 
70 #ifdef TRACE
71 static inline uint64_t get_v_trace(AVIOContext *bc, char *file, char *func, int line){
72  uint64_t v= ffio_read_varlen(bc);
73 
74  av_log(NULL, AV_LOG_DEBUG, "get_v %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line);
75  return v;
76 }
77 
78 static inline int64_t get_s_trace(AVIOContext *bc, char *file, char *func, int line){
79  int64_t v= get_s(bc);
80 
81  av_log(NULL, AV_LOG_DEBUG, "get_s %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line);
82  return v;
83 }
84 #define ffio_read_varlen(bc) get_v_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__)
85 #define get_s(bc) get_s_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__)
86 #endif
87 
88 static int get_packetheader(NUTContext *nut, AVIOContext *bc, int calculate_checksum, uint64_t startcode)
89 {
90  int64_t size;
91 // start= avio_tell(bc) - 8;
92 
93  startcode= av_be2ne64(startcode);
94  startcode= ff_crc04C11DB7_update(0, (uint8_t*)&startcode, 8);
95 
97  size= ffio_read_varlen(bc);
98  if(size > 4096)
99  avio_rb32(bc);
100  if(ffio_get_checksum(bc) && size > 4096)
101  return -1;
102 
103  ffio_init_checksum(bc, calculate_checksum ? ff_crc04C11DB7_update : NULL, 0);
104 
105  return size;
106 }
107 
108 static uint64_t find_any_startcode(AVIOContext *bc, int64_t pos){
109  uint64_t state=0;
110 
111  if(pos >= 0)
112  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
113 
114  while(!bc->eof_reached){
115  state= (state<<8) | avio_r8(bc);
116  if((state>>56) != 'N')
117  continue;
118  switch(state){
119  case MAIN_STARTCODE:
120  case STREAM_STARTCODE:
121  case SYNCPOINT_STARTCODE:
122  case INFO_STARTCODE:
123  case INDEX_STARTCODE:
124  return state;
125  }
126  }
127 
128  return 0;
129 }
130 
137 static int64_t find_startcode(AVIOContext *bc, uint64_t code, int64_t pos){
138  for(;;){
139  uint64_t startcode= find_any_startcode(bc, pos);
140  if(startcode == code)
141  return avio_tell(bc) - 8;
142  else if(startcode == 0)
143  return -1;
144  pos=-1;
145  }
146 }
147 
148 static int nut_probe(AVProbeData *p){
149  int i;
150  uint64_t code= 0;
151 
152  for (i = 0; i < p->buf_size; i++) {
153  code = (code << 8) | p->buf[i];
154  if (code == MAIN_STARTCODE)
155  return AVPROBE_SCORE_MAX;
156  }
157  return 0;
158 }
159 
160 #define GET_V(dst, check) \
161  tmp= ffio_read_varlen(bc);\
162  if(!(check)){\
163  av_log(s, AV_LOG_ERROR, "Error " #dst " is (%"PRId64")\n", tmp);\
164  return -1;\
165  }\
166  dst= tmp;
167 
168 static int skip_reserved(AVIOContext *bc, int64_t pos){
169  pos -= avio_tell(bc);
170  if(pos<0){
171  avio_seek(bc, pos, SEEK_CUR);
172  return -1;
173  }else{
174  while(pos--)
175  avio_r8(bc);
176  return 0;
177  }
178 }
179 
181  AVFormatContext *s= nut->avf;
182  AVIOContext *bc = s->pb;
183  uint64_t tmp, end;
184  unsigned int stream_count;
185  int i, j, tmp_stream, tmp_mul, tmp_pts, tmp_size, count, tmp_res, tmp_head_idx;
186 
187  end= get_packetheader(nut, bc, 1, MAIN_STARTCODE);
188  end += avio_tell(bc);
189 
190  GET_V(tmp , tmp >=2 && tmp <= 3)
191  GET_V(stream_count , tmp > 0 && tmp <= NUT_MAX_STREAMS)
192 
193  nut->max_distance = ffio_read_varlen(bc);
194  if(nut->max_distance > 65536){
195  av_log(s, AV_LOG_DEBUG, "max_distance %d\n", nut->max_distance);
196  nut->max_distance= 65536;
197  }
198 
199  GET_V(nut->time_base_count, tmp>0 && tmp<INT_MAX / sizeof(AVRational))
200  nut->time_base= av_malloc(nut->time_base_count * sizeof(AVRational));
201 
202  for(i=0; i<nut->time_base_count; i++){
203  GET_V(nut->time_base[i].num, tmp>0 && tmp<(1ULL<<31))
204  GET_V(nut->time_base[i].den, tmp>0 && tmp<(1ULL<<31))
205  if(av_gcd(nut->time_base[i].num, nut->time_base[i].den) != 1){
206  av_log(s, AV_LOG_ERROR, "time base invalid\n");
207  return AVERROR_INVALIDDATA;
208  }
209  }
210  tmp_pts=0;
211  tmp_mul=1;
212  tmp_stream=0;
213  tmp_head_idx= 0;
214  for(i=0; i<256;){
215  int tmp_flags = ffio_read_varlen(bc);
216  int tmp_fields= ffio_read_varlen(bc);
217  if(tmp_fields>0) tmp_pts = get_s(bc);
218  if(tmp_fields>1) tmp_mul = ffio_read_varlen(bc);
219  if(tmp_fields>2) tmp_stream= ffio_read_varlen(bc);
220  if(tmp_fields>3) tmp_size = ffio_read_varlen(bc);
221  else tmp_size = 0;
222  if(tmp_fields>4) tmp_res = ffio_read_varlen(bc);
223  else tmp_res = 0;
224  if(tmp_fields>5) count = ffio_read_varlen(bc);
225  else count = tmp_mul - tmp_size;
226  if(tmp_fields>6) get_s(bc);
227  if(tmp_fields>7) tmp_head_idx= ffio_read_varlen(bc);
228 
229  while(tmp_fields-- > 8)
230  ffio_read_varlen(bc);
231 
232  if(count == 0 || i+count > 256){
233  av_log(s, AV_LOG_ERROR, "illegal count %d at %d\n", count, i);
234  return AVERROR_INVALIDDATA;
235  }
236  if(tmp_stream >= stream_count){
237  av_log(s, AV_LOG_ERROR, "illegal stream number\n");
238  return AVERROR_INVALIDDATA;
239  }
240 
241  for(j=0; j<count; j++,i++){
242  if (i == 'N') {
243  nut->frame_code[i].flags= FLAG_INVALID;
244  j--;
245  continue;
246  }
247  nut->frame_code[i].flags = tmp_flags ;
248  nut->frame_code[i].pts_delta = tmp_pts ;
249  nut->frame_code[i].stream_id = tmp_stream;
250  nut->frame_code[i].size_mul = tmp_mul ;
251  nut->frame_code[i].size_lsb = tmp_size+j;
252  nut->frame_code[i].reserved_count = tmp_res ;
253  nut->frame_code[i].header_idx = tmp_head_idx;
254  }
255  }
256  assert(nut->frame_code['N'].flags == FLAG_INVALID);
257 
258  if(end > avio_tell(bc) + 4){
259  int rem= 1024;
260  GET_V(nut->header_count, tmp<128U)
261  nut->header_count++;
262  for(i=1; i<nut->header_count; i++){
263  GET_V(nut->header_len[i], tmp>0 && tmp<256);
264  rem -= nut->header_len[i];
265  if(rem < 0){
266  av_log(s, AV_LOG_ERROR, "invalid elision header\n");
267  return AVERROR_INVALIDDATA;
268  }
269  nut->header[i]= av_malloc(nut->header_len[i]);
270  avio_read(bc, nut->header[i], nut->header_len[i]);
271  }
272  assert(nut->header_len[0]==0);
273  }
274 
275  if(skip_reserved(bc, end) || ffio_get_checksum(bc)){
276  av_log(s, AV_LOG_ERROR, "main header checksum mismatch\n");
277  return AVERROR_INVALIDDATA;
278  }
279 
280  nut->stream = av_mallocz(sizeof(StreamContext)*stream_count);
281  for(i=0; i<stream_count; i++){
283  }
284 
285  return 0;
286 }
287 
289  AVFormatContext *s= nut->avf;
290  AVIOContext *bc = s->pb;
291  StreamContext *stc;
292  int class, stream_id;
293  uint64_t tmp, end;
294  AVStream *st;
295 
296  end= get_packetheader(nut, bc, 1, STREAM_STARTCODE);
297  end += avio_tell(bc);
298 
299  GET_V(stream_id, tmp < s->nb_streams && !nut->stream[tmp].time_base);
300  stc= &nut->stream[stream_id];
301 
302  st = s->streams[stream_id];
303  if (!st)
304  return AVERROR(ENOMEM);
305 
306  class = ffio_read_varlen(bc);
307  tmp = get_fourcc(bc);
308  st->codec->codec_tag= tmp;
309  switch(class)
310  {
311  case 0:
314  (const AVCodecTag * const []) { ff_codec_bmp_tags, ff_nut_video_tags, 0 },
315  tmp);
316  break;
317  case 1:
320  break;
321  case 2:
324  break;
325  case 3:
327  break;
328  default:
329  av_log(s, AV_LOG_ERROR, "unknown stream class (%d)\n", class);
330  return -1;
331  }
332  if(class<3 && st->codec->codec_id == CODEC_ID_NONE)
333  av_log(s, AV_LOG_ERROR, "Unknown codec tag '0x%04x' for stream number %d\n",
334  (unsigned int)tmp, stream_id);
335 
336  GET_V(stc->time_base_id , tmp < nut->time_base_count);
337  GET_V(stc->msb_pts_shift , tmp < 16);
339  GET_V(stc->decode_delay , tmp < 1000); //sanity limit, raise this if Moore's law is true
340  st->codec->has_b_frames= stc->decode_delay;
341  ffio_read_varlen(bc); //stream flags
342 
343  GET_V(st->codec->extradata_size, tmp < (1<<30));
344  if(st->codec->extradata_size){
346  avio_read(bc, st->codec->extradata, st->codec->extradata_size);
347  }
348 
349  if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO){
350  GET_V(st->codec->width , tmp > 0)
351  GET_V(st->codec->height, tmp > 0)
354  if((!st->sample_aspect_ratio.num) != (!st->sample_aspect_ratio.den)){
355  av_log(s, AV_LOG_ERROR, "invalid aspect ratio %d/%d\n", st->sample_aspect_ratio.num, st->sample_aspect_ratio.den);
356  return -1;
357  }
358  ffio_read_varlen(bc); /* csp type */
359  }else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO){
360  GET_V(st->codec->sample_rate , tmp > 0)
361  ffio_read_varlen(bc); // samplerate_den
362  GET_V(st->codec->channels, tmp > 0)
363  }
364  if(skip_reserved(bc, end) || ffio_get_checksum(bc)){
365  av_log(s, AV_LOG_ERROR, "stream header %d checksum mismatch\n", stream_id);
366  return -1;
367  }
368  stc->time_base= &nut->time_base[stc->time_base_id];
369  avpriv_set_pts_info(s->streams[stream_id], 63, stc->time_base->num, stc->time_base->den);
370  return 0;
371 }
372 
373 static void set_disposition_bits(AVFormatContext* avf, char* value, int stream_id){
374  int flag = 0, i;
375  for (i=0; ff_nut_dispositions[i].flag; ++i) {
376  if (!strcmp(ff_nut_dispositions[i].str, value))
377  flag = ff_nut_dispositions[i].flag;
378  }
379  if (!flag)
380  av_log(avf, AV_LOG_INFO, "unknown disposition type '%s'\n", value);
381  for (i = 0; i < avf->nb_streams; ++i)
382  if (stream_id == i || stream_id == -1)
383  avf->streams[i]->disposition |= flag;
384 }
385 
387  AVFormatContext *s= nut->avf;
388  AVIOContext *bc = s->pb;
389  uint64_t tmp, chapter_start, chapter_len;
390  unsigned int stream_id_plus1, count;
391  int chapter_id, i;
392  int64_t value, end;
393  char name[256], str_value[1024], type_str[256];
394  const char *type;
395  AVChapter *chapter= NULL;
396  AVStream *st= NULL;
398 
399  end= get_packetheader(nut, bc, 1, INFO_STARTCODE);
400  end += avio_tell(bc);
401 
402  GET_V(stream_id_plus1, tmp <= s->nb_streams)
403  chapter_id = get_s(bc);
404  chapter_start= ffio_read_varlen(bc);
405  chapter_len = ffio_read_varlen(bc);
406  count = ffio_read_varlen(bc);
407 
408  if(chapter_id && !stream_id_plus1){
409  int64_t start= chapter_start / nut->time_base_count;
410  chapter= avpriv_new_chapter(s, chapter_id,
411  nut->time_base[chapter_start % nut->time_base_count],
412  start, start + chapter_len, NULL);
413  metadata = &chapter->metadata;
414  } else if(stream_id_plus1) {
415  st= s->streams[stream_id_plus1 - 1];
416  metadata = &st->metadata;
417  } else
418  metadata = &s->metadata;
419 
420  for(i=0; i<count; i++){
421  get_str(bc, name, sizeof(name));
422  value= get_s(bc);
423  if(value == -1){
424  type= "UTF-8";
425  get_str(bc, str_value, sizeof(str_value));
426  }else if(value == -2){
427  get_str(bc, type_str, sizeof(type_str));
428  type= type_str;
429  get_str(bc, str_value, sizeof(str_value));
430  }else if(value == -3){
431  type= "s";
432  value= get_s(bc);
433  }else if(value == -4){
434  type= "t";
435  value= ffio_read_varlen(bc);
436  }else if(value < -4){
437  type= "r";
438  get_s(bc);
439  }else{
440  type= "v";
441  }
442 
443  if (stream_id_plus1 > s->nb_streams) {
444  av_log(s, AV_LOG_ERROR, "invalid stream id for info packet\n");
445  continue;
446  }
447 
448  if(!strcmp(type, "UTF-8")){
449  if(chapter_id==0 && !strcmp(name, "Disposition")) {
450  set_disposition_bits(s, str_value, stream_id_plus1 - 1);
451  continue;
452  }
453  if(metadata && av_strcasecmp(name,"Uses")
454  && av_strcasecmp(name,"Depends") && av_strcasecmp(name,"Replaces"))
455  av_dict_set(metadata, name, str_value, 0);
456  }
457  }
458 
459  if(skip_reserved(bc, end) || ffio_get_checksum(bc)){
460  av_log(s, AV_LOG_ERROR, "info header checksum mismatch\n");
461  return -1;
462  }
463  return 0;
464 }
465 
466 static int decode_syncpoint(NUTContext *nut, int64_t *ts, int64_t *back_ptr){
467  AVFormatContext *s= nut->avf;
468  AVIOContext *bc = s->pb;
469  int64_t end, tmp;
470 
471  nut->last_syncpoint_pos= avio_tell(bc)-8;
472 
473  end= get_packetheader(nut, bc, 1, SYNCPOINT_STARTCODE);
474  end += avio_tell(bc);
475 
476  tmp= ffio_read_varlen(bc);
477  *back_ptr= nut->last_syncpoint_pos - 16*ffio_read_varlen(bc);
478  if(*back_ptr < 0)
479  return -1;
480 
481  ff_nut_reset_ts(nut, nut->time_base[tmp % nut->time_base_count], tmp / nut->time_base_count);
482 
483  if(skip_reserved(bc, end) || ffio_get_checksum(bc)){
484  av_log(s, AV_LOG_ERROR, "sync point checksum mismatch\n");
485  return -1;
486  }
487 
488  *ts= tmp / s->nb_streams * av_q2d(nut->time_base[tmp % s->nb_streams])*AV_TIME_BASE;
489  ff_nut_add_sp(nut, nut->last_syncpoint_pos, *back_ptr, *ts);
490 
491  return 0;
492 }
493 
495  AVFormatContext *s= nut->avf;
496  AVIOContext *bc = s->pb;
497  uint64_t tmp, end;
498  int i, j, syncpoint_count;
499  int64_t filesize= avio_size(bc);
500  int64_t *syncpoints;
501  int8_t *has_keyframe;
502  int ret= -1;
503 
504  avio_seek(bc, filesize-12, SEEK_SET);
505  avio_seek(bc, filesize-avio_rb64(bc), SEEK_SET);
506  if(avio_rb64(bc) != INDEX_STARTCODE){
507  av_log(s, AV_LOG_ERROR, "no index at the end\n");
508  return -1;
509  }
510 
511  end= get_packetheader(nut, bc, 1, INDEX_STARTCODE);
512  end += avio_tell(bc);
513 
514  ffio_read_varlen(bc); //max_pts
515  GET_V(syncpoint_count, tmp < INT_MAX/8 && tmp > 0)
516  syncpoints= av_malloc(sizeof(int64_t)*syncpoint_count);
517  has_keyframe= av_malloc(sizeof(int8_t)*(syncpoint_count+1));
518  for(i=0; i<syncpoint_count; i++){
519  syncpoints[i] = ffio_read_varlen(bc);
520  if(syncpoints[i] <= 0)
521  goto fail;
522  if(i)
523  syncpoints[i] += syncpoints[i-1];
524  }
525 
526  for(i=0; i<s->nb_streams; i++){
527  int64_t last_pts= -1;
528  for(j=0; j<syncpoint_count;){
529  uint64_t x= ffio_read_varlen(bc);
530  int type= x&1;
531  int n= j;
532  x>>=1;
533  if(type){
534  int flag= x&1;
535  x>>=1;
536  if(n+x >= syncpoint_count + 1){
537  av_log(s, AV_LOG_ERROR, "index overflow A\n");
538  goto fail;
539  }
540  while(x--)
541  has_keyframe[n++]= flag;
542  has_keyframe[n++]= !flag;
543  }else{
544  while(x != 1){
545  if(n>=syncpoint_count + 1){
546  av_log(s, AV_LOG_ERROR, "index overflow B\n");
547  goto fail;
548  }
549  has_keyframe[n++]= x&1;
550  x>>=1;
551  }
552  }
553  if(has_keyframe[0]){
554  av_log(s, AV_LOG_ERROR, "keyframe before first syncpoint in index\n");
555  goto fail;
556  }
557  assert(n<=syncpoint_count+1);
558  for(; j<n && j<syncpoint_count; j++){
559  if(has_keyframe[j]){
560  uint64_t B, A= ffio_read_varlen(bc);
561  if(!A){
562  A= ffio_read_varlen(bc);
563  B= ffio_read_varlen(bc);
564  //eor_pts[j][i] = last_pts + A + B
565  }else
566  B= 0;
568  s->streams[i],
569  16*syncpoints[j-1],
570  last_pts + A,
571  0,
572  0,
574  last_pts += A + B;
575  }
576  }
577  }
578  }
579 
580  if(skip_reserved(bc, end) || ffio_get_checksum(bc)){
581  av_log(s, AV_LOG_ERROR, "index checksum mismatch\n");
582  goto fail;
583  }
584  ret= 0;
585 fail:
586  av_free(syncpoints);
587  av_free(has_keyframe);
588  return ret;
589 }
590 
592 {
593  NUTContext *nut = s->priv_data;
594  AVIOContext *bc = s->pb;
595  int64_t pos;
596  int initialized_stream_count;
597 
598  nut->avf= s;
599 
600  /* main header */
601  pos=0;
602  do{
603  pos= find_startcode(bc, MAIN_STARTCODE, pos)+1;
604  if (pos<0+1){
605  av_log(s, AV_LOG_ERROR, "No main startcode found.\n");
606  return AVERROR_INVALIDDATA;
607  }
608  }while(decode_main_header(nut) < 0);
609 
610  /* stream headers */
611  pos=0;
612  for(initialized_stream_count=0; initialized_stream_count < s->nb_streams;){
613  pos= find_startcode(bc, STREAM_STARTCODE, pos)+1;
614  if (pos<0+1){
615  av_log(s, AV_LOG_ERROR, "Not all stream headers found.\n");
616  return AVERROR_INVALIDDATA;
617  }
618  if(decode_stream_header(nut) >= 0)
619  initialized_stream_count++;
620  }
621 
622  /* info headers */
623  pos=0;
624  for(;;){
625  uint64_t startcode= find_any_startcode(bc, pos);
626  pos= avio_tell(bc);
627 
628  if(startcode==0){
629  av_log(s, AV_LOG_ERROR, "EOF before video frames\n");
630  return AVERROR_INVALIDDATA;
631  }else if(startcode == SYNCPOINT_STARTCODE){
632  nut->next_startcode= startcode;
633  break;
634  }else if(startcode != INFO_STARTCODE){
635  continue;
636  }
637 
638  decode_info_header(nut);
639  }
640 
641  s->data_offset= pos-8;
642 
643  if(bc->seekable){
644  int64_t orig_pos= avio_tell(bc);
646  avio_seek(bc, orig_pos, SEEK_SET);
647  }
648  assert(nut->next_startcode == SYNCPOINT_STARTCODE);
649 
651 
652  return 0;
653 }
654 
655 static int decode_frame_header(NUTContext *nut, int64_t *pts, int *stream_id, uint8_t *header_idx, int frame_code){
656  AVFormatContext *s= nut->avf;
657  AVIOContext *bc = s->pb;
658  StreamContext *stc;
659  int size, flags, size_mul, pts_delta, i, reserved_count;
660  uint64_t tmp;
661 
662  if(avio_tell(bc) > nut->last_syncpoint_pos + nut->max_distance){
663  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);
664  return AVERROR_INVALIDDATA;
665  }
666 
667  flags = nut->frame_code[frame_code].flags;
668  size_mul = nut->frame_code[frame_code].size_mul;
669  size = nut->frame_code[frame_code].size_lsb;
670  *stream_id = nut->frame_code[frame_code].stream_id;
671  pts_delta = nut->frame_code[frame_code].pts_delta;
672  reserved_count = nut->frame_code[frame_code].reserved_count;
673  *header_idx = nut->frame_code[frame_code].header_idx;
674 
675  if(flags & FLAG_INVALID)
676  return AVERROR_INVALIDDATA;
677  if(flags & FLAG_CODED)
678  flags ^= ffio_read_varlen(bc);
679  if(flags & FLAG_STREAM_ID){
680  GET_V(*stream_id, tmp < s->nb_streams)
681  }
682  stc= &nut->stream[*stream_id];
683  if(flags&FLAG_CODED_PTS){
684  int coded_pts= ffio_read_varlen(bc);
685 //FIXME check last_pts validity?
686  if(coded_pts < (1<<stc->msb_pts_shift)){
687  *pts=ff_lsb2full(stc, coded_pts);
688  }else
689  *pts=coded_pts - (1<<stc->msb_pts_shift);
690  }else
691  *pts= stc->last_pts + pts_delta;
692  if(flags&FLAG_SIZE_MSB){
693  size += size_mul*ffio_read_varlen(bc);
694  }
695  if(flags&FLAG_MATCH_TIME)
696  get_s(bc);
697  if(flags&FLAG_HEADER_IDX)
698  *header_idx= ffio_read_varlen(bc);
699  if(flags&FLAG_RESERVED)
700  reserved_count= ffio_read_varlen(bc);
701  for(i=0; i<reserved_count; i++)
702  ffio_read_varlen(bc);
703 
704  if(*header_idx >= (unsigned)nut->header_count){
705  av_log(s, AV_LOG_ERROR, "header_idx invalid\n");
706  return AVERROR_INVALIDDATA;
707  }
708  if(size > 4096)
709  *header_idx=0;
710  size -= nut->header_len[*header_idx];
711 
712  if(flags&FLAG_CHECKSUM){
713  avio_rb32(bc); //FIXME check this
714  }else if(size > 2*nut->max_distance || FFABS(stc->last_pts - *pts) > stc->max_pts_distance){
715  av_log(s, AV_LOG_ERROR, "frame size > 2max_distance and no checksum\n");
716  return AVERROR_INVALIDDATA;
717  }
718 
719  stc->last_pts= *pts;
720  stc->last_flags= flags;
721 
722  return size;
723 }
724 
725 static int decode_frame(NUTContext *nut, AVPacket *pkt, int frame_code){
726  AVFormatContext *s= nut->avf;
727  AVIOContext *bc = s->pb;
728  int size, stream_id, discard;
729  int64_t pts, last_IP_pts;
730  StreamContext *stc;
731  uint8_t header_idx;
732 
733  size= decode_frame_header(nut, &pts, &stream_id, &header_idx, frame_code);
734  if(size < 0)
735  return size;
736 
737  stc= &nut->stream[stream_id];
738 
739  if (stc->last_flags & FLAG_KEY)
740  stc->skip_until_key_frame=0;
741 
742  discard= s->streams[ stream_id ]->discard;
743  last_IP_pts= s->streams[ stream_id ]->last_IP_pts;
744  if( (discard >= AVDISCARD_NONKEY && !(stc->last_flags & FLAG_KEY))
745  ||(discard >= AVDISCARD_BIDIR && last_IP_pts != AV_NOPTS_VALUE && last_IP_pts > pts)
746  || discard >= AVDISCARD_ALL
747  || stc->skip_until_key_frame){
748  avio_skip(bc, size);
749  return 1;
750  }
751 
752  av_new_packet(pkt, size + nut->header_len[header_idx]);
753  memcpy(pkt->data, nut->header[header_idx], nut->header_len[header_idx]);
754  pkt->pos= avio_tell(bc); //FIXME
755  avio_read(bc, pkt->data + nut->header_len[header_idx], size);
756 
757  pkt->stream_index = stream_id;
758  if (stc->last_flags & FLAG_KEY)
759  pkt->flags |= AV_PKT_FLAG_KEY;
760  pkt->pts = pts;
761 
762  return 0;
763 }
764 
766 {
767  NUTContext *nut = s->priv_data;
768  AVIOContext *bc = s->pb;
769  int i, frame_code=0, ret, skip;
770  int64_t ts, back_ptr;
771 
772  for(;;){
773  int64_t pos= avio_tell(bc);
774  uint64_t tmp= nut->next_startcode;
775  nut->next_startcode=0;
776 
777  if(tmp){
778  pos-=8;
779  }else{
780  frame_code = avio_r8(bc);
781  if(bc->eof_reached)
782  return -1;
783  if(frame_code == 'N'){
784  tmp= frame_code;
785  for(i=1; i<8; i++)
786  tmp = (tmp<<8) + avio_r8(bc);
787  }
788  }
789  switch(tmp){
790  case MAIN_STARTCODE:
791  case STREAM_STARTCODE:
792  case INDEX_STARTCODE:
793  skip= get_packetheader(nut, bc, 0, tmp);
794  avio_skip(bc, skip);
795  break;
796  case INFO_STARTCODE:
797  if(decode_info_header(nut)<0)
798  goto resync;
799  break;
800  case SYNCPOINT_STARTCODE:
801  if(decode_syncpoint(nut, &ts, &back_ptr)<0)
802  goto resync;
803  frame_code = avio_r8(bc);
804  case 0:
805  ret= decode_frame(nut, pkt, frame_code);
806  if(ret==0)
807  return 0;
808  else if(ret==1) //ok but discard packet
809  break;
810  default:
811 resync:
812 av_log(s, AV_LOG_DEBUG, "syncing from %"PRId64"\n", pos);
813  tmp= find_any_startcode(bc, nut->last_syncpoint_pos+1);
814  if(tmp==0)
815  return AVERROR_INVALIDDATA;
816 av_log(s, AV_LOG_DEBUG, "sync\n");
817  nut->next_startcode= tmp;
818  }
819  }
820 }
821 
822 static int64_t nut_read_timestamp(AVFormatContext *s, int stream_index, int64_t *pos_arg, int64_t pos_limit){
823  NUTContext *nut = s->priv_data;
824  AVIOContext *bc = s->pb;
825  int64_t pos, pts, back_ptr;
826 av_log(s, AV_LOG_DEBUG, "read_timestamp(X,%d,%"PRId64",%"PRId64")\n", stream_index, *pos_arg, pos_limit);
827 
828  pos= *pos_arg;
829  do{
830  pos= find_startcode(bc, SYNCPOINT_STARTCODE, pos)+1;
831  if(pos < 1){
832  assert(nut->next_startcode == 0);
833  av_log(s, AV_LOG_ERROR, "read_timestamp failed.\n");
834  return AV_NOPTS_VALUE;
835  }
836  }while(decode_syncpoint(nut, &pts, &back_ptr) < 0);
837  *pos_arg = pos-1;
838  assert(nut->last_syncpoint_pos == *pos_arg);
839 
840  av_log(s, AV_LOG_DEBUG, "return %"PRId64" %"PRId64"\n", pts,back_ptr );
841  if (stream_index == -1) return pts;
842  else if(stream_index == -2) return back_ptr;
843 
844 assert(0);
845 }
846 
847 static int read_seek(AVFormatContext *s, int stream_index, int64_t pts, int flags){
848  NUTContext *nut = s->priv_data;
849  AVStream *st= s->streams[stream_index];
850  Syncpoint dummy={.ts= pts*av_q2d(st->time_base)*AV_TIME_BASE};
851  Syncpoint nopts_sp= {.ts= AV_NOPTS_VALUE, .back_ptr= AV_NOPTS_VALUE};
852  Syncpoint *sp, *next_node[2]= {&nopts_sp, &nopts_sp};
853  int64_t pos, pos2, ts;
854  int i;
855 
856  if(st->index_entries){
857  int index= av_index_search_timestamp(st, pts, flags);
858  if(index<0)
859  return -1;
860 
861  pos2= st->index_entries[index].pos;
862  ts = st->index_entries[index].timestamp;
863  }else{
864  av_tree_find(nut->syncpoints, &dummy, (void *) ff_nut_sp_pts_cmp,
865  (void **) next_node);
866  av_log(s, AV_LOG_DEBUG, "%"PRIu64"-%"PRIu64" %"PRId64"-%"PRId64"\n", next_node[0]->pos, next_node[1]->pos,
867  next_node[0]->ts , next_node[1]->ts);
868  pos = ff_gen_search(s, -1, dummy.ts, next_node[0]->pos, next_node[1]->pos, next_node[1]->pos,
869  next_node[0]->ts , next_node[1]->ts, AVSEEK_FLAG_BACKWARD, &ts, nut_read_timestamp);
870 
871  if(!(flags & AVSEEK_FLAG_BACKWARD)){
872  dummy.pos= pos+16;
873  next_node[1]= &nopts_sp;
874  av_tree_find(nut->syncpoints, &dummy, (void *) ff_nut_sp_pos_cmp,
875  (void **) next_node);
876  pos2 = ff_gen_search(s, -2, dummy.pos, next_node[0]->pos , next_node[1]->pos, next_node[1]->pos,
877  next_node[0]->back_ptr, next_node[1]->back_ptr, flags, &ts, nut_read_timestamp);
878  if(pos2>=0)
879  pos= pos2;
880  //FIXME dir but I think it does not matter
881  }
882  dummy.pos= pos;
883  sp= av_tree_find(nut->syncpoints, &dummy, (void *) ff_nut_sp_pos_cmp,
884  NULL);
885 
886  assert(sp);
887  pos2= sp->back_ptr - 15;
888  }
889  av_log(NULL, AV_LOG_DEBUG, "SEEKTO: %"PRId64"\n", pos2);
890  pos= find_startcode(s->pb, SYNCPOINT_STARTCODE, pos2);
891  avio_seek(s->pb, pos, SEEK_SET);
892  av_log(NULL, AV_LOG_DEBUG, "SP: %"PRId64"\n", pos);
893  if(pos2 > pos || pos2 + 15 < pos){
894  av_log(NULL, AV_LOG_ERROR, "no syncpoint at backptr pos\n");
895  }
896  for(i=0; i<s->nb_streams; i++)
897  nut->stream[i].skip_until_key_frame=1;
898 
899  return 0;
900 }
901 
903 {
904  NUTContext *nut = s->priv_data;
905  int i;
906 
907  av_freep(&nut->time_base);
908  av_freep(&nut->stream);
909  ff_nut_free_sp(nut);
910  for(i = 1; i < nut->header_count; i++)
911  av_freep(&nut->header[i]);
912 
913  return 0;
914 }
915 
916 #if CONFIG_NUT_DEMUXER
917 AVInputFormat ff_nut_demuxer = {
918  .name = "nut",
919  .long_name = NULL_IF_CONFIG_SMALL("NUT format"),
920  .priv_data_size = sizeof(NUTContext),
925  .read_seek = read_seek,
926  .extensions = "nut",
927  .codec_tag = (const AVCodecTag * const []) { ff_codec_bmp_tags, ff_nut_video_tags, ff_codec_wav_tags, ff_nut_subtitle_tags, 0 },
928 };
929 #endif