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