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 -1; \
200 } \
201 dst = tmp; \
202 } while (0)
203
205 {
207 if (pos < 0) {
209 return -1;
210 } else {
211 while (pos--)
213 return 0;
214 }
215 }
216
218 {
222 unsigned int stream_count;
223 int i, j, count;
224 int tmp_stream, tmp_mul, tmp_pts, tmp_size, tmp_res, tmp_head_idx;
225
228
229 GET_V(tmp, tmp >= 2 && tmp <= 3);
231
236 }
237
240
247 }
248 }
249 tmp_pts = 0;
250 tmp_mul = 1;
251 tmp_stream = 0;
252 tmp_head_idx = 0;
253 for (i = 0; i < 256;) {
256
257 if (tmp_fields > 0)
259 if (tmp_fields > 1)
261 if (tmp_fields > 2)
263 if (tmp_fields > 3)
265 else
266 tmp_size = 0;
267 if (tmp_fields > 4)
269 else
270 tmp_res = 0;
271 if (tmp_fields > 5)
273 else
274 count = tmp_mul - tmp_size;
275 if (tmp_fields > 6)
277 if (tmp_fields > 7)
279
280 while (tmp_fields-- > 8)
282
283 if (count == 0 || i + count > 256) {
286 }
287 if (tmp_stream >= stream_count) {
290 }
291
292 for (j = 0; j < count; j++, i++) {
293 if (i == 'N') {
295 j--;
296 continue;
297 }
305 }
306 }
308
310 int rem = 1024;
317 if (rem < 0) {
320 }
322 if (!hdr)
326 }
328 }
329
333 }
334
336 for (i = 0; i < stream_count; i++)
338
339 return 0;
340 }
341
343 {
347 int class, stream_id;
350
353
355 stc = &nut->
stream[stream_id];
357 if (!st)
359
360 class = ffio_read_varlen(bc);
363 switch (class) {
364 case 0:
369 0
370 },
371 tmp);
372 break;
373 case 1:
378 0
379 },
380 tmp);
381 break;
382 case 2:
385 break;
386 case 3:
389 break;
390 default:
392 return -1;
393 }
396 "Unknown codec tag '0x%04x' for stream number %d\n",
397 (unsigned int) tmp, stream_id);
398
402 GET_V(stc->
decode_delay, tmp < 1000);
// sanity limit, raise this if Moore's law is true
405
411 }
412
421 return -1;
422 }
428 }
431 "stream header %d checksum mismatch\n", stream_id);
432 return -1;
433 }
437 return 0;
438 }
439
441 int stream_id)
442 {
443 int flag = 0, i;
444
448 if (!flag)
451 if (stream_id == i || stream_id == -1)
453 }
454
456 {
459 uint64_t tmp, chapter_start, chapter_len;
460 unsigned int stream_id_plus1, count;
461 int chapter_id, i;
463 char name[256], str_value[1024], type_str[256];
464 const char *type;
468
471
472 GET_V(stream_id_plus1, tmp <= s->nb_streams);
473 chapter_id =
get_s(bc);
477
478 if (chapter_id && !stream_id_plus1) {
483 start, start + chapter_len,
NULL);
485 } else if (stream_id_plus1) {
486 st = s->
streams[stream_id_plus1 - 1];
488 } else
490
491 for (i = 0; i < count; i++) {
492 get_str(bc, name,
sizeof(name));
494 if (value == -1) {
495 type = "UTF-8";
496 get_str(bc, str_value,
sizeof(str_value));
497 } else if (value == -2) {
498 get_str(bc, type_str,
sizeof(type_str));
499 type = type_str;
500 get_str(bc, str_value,
sizeof(str_value));
501 } else if (value == -3) {
502 type = "s";
504 } else if (value == -4) {
505 type = "t";
507 } else if (value < -4) {
508 type = "r";
510 } else {
511 type = "v";
512 }
513
516 continue;
517 }
518
519 if (!strcmp(type, "UTF-8")) {
520 if (chapter_id == 0 && !strcmp(name, "Disposition")) {
522 continue;
523 }
524
525 if (stream_id_plus1 && !strcmp(name, "r_frame_rate")) {
526 sscanf(str_value, "%d/%d", &st->r_frame_rate.num, &st->r_frame_rate.den);
527 if (st->r_frame_rate.num >= 1000LL*st->r_frame_rate.den)
528 st->r_frame_rate.num = st->r_frame_rate.den = 0;
529 continue;
530 }
531
535 }
536 }
537
540 return -1;
541 }
542 return 0;
543 }
544
546 {
550 uint64_t tmp;
551
553
556
559 if (*back_ptr < 0)
561
564
568 }
569
573
574 return 0;
575 }
576
577 //FIXME calculate exactly, this is just a good approximation.
579 {
582
584 for(;;){
586 if(ts < 0)
587 break;
588 duration =
FFMAX(duration, ts);
589 pos++;
590 }
591 if(duration > 0)
594 }
595
597 {
601 int i, j, syncpoint_count;
603 int64_t *syncpoints;
604 int8_t *has_keyframe;
605 int ret = -1;
606
607 if(filesize <= 0)
608 return -1;
609
614
617 return -1;
618 }
619
622
624 GET_V(syncpoint_count, tmp < INT_MAX / 8 && tmp > 0);
625 syncpoints =
av_malloc(
sizeof(int64_t) * syncpoint_count);
626 has_keyframe =
av_malloc(
sizeof(int8_t) * (syncpoint_count + 1));
627 for (i = 0; i < syncpoint_count; i++) {
629 if (syncpoints[i] <= 0)
630 goto fail;
631 if (i)
632 syncpoints[i] += syncpoints[i - 1];
633 }
634
637 for (j = 0; j < syncpoint_count;) {
639 int type = x & 1;
640 int n = j;
641 x >>= 1;
642 if (type) {
643 int flag = x & 1;
644 x >>= 1;
645 if (n + x >= syncpoint_count + 1) {
646 av_log(s,
AV_LOG_ERROR,
"index overflow A %d + %"PRIu64
" >= %d\n", n, x, syncpoint_count + 1);
647 goto fail;
648 }
649 while (x--)
650 has_keyframe[n++] = flag;
651 has_keyframe[n++] = !flag;
652 } else {
653 while (x != 1) {
654 if (n >= syncpoint_count + 1) {
656 goto fail;
657 }
658 has_keyframe[n++] = x & 1;
659 x >>= 1;
660 }
661 }
662 if (has_keyframe[0]) {
664 goto fail;
665 }
667 for (; j < n && j < syncpoint_count; j++) {
668 if (has_keyframe[j]) {
670 if (!A) {
673 // eor_pts[j][i] = last_pts + A + B
674 } else
675 B = 0;
679 }
680 }
681 }
682 }
683
686 goto fail;
687 }
688 ret = 0;
689
690 fail:
693 return ret;
694 }
695
697 {
700 int64_t pos;
701 int initialized_stream_count;
702
704
705 /* main header */
706 pos = 0;
707 do {
709 if (pos < 0 + 1) {
712 }
714
715 /* stream headers */
716 pos = 0;
717 for (initialized_stream_count = 0; initialized_stream_count < s->
nb_streams;) {
719 if (pos < 0 + 1) {
722 }
724 initialized_stream_count++;
725 }
726
727 /* info headers */
728 pos = 0;
729 for (;;) {
732
733 if (startcode == 0) {
738 break;
740 continue;
741 }
742
744 }
745
747
752 }
754
756
757 return 0;
758 }
759
761 uint8_t *header_idx,
int frame_code)
762 {
766 int size,
flags, size_mul, pts_delta, i, reserved_count;
767 uint64_t tmp;
768
771 "Last frame must have been damaged %"PRId64" > %"PRId64" + %d\n",
774 }
775
783
789 GET_V(*stream_id, tmp < s->nb_streams);
790 }
791 stc = &nut->
stream[*stream_id];
794 // FIXME check last_pts validity?
797 } else
799 } else
809 for (i = 0; i < reserved_count; i++)
811
815 }
816 if (size > 4096)
817 *header_idx = 0;
819
826 }
827
830
832 }
833
835 {
838 int size, stream_id, discard;
839 int64_t pts, last_IP_pts;
842
844 if (size < 0)
846
847 stc = &nut->
stream[stream_id];
848
851
856 last_IP_pts > pts) ||
860 return 1;
861 }
862
868
873
874 return 0;
875 }
876
878 {
881 int i, frame_code = 0, ret, skip;
882 int64_t ts, back_ptr;
883
884 for (;;) {
888
889 if (tmp) {
890 pos -= 8;
891 } else {
894 return -1;
895 if (frame_code == 'N') {
896 tmp = frame_code;
897 for (i = 1; i < 8; i++)
898 tmp = (tmp << 8) +
avio_r8(bc);
899 }
900 }
901 switch (tmp) {
907 break;
911 break;
916 case 0:
918 if (ret == 0)
919 return 0;
920 else if (ret == 1) // OK but discard packet
921 break;
922 default:
926 if (tmp == 0)
930 }
931 }
932 }
933
935 int64_t *pos_arg, int64_t pos_limit)
936 {
939 int64_t pos, pts, back_ptr;
941 stream_index, *pos_arg, pos_limit);
942
943 pos = *pos_arg;
944 do {
946 if (pos < 1) {
949 }
951 *pos_arg = pos - 1;
953
955 if (stream_index == -2)
956 return back_ptr;
958 return pts;
959 }
960
962 int64_t pts,
int flags)
963 {
968 Syncpoint *
sp, *next_node[2] = { &nopts_sp, &nopts_sp };
969 int64_t pos, pos2, ts;
970 int i;
971
974 if (index < 0)
976 if (index < 0)
977 return -1;
978
981 } else {
983 (void **) next_node);
985 next_node[0]->pos, next_node[1]->pos, next_node[0]->ts,
986 next_node[1]->ts);
988 next_node[1]->
pos, next_node[1]->
pos,
989 next_node[0]->
ts, next_node[1]->
ts,
991
993 dummy.
pos = pos + 16;
994 next_node[1] = &nopts_sp;
996 (void **) next_node);
998 next_node[1]->
pos, next_node[1]->
pos,
1001 if (pos2 >= 0)
1002 pos = pos2;
1003 // FIXME dir but I think it does not matter
1004 }
1008
1011 }
1016 if (pos2 > pos || pos2 + 15 < pos)
1020
1021 return 0;
1022 }
1023
1025 {
1027 int i;
1028
1034
1035 return 0;
1036 }
1037
1048 .extensions = "nut",
1050 };