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