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 FFmpeg.
7 *
8 * FFmpeg 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 * FFmpeg 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 FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
32
33 #define NUT_MAX_STREAMS 256 /* arbitrary sanity check value */
34
36 int64_t *pos_arg, int64_t pos_limit);
37
39 {
41
42 if (len && maxlen)
44 while (len > maxlen) {
46 len--;
47 }
48
49 if (maxlen)
50 string[
FFMIN(len, maxlen - 1)] = 0;
51
52 if (maxlen == len)
53 return -1;
54 else
55 return 0;
56 }
57
59 {
61
62 if (v & 1)
63 return -(v >> 1);
64 else
65 return (v >> 1);
66 }
67
69 {
71
72 if (len == 2)
74 else if (len == 4)
76 else {
78 return -1;
79 }
80 }
81
82 #ifdef TRACE
83 static inline uint64_t get_v_trace(
AVIOContext *bc,
const char *file,
85 {
87
89 v, v, file, func, line);
91 }
92
93 static inline int64_t get_s_trace(
AVIOContext *bc,
const char *file,
95 {
97
99 v, v, file, func, line);
101 }
102
103 static inline uint64_t get_4cc_trace(
AVIOContext *bc,
char *file,
105 {
107
109 v, v, file, func, line);
111 }
112 #define ffio_read_varlen(bc) get_v_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__)
113 #define get_s(bc) get_s_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__)
114 #define get_fourcc(bc) get_4cc_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__)
115 #endif
116
118 int calculate_checksum, uint64_t startcode)
119 {
121 // start = avio_tell(bc) - 8;
122
125
128 if (size > 4096)
131 return -1;
132
134
136 }
137
139 {
141
142 if (pos >= 0)
143 /* Note, this may fail if the stream is not seekable, but that should
144 * not matter, as in this case we simply start where we currently are */
147 state = (state << 8) |
avio_r8(bc);
148 if ((state >> 56) != 'N')
149 continue;
150 switch (state) {
157 }
158 }
159
160 return 0;
161 }
162
163 /**
164 * Find the given startcode.
165 * @param code the startcode
166 * @param pos the start position of the search, or -1 if the current position
167 * @return the position of the startcode or -1 if not found
168 */
170 {
171 for (;;) {
173 if (startcode == code)
175 else if (startcode == 0)
176 return -1;
177 pos = -1;
178 }
179 }
180
182 {
183 int i;
184 uint64_t code = 0;
185
187 code = (code << 8) | p->
buf[i];
190 }
191 return 0;
192 }
193
194 #define GET_V(dst, check) \
195 do { \
196 tmp = ffio_read_varlen(bc); \
197 if (!(check)) { \
198 av_log(s, AV_LOG_ERROR, "Error " #dst " is (%"PRId64")\n", tmp); \
199 return AVERROR_INVALIDDATA; \
200 } \
201 dst = tmp; \
202 } while (0)
203
205 {
207 if (pos < 0) {
210 } else {
211 while (pos--)
213 return 0;
214 }
215 }
216
218 {
222 unsigned int stream_count;
224 int tmp_stream, tmp_mul, tmp_pts, tmp_size, tmp_res, tmp_head_idx;
225
228
232 tmp);
234 }
235
237
242 }
243
246
253 }
254 }
255 tmp_pts = 0;
256 tmp_mul = 1;
257 tmp_stream = 0;
258 tmp_head_idx = 0;
259 for (i = 0; i < 256;) {
262
263 if (tmp_fields > 0)
265 if (tmp_fields > 1)
267 if (tmp_fields > 2)
269 if (tmp_fields > 3)
271 else
272 tmp_size = 0;
273 if (tmp_fields > 4)
275 else
276 tmp_res = 0;
277 if (tmp_fields > 5)
279 else
280 count = tmp_mul - tmp_size;
281 if (tmp_fields > 6)
283 if (tmp_fields > 7)
285
286 while (tmp_fields-- > 8)
288
289 if (count == 0 || i + count > 256) {
292 }
293 if (tmp_stream >= stream_count) {
296 }
297
298 for (j = 0; j <
count; j++, i++) {
299 if (i == 'N') {
301 j--;
302 continue;
303 }
311 }
312 }
314
316 int rem = 1024;
323 if (rem < 0) {
326 }
328 if (!hdr)
332 }
334 }
335
339 }
340
342 for (i = 0; i < stream_count; i++)
344
345 return 0;
346 }
347
349 {
353 int class, stream_id;
356
359
361 stc = &nut->
stream[stream_id];
363 if (!st)
365
366 class = ffio_read_varlen(bc);
369 switch (class) {
370 case 0:
375 0
376 },
377 tmp);
378 break;
379 case 1:
384 0
385 },
386 tmp);
387 break;
388 case 2:
391 break;
392 case 3:
395 break;
396 default:
399 }
402 "Unknown codec tag '0x%04x' for stream number %d\n",
403 (unsigned int) tmp, stream_id);
404
408 GET_V(stc->
decode_delay, tmp < 1000);
// sanity limit, raise this if Moore's law is true
411
417 }
418
428 }
434 }
437 "stream header %d checksum mismatch\n", stream_id);
439 }
443 return 0;
444 }
445
447 int stream_id)
448 {
449 int flag = 0, i;
450
454 if (!flag)
457 if (stream_id == i || stream_id == -1)
459 }
460
462 {
465 uint64_t tmp, chapter_start, chapter_len;
466 unsigned int stream_id_plus1,
count;
467 int chapter_id, i;
469 char name[256], str_value[1024], type_str[256];
474
477
478 GET_V(stream_id_plus1, tmp <= s->nb_streams);
479 chapter_id =
get_s(bc);
483
484 if (chapter_id && !stream_id_plus1) {
489 start, start + chapter_len, NULL);
491 } else if (stream_id_plus1) {
492 st = s->
streams[stream_id_plus1 - 1];
494 } else
496
497 for (i = 0; i <
count; i++) {
498 get_str(bc, name,
sizeof(name));
500 if (value == -1) {
501 type = "UTF-8";
502 get_str(bc, str_value,
sizeof(str_value));
503 } else if (value == -2) {
504 get_str(bc, type_str,
sizeof(type_str));
505 type = type_str;
506 get_str(bc, str_value,
sizeof(str_value));
507 } else if (value == -3) {
508 type = "s";
510 } else if (value == -4) {
511 type = "t";
513 } else if (value < -4) {
514 type = "r";
516 } else {
517 type = "v";
518 }
519
522 continue;
523 }
524
525 if (!strcmp(type, "UTF-8")) {
526 if (chapter_id == 0 && !strcmp(name, "Disposition")) {
528 continue;
529 }
530
531 if (stream_id_plus1 && !strcmp(name, "r_frame_rate")) {
535 continue;
536 }
537
541 }
542 }
543
547 }
548 return 0;
549 }
550
552 {
556 uint64_t tmp;
557
559
562
565 if (*back_ptr < 0)
567
570
574 }
575
579
580 return 0;
581 }
582
583 //FIXME calculate exactly, this is just a good approximation.
585 {
588
590
591 if(duration > 0)
594 }
595
597 {
601 int i, j, syncpoint_count;
603 int64_t *syncpoints;
604 uint64_t max_pts;
605 int8_t *has_keyframe;
607
608 if(filesize <= 0)
609 return -1;
610
615
619 }
620
623
629
630 GET_V(syncpoint_count, tmp < INT_MAX / 8 && tmp > 0);
631 syncpoints =
av_malloc(
sizeof(int64_t) * syncpoint_count);
632 has_keyframe =
av_malloc(
sizeof(int8_t) * (syncpoint_count + 1));
633 for (i = 0; i < syncpoint_count; i++) {
635 if (syncpoints[i] <= 0)
636 goto fail;
637 if (i)
638 syncpoints[i] += syncpoints[i - 1];
639 }
640
643 for (j = 0; j < syncpoint_count;) {
647 x >>= 1;
648 if (type) {
649 int flag = x & 1;
650 x >>= 1;
651 if (n + x >= syncpoint_count + 1) {
652 av_log(s,
AV_LOG_ERROR,
"index overflow A %d + %"PRIu64
" >= %d\n", n, x, syncpoint_count + 1);
653 goto fail;
654 }
655 while (x--)
656 has_keyframe[n++] = flag;
657 has_keyframe[n++] = !flag;
658 } else {
659 while (x != 1) {
660 if (n >= syncpoint_count + 1) {
662 goto fail;
663 }
664 has_keyframe[n++] = x & 1;
665 x >>= 1;
666 }
667 }
668 if (has_keyframe[0]) {
670 goto fail;
671 }
673 for (; j < n && j < syncpoint_count; j++) {
674 if (has_keyframe[j]) {
676 if (!A) {
679 // eor_pts[j][i] = last_pts + A + B
680 } else
681 B = 0;
685 }
686 }
687 }
688 }
689
692 goto fail;
693 }
694 ret = 0;
695
696 fail:
700 }
701
703 {
706 int64_t pos;
707 int initialized_stream_count;
708
710
711 /* main header */
712 pos = 0;
713 do {
715 if (pos < 0 + 1) {
718 }
720
721 /* stream headers */
722 pos = 0;
723 for (initialized_stream_count = 0; initialized_stream_count < s->
nb_streams;) {
725 if (pos < 0 + 1) {
728 }
730 initialized_stream_count++;
731 }
732
733 /* info headers */
734 pos = 0;
735 for (;;) {
738
739 if (startcode == 0) {
744 break;
746 continue;
747 }
748
750 }
751
753
758 }
760
762
763 return 0;
764 }
765
767 uint8_t *header_idx,
int frame_code)
768 {
772 int size,
flags, size_mul, pts_delta, i, reserved_count;
773 uint64_t tmp;
774
777 "Last frame must have been damaged %"PRId64" > %"PRId64" + %d\n",
780 }
781
789
795 GET_V(*stream_id, tmp < s->nb_streams);
796 }
797 stc = &nut->
stream[*stream_id];
800 // FIXME check last_pts validity?
803 } else
805 } else
815 for (i = 0; i < reserved_count; i++)
817
821 }
822 if (size > 4096)
823 *header_idx = 0;
825
832 }
833
836
838 }
839
841 {
844 int size, stream_id, discard;
845 int64_t pts, last_IP_pts;
848
850 if (size < 0)
852
853 stc = &nut->
stream[stream_id];
854
857
862 last_IP_pts > pts) ||
866 return 1;
867 }
868
874
879
880 return 0;
881 }
882
884 {
887 int i, frame_code = 0,
ret, skip;
888 int64_t ts, back_ptr;
889
890 for (;;) {
894
895 if (tmp) {
896 pos -= 8;
897 } else {
901 if (frame_code == 'N') {
902 tmp = frame_code;
903 for (i = 1; i < 8; i++)
904 tmp = (tmp << 8) +
avio_r8(bc);
905 }
906 }
907 switch (tmp) {
913 break;
917 break;
922 case 0:
925 return 0;
926 else if (
ret == 1)
// OK but discard packet
927 break;
928 default:
932 if (tmp == 0)
936 }
937 }
938 }
939
941 int64_t *pos_arg, int64_t pos_limit)
942 {
945 int64_t pos, pts, back_ptr;
947 stream_index, *pos_arg, pos_limit);
948
949 pos = *pos_arg;
950 do {
952 if (pos < 1) {
955 }
957 *pos_arg = pos - 1;
959
961 if (stream_index == -2)
962 return back_ptr;
964 return pts;
965 }
966
968 int64_t pts,
int flags)
969 {
974 Syncpoint *
sp, *next_node[2] = { &nopts_sp, &nopts_sp };
975 int64_t pos, pos2, ts;
976 int i;
977
980 if (index < 0)
982 if (index < 0)
983 return -1;
984
987 } else {
989 (void **) next_node);
991 next_node[0]->pos, next_node[1]->pos, next_node[0]->ts,
992 next_node[1]->ts);
994 next_node[1]->
pos, next_node[1]->
pos,
995 next_node[0]->
ts, next_node[1]->
ts,
997
999 dummy.
pos = pos + 16;
1000 next_node[1] = &nopts_sp;
1002 (void **) next_node);
1004 next_node[1]->
pos, next_node[1]->
pos,
1007 if (pos2 >= 0)
1008 pos = pos2;
1009 // FIXME dir but I think it does not matter
1010 }
1013 NULL);
1014
1017 }
1022 if (pos2 > pos || pos2 + 15 < pos)
1026
1027 return 0;
1028 }
1029
1031 {
1033 int i;
1034
1040
1041 return 0;
1042 }
1043
1054 .extensions = "nut",
1056 };