2 * "NUT" Container Format demuxer
3 * Copyright (c) 2004-2006 Michael Niedermayer
4 * Copyright (c) 2003 Alex Beregszaszi
6 * This file is part of Libav.
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.
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.
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
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"
35 #define NUT_MAX_STREAMS 256 /* arbitrary sanity check value */
37 static int get_str(AVIOContext
*bc
, char *string
, unsigned int maxlen
)
39 unsigned int len
= ffio_read_varlen(bc
);
42 avio_read(bc
, string
, FFMIN(len
, maxlen
));
43 while (len
> maxlen
) {
49 string
[FFMIN(len
, maxlen
- 1)] = 0;
57 static int64_t get_s(AVIOContext
*bc
)
59 int64_t v
= ffio_read_varlen(bc
) + 1;
67 static uint64_t get_fourcc(AVIOContext
*bc
)
69 unsigned int len
= ffio_read_varlen(bc
);
80 static inline uint64_t get_v_trace(AVIOContext
*bc
, const char *file
,
81 const char *func
, int line
)
83 uint64_t v
= ffio_read_varlen(bc
);
85 av_log(NULL
, AV_LOG_DEBUG
, "get_v %5"PRId64
" / %"PRIX64
" in %s %s:%d\n",
86 v
, v
, file
, func
, line
);
90 static inline int64_t get_s_trace(AVIOContext
*bc
, const char *file
,
91 const char *func
, int line
)
93 int64_t v
= get_s(bc
);
95 av_log(NULL
, AV_LOG_DEBUG
, "get_s %5"PRId64
" / %"PRIX64
" in %s %s:%d\n",
96 v
, v
, file
, func
, line
);
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__)
104 static int get_packetheader(NUTContext
*nut
, AVIOContext
*bc
,
105 int calculate_checksum
, uint64_t startcode
)
108 // start = avio_tell(bc) - 8;
110 startcode
= av_be2ne64(startcode
);
111 startcode
= ff_crc04C11DB7_update(0, (uint8_t*) &startcode
, 8);
113 ffio_init_checksum(bc
, ff_crc04C11DB7_update
, startcode
);
114 size
= ffio_read_varlen(bc
);
117 if (ffio_get_checksum(bc
) && size
> 4096)
120 ffio_init_checksum(bc
, calculate_checksum ? ff_crc04C11DB7_update
: NULL
, 0);
125 static uint64_t find_any_startcode(AVIOContext
*bc
, int64_t pos
)
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')
139 case STREAM_STARTCODE
:
140 case SYNCPOINT_STARTCODE
:
142 case INDEX_STARTCODE
:
151 * Find the given startcode.
152 * @param code the startcode
153 * @param pos the start position of the search, or -1 if the current position
154 * @return the position of the startcode or -1 if not found
156 static int64_t find_startcode(AVIOContext
*bc
, uint64_t code
, int64_t pos
)
159 uint64_t startcode
= find_any_startcode(bc
, pos
);
160 if (startcode
== code
)
161 return avio_tell(bc
) - 8;
162 else if (startcode
== 0)
168 static int nut_probe(AVProbeData
*p
)
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
;
181 #define GET_V(dst, check) \
183 tmp = ffio_read_varlen(bc); \
185 av_log(s, AV_LOG_ERROR, "Error " #dst " is (%"PRId64")\n", tmp); \
186 return AVERROR_INVALIDDATA; \
191 static int skip_reserved(AVIOContext
*bc
, int64_t pos
)
193 pos
-= avio_tell(bc
);
195 avio_seek(bc
, pos
, SEEK_CUR
);
196 return AVERROR_INVALIDDATA
;
204 static int decode_main_header(NUTContext
*nut
)
206 AVFormatContext
*s
= nut
->avf
;
207 AVIOContext
*bc
= s
->pb
;
209 unsigned int stream_count
;
211 int tmp_stream
, tmp_mul
, tmp_pts
, tmp_size
, tmp_res
, tmp_head_idx
;
213 end
= get_packetheader(nut
, bc
, 1, MAIN_STARTCODE
);
214 end
+= avio_tell(bc
);
216 nut
->version
= ffio_read_varlen(bc
);
217 if (nut
->version
< NUT_MIN_VERSION
&&
218 nut
->version
> NUT_MAX_VERSION
) {
219 av_log(s
, AV_LOG_ERROR
, "Version %d not supported.\n",
221 return AVERROR(ENOSYS
);
224 GET_V(stream_count
, tmp
> 0 && tmp
<= NUT_MAX_STREAMS
);
226 nut
->max_distance
= ffio_read_varlen(bc
);
227 if (nut
->max_distance
> 65536) {
228 av_log(s
, AV_LOG_DEBUG
, "max_distance %d\n", nut
->max_distance
);
229 nut
->max_distance
= 65536;
232 GET_V(nut
->time_base_count
, tmp
> 0 && tmp
< INT_MAX
/ sizeof(AVRational
));
233 nut
->time_base
= av_malloc(nut
->time_base_count
* sizeof(AVRational
));
235 return AVERROR(ENOMEM
);
237 for (i
= 0; i
< nut
->time_base_count
; i
++) {
238 GET_V(nut
->time_base
[i
].num
, tmp
> 0 && tmp
< (1ULL << 31));
239 GET_V(nut
->time_base
[i
].den
, tmp
> 0 && tmp
< (1ULL << 31));
240 if (av_gcd(nut
->time_base
[i
].num
, nut
->time_base
[i
].den
) != 1) {
241 av_log(s
, AV_LOG_ERROR
, "invalid time base %d/%d\n",
242 nut
->time_base
[i
].num
,
243 nut
->time_base
[i
].den
);
244 return AVERROR_INVALIDDATA
;
251 for (i
= 0; i
< 256;) {
252 int tmp_flags
= ffio_read_varlen(bc
);
253 int tmp_fields
= ffio_read_varlen(bc
);
258 tmp_mul
= ffio_read_varlen(bc
);
260 tmp_stream
= ffio_read_varlen(bc
);
262 tmp_size
= ffio_read_varlen(bc
);
266 tmp_res
= ffio_read_varlen(bc
);
270 count
= ffio_read_varlen(bc
);
272 count
= tmp_mul
- tmp_size
;
276 tmp_head_idx
= ffio_read_varlen(bc
);
278 while (tmp_fields
-- > 8)
279 ffio_read_varlen(bc
);
281 if (count
== 0 || i
+ count
> 256) {
282 av_log(s
, AV_LOG_ERROR
, "illegal count %d at %d\n", count
, i
);
283 return AVERROR_INVALIDDATA
;
285 if (tmp_stream
>= stream_count
) {
286 av_log(s
, AV_LOG_ERROR
, "illegal stream number %d >= %d\n",
287 tmp_stream
, stream_count
);
288 return AVERROR_INVALIDDATA
;
291 for (j
= 0; j
< count
; j
++, i
++) {
293 nut
->frame_code
[i
].flags
= FLAG_INVALID
;
297 nut
->frame_code
[i
].flags
= tmp_flags
;
298 nut
->frame_code
[i
].pts_delta
= tmp_pts
;
299 nut
->frame_code
[i
].stream_id
= tmp_stream
;
300 nut
->frame_code
[i
].size_mul
= tmp_mul
;
301 nut
->frame_code
[i
].size_lsb
= tmp_size
+ j
;
302 nut
->frame_code
[i
].reserved_count
= tmp_res
;
303 nut
->frame_code
[i
].header_idx
= tmp_head_idx
;
306 assert(nut
->frame_code
['N'].flags
== FLAG_INVALID
);
308 if (end
> avio_tell(bc
) + 4) {
310 GET_V(nut
->header_count
, tmp
< 128U);
312 for (i
= 1; i
< nut
->header_count
; i
++) {
314 GET_V(nut
->header_len
[i
], tmp
> 0 && tmp
< 256);
315 if (rem
< nut
->header_len
[i
]) {
316 av_log(s
, AV_LOG_ERROR
,
317 "invalid elision header %d : %d > %d\n",
318 i
, nut
->header_len
[i
], rem
);
319 return AVERROR_INVALIDDATA
;
321 rem
-= nut
->header_len
[i
];
322 hdr
= av_malloc(nut
->header_len
[i
]);
324 return AVERROR(ENOMEM
);
325 avio_read(bc
, hdr
, nut
->header_len
[i
]);
326 nut
->header
[i
] = hdr
;
328 assert(nut
->header_len
[0] == 0);
331 // flags had been effectively introduced in version 4
332 if (nut
->version
> NUT_STABLE_VERSION
) {
333 nut
->flags
= ffio_read_varlen(bc
);
336 if (skip_reserved(bc
, end
) || ffio_get_checksum(bc
)) {
337 av_log(s
, AV_LOG_ERROR
, "main header checksum mismatch\n");
338 return AVERROR_INVALIDDATA
;
341 nut
->stream
= av_mallocz(sizeof(StreamContext
) * stream_count
);
343 return AVERROR(ENOMEM
);
344 for (i
= 0; i
< stream_count
; i
++)
345 avformat_new_stream(s
, NULL
);
350 static int decode_stream_header(NUTContext
*nut
)
352 AVFormatContext
*s
= nut
->avf
;
353 AVIOContext
*bc
= s
->pb
;
355 int class, stream_id
;
359 end
= get_packetheader(nut
, bc
, 1, STREAM_STARTCODE
);
360 end
+= avio_tell(bc
);
362 GET_V(stream_id
, tmp
< s
->nb_streams
&& !nut
->stream
[tmp
].time_base
);
363 stc
= &nut
->stream
[stream_id
];
364 st
= s
->streams
[stream_id
];
366 return AVERROR(ENOMEM
);
368 class = ffio_read_varlen(bc
);
369 tmp
= get_fourcc(bc
);
370 st
->codec
->codec_tag
= tmp
;
373 st
->codec
->codec_type
= AVMEDIA_TYPE_VIDEO
;
374 st
->codec
->codec_id
= av_codec_get_id((const AVCodecTag
* const []) {
382 st
->codec
->codec_type
= AVMEDIA_TYPE_AUDIO
;
383 st
->codec
->codec_id
= av_codec_get_id((const AVCodecTag
* const []) {
391 st
->codec
->codec_type
= AVMEDIA_TYPE_SUBTITLE
;
392 st
->codec
->codec_id
= ff_codec_get_id(ff_nut_subtitle_tags
, tmp
);
395 st
->codec
->codec_type
= AVMEDIA_TYPE_DATA
;
396 st
->codec
->codec_id
= ff_codec_get_id(ff_nut_data_tags
, tmp
);
399 av_log(s
, AV_LOG_ERROR
, "unknown stream class (%d)\n", class);
400 return AVERROR(ENOSYS
);
402 if (class < 3 && st
->codec
->codec_id
== AV_CODEC_ID_NONE
)
403 av_log(s
, AV_LOG_ERROR
,
404 "Unknown codec tag '0x%04x' for stream number %d\n",
405 (unsigned int) tmp
, stream_id
);
407 GET_V(stc
->time_base_id
, tmp
< nut
->time_base_count
);
408 GET_V(stc
->msb_pts_shift
, tmp
< 16);
409 stc
->max_pts_distance
= ffio_read_varlen(bc
);
410 GET_V(stc
->decode_delay
, tmp
< 1000); // sanity limit, raise this if Moore's law is true
411 ffio_read_varlen(bc
); // stream flags
413 GET_V(st
->codec
->extradata_size
, tmp
< (1 << 30));
414 if (st
->codec
->extradata_size
) {
415 st
->codec
->extradata
= av_mallocz(st
->codec
->extradata_size
+
416 AV_INPUT_BUFFER_PADDING_SIZE
);
417 if (!st
->codec
->extradata
)
418 return AVERROR(ENOMEM
);
419 avio_read(bc
, st
->codec
->extradata
, st
->codec
->extradata_size
);
422 if (st
->codec
->codec_type
== AVMEDIA_TYPE_VIDEO
) {
423 GET_V(st
->codec
->width
, tmp
> 0);
424 GET_V(st
->codec
->height
, tmp
> 0);
425 st
->sample_aspect_ratio
.num
= ffio_read_varlen(bc
);
426 st
->sample_aspect_ratio
.den
= ffio_read_varlen(bc
);
427 if ((!st
->sample_aspect_ratio
.num
) != (!st
->sample_aspect_ratio
.den
)) {
428 av_log(s
, AV_LOG_ERROR
, "invalid aspect ratio %d/%d\n",
429 st
->sample_aspect_ratio
.num
, st
->sample_aspect_ratio
.den
);
430 return AVERROR_INVALIDDATA
;
432 ffio_read_varlen(bc
); /* csp type */
433 } else if (st
->codec
->codec_type
== AVMEDIA_TYPE_AUDIO
) {
434 GET_V(st
->codec
->sample_rate
, tmp
> 0);
435 ffio_read_varlen(bc
); // samplerate_den
436 GET_V(st
->codec
->channels
, tmp
> 0);
438 if (skip_reserved(bc
, end
) || ffio_get_checksum(bc
)) {
439 av_log(s
, AV_LOG_ERROR
,
440 "stream header %d checksum mismatch\n", stream_id
);
441 return AVERROR_INVALIDDATA
;
443 stc
->time_base
= &nut
->time_base
[stc
->time_base_id
];
444 avpriv_set_pts_info(s
->streams
[stream_id
], 63, stc
->time_base
->num
,
445 stc
->time_base
->den
);
449 static void set_disposition_bits(AVFormatContext
*avf
, char *value
,
454 for (i
= 0; ff_nut_dispositions
[i
].flag
; ++i
)
455 if (!strcmp(ff_nut_dispositions
[i
].str
, value
))
456 flag
= ff_nut_dispositions
[i
].flag
;
458 av_log(avf
, AV_LOG_INFO
, "unknown disposition type '%s'\n", value
);
459 for (i
= 0; i
< avf
->nb_streams
; ++i
)
460 if (stream_id
== i
|| stream_id
== -1)
461 avf
->streams
[i
]->disposition
|= flag
;
464 static int decode_info_header(NUTContext
*nut
)
466 AVFormatContext
*s
= nut
->avf
;
467 AVIOContext
*bc
= s
->pb
;
468 uint64_t tmp
, chapter_start
, chapter_len
;
469 unsigned int stream_id_plus1
, count
;
472 char name
[256], str_value
[1024], type_str
[256];
474 int *event_flags
= NULL
;
475 AVChapter
*chapter
= NULL
;
477 AVDictionary
**metadata
= NULL
;
478 int metadata_flag
= 0;
480 end
= get_packetheader(nut
, bc
, 1, INFO_STARTCODE
);
481 end
+= avio_tell(bc
);
483 GET_V(stream_id_plus1
, tmp
<= s
->nb_streams
);
484 chapter_id
= get_s(bc
);
485 chapter_start
= ffio_read_varlen(bc
);
486 chapter_len
= ffio_read_varlen(bc
);
487 count
= ffio_read_varlen(bc
);
489 if (chapter_id
&& !stream_id_plus1
) {
490 int64_t start
= chapter_start
/ nut
->time_base_count
;
491 chapter
= avpriv_new_chapter(s
, chapter_id
,
492 nut
->time_base
[chapter_start
%
493 nut
->time_base_count
],
494 start
, start
+ chapter_len
, NULL
);
496 av_log(s
, AV_LOG_ERROR
, "Could not create chapter.\n");
497 return AVERROR(ENOMEM
);
499 metadata
= &chapter
->metadata
;
500 } else if (stream_id_plus1
) {
501 st
= s
->streams
[stream_id_plus1
- 1];
502 metadata
= &st
->metadata
;
503 event_flags
= &st
->event_flags
;
504 metadata_flag
= AVSTREAM_EVENT_FLAG_METADATA_UPDATED
;
506 metadata
= &s
->metadata
;
507 event_flags
= &s
->event_flags
;
508 metadata_flag
= AVFMT_EVENT_FLAG_METADATA_UPDATED
;
511 for (i
= 0; i
< count
; i
++) {
512 get_str(bc
, name
, sizeof(name
));
516 get_str(bc
, str_value
, sizeof(str_value
));
517 } else if (value
== -2) {
518 get_str(bc
, type_str
, sizeof(type_str
));
520 get_str(bc
, str_value
, sizeof(str_value
));
521 } else if (value
== -3) {
524 } else if (value
== -4) {
526 value
= ffio_read_varlen(bc
);
527 } else if (value
< -4) {
534 if (stream_id_plus1
> s
->nb_streams
) {
535 av_log(s
, AV_LOG_ERROR
, "invalid stream id for info packet\n");
539 if (!strcmp(type
, "UTF-8")) {
540 if (chapter_id
== 0 && !strcmp(name
, "Disposition")) {
541 set_disposition_bits(s
, str_value
, stream_id_plus1
- 1);
544 if (metadata
&& av_strcasecmp(name
, "Uses") &&
545 av_strcasecmp(name
, "Depends") && av_strcasecmp(name
, "Replaces")) {
547 *event_flags
|= metadata_flag
;
548 av_dict_set(metadata
, name
, str_value
, 0);
553 if (skip_reserved(bc
, end
) || ffio_get_checksum(bc
)) {
554 av_log(s
, AV_LOG_ERROR
, "info header checksum mismatch\n");
555 return AVERROR_INVALIDDATA
;
560 static int decode_syncpoint(NUTContext
*nut
, int64_t *ts
, int64_t *back_ptr
)
562 AVFormatContext
*s
= nut
->avf
;
563 AVIOContext
*bc
= s
->pb
;
567 nut
->last_syncpoint_pos
= avio_tell(bc
) - 8;
569 end
= get_packetheader(nut
, bc
, 1, SYNCPOINT_STARTCODE
);
570 end
+= avio_tell(bc
);
572 tmp
= ffio_read_varlen(bc
);
573 *back_ptr
= nut
->last_syncpoint_pos
- 16 * ffio_read_varlen(bc
);
577 ff_nut_reset_ts(nut
, nut
->time_base
[tmp
% nut
->time_base_count
],
578 tmp
/ nut
->time_base_count
);
580 if (nut
->flags
& NUT_BROADCAST
) {
581 tmp
= ffio_read_varlen(bc
);
582 av_log(s
, AV_LOG_VERBOSE
, "Syncpoint wallclock %"PRId64
"\n",
583 av_rescale_q(tmp
/ nut
->time_base_count
,
584 nut
->time_base
[tmp
% nut
->time_base_count
],
588 if (skip_reserved(bc
, end
) || ffio_get_checksum(bc
)) {
589 av_log(s
, AV_LOG_ERROR
, "sync point checksum mismatch\n");
590 return AVERROR_INVALIDDATA
;
593 *ts
= tmp
/ s
->nb_streams
*
594 av_q2d(nut
->time_base
[tmp
% s
->nb_streams
]) * AV_TIME_BASE
;
596 if ((ret
= ff_nut_add_sp(nut
, nut
->last_syncpoint_pos
, *back_ptr
, *ts
)) < 0)
602 static int find_and_decode_index(NUTContext
*nut
)
604 AVFormatContext
*s
= nut
->avf
;
605 AVIOContext
*bc
= s
->pb
;
607 int i
, j
, syncpoint_count
;
608 int64_t filesize
= avio_size(bc
);
610 int8_t *has_keyframe
;
611 int ret
= AVERROR_INVALIDDATA
;
613 avio_seek(bc
, filesize
- 12, SEEK_SET
);
614 avio_seek(bc
, filesize
- avio_rb64(bc
), SEEK_SET
);
615 if (avio_rb64(bc
) != INDEX_STARTCODE
) {
616 av_log(s
, AV_LOG_ERROR
, "no index at the end\n");
620 end
= get_packetheader(nut
, bc
, 1, INDEX_STARTCODE
);
621 end
+= avio_tell(bc
);
623 ffio_read_varlen(bc
); // max_pts
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 if (!syncpoints
|| !has_keyframe
) {
628 ret
= AVERROR(ENOMEM
);
631 for (i
= 0; i
< syncpoint_count
; i
++) {
632 syncpoints
[i
] = ffio_read_varlen(bc
);
633 if (syncpoints
[i
] <= 0)
636 syncpoints
[i
] += syncpoints
[i
- 1];
639 for (i
= 0; i
< s
->nb_streams
; i
++) {
640 int64_t last_pts
= -1;
641 for (j
= 0; j
< syncpoint_count
;) {
642 uint64_t x
= ffio_read_varlen(bc
);
649 if (n
+ x
>= syncpoint_count
+ 1) {
650 av_log(s
, AV_LOG_ERROR
, "index overflow A\n");
654 has_keyframe
[n
++] = flag
;
655 has_keyframe
[n
++] = !flag
;
658 if (n
>= syncpoint_count
+ 1) {
659 av_log(s
, AV_LOG_ERROR
, "index overflow B\n");
662 has_keyframe
[n
++] = x
& 1;
666 if (has_keyframe
[0]) {
667 av_log(s
, AV_LOG_ERROR
, "keyframe before first syncpoint in index\n");
670 assert(n
<= syncpoint_count
+ 1);
671 for (; j
< n
&& j
< syncpoint_count
; j
++) {
672 if (has_keyframe
[j
]) {
673 uint64_t B
, A
= ffio_read_varlen(bc
);
675 A
= ffio_read_varlen(bc
);
676 B
= ffio_read_varlen(bc
);
677 // eor_pts[j][i] = last_pts + A + B
680 av_add_index_entry(s
->streams
[i
], 16 * syncpoints
[j
- 1],
681 last_pts
+ A
, 0, 0, AVINDEX_KEYFRAME
);
688 if (skip_reserved(bc
, end
) || ffio_get_checksum(bc
)) {
689 av_log(s
, AV_LOG_ERROR
, "index checksum mismatch\n");
696 av_free(has_keyframe
);
700 static int nut_read_close(AVFormatContext
*s
)
702 NUTContext
*nut
= s
->priv_data
;
705 av_freep(&nut
->time_base
);
706 av_freep(&nut
->stream
);
708 for (i
= 1; i
< nut
->header_count
; i
++)
709 av_freep(&nut
->header
[i
]);
714 static int nut_read_header(AVFormatContext
*s
)
716 NUTContext
*nut
= s
->priv_data
;
717 AVIOContext
*bc
= s
->pb
;
719 int initialized_stream_count
;
726 pos
= find_startcode(bc
, MAIN_STARTCODE
, pos
) + 1;
728 av_log(s
, AV_LOG_ERROR
, "No main startcode found.\n");
731 } while (decode_main_header(nut
) < 0);
735 for (initialized_stream_count
= 0; initialized_stream_count
< s
->nb_streams
;) {
736 pos
= find_startcode(bc
, STREAM_STARTCODE
, pos
) + 1;
738 av_log(s
, AV_LOG_ERROR
, "Not all stream headers found.\n");
741 if (decode_stream_header(nut
) >= 0)
742 initialized_stream_count
++;
748 uint64_t startcode
= find_any_startcode(bc
, pos
);
751 if (startcode
== 0) {
752 av_log(s
, AV_LOG_ERROR
, "EOF before video frames\n");
754 } else if (startcode
== SYNCPOINT_STARTCODE
) {
755 nut
->next_startcode
= startcode
;
757 } else if (startcode
!= INFO_STARTCODE
) {
761 decode_info_header(nut
);
764 s
->internal
->data_offset
= pos
- 8;
767 int64_t orig_pos
= avio_tell(bc
);
768 find_and_decode_index(nut
);
769 avio_seek(bc
, orig_pos
, SEEK_SET
);
771 assert(nut
->next_startcode
== SYNCPOINT_STARTCODE
);
773 ff_metadata_conv_ctx(s
, NULL
, ff_nut_metadata_conv
);
780 return AVERROR_INVALIDDATA
;
783 static int decode_frame_header(NUTContext
*nut
, int64_t *pts
, int *stream_id
,
784 uint8_t *header_idx
, int frame_code
)
786 AVFormatContext
*s
= nut
->avf
;
787 AVIOContext
*bc
= s
->pb
;
789 int size
, flags
, size_mul
, pts_delta
, i
, reserved_count
;
792 if (!(nut
->flags
& NUT_PIPE
) &&
793 avio_tell(bc
) > nut
->last_syncpoint_pos
+ nut
->max_distance
) {
794 av_log(s
, AV_LOG_ERROR
,
795 "Last frame must have been damaged %"PRId64
" > %"PRId64
" + %d\n",
796 avio_tell(bc
), nut
->last_syncpoint_pos
, nut
->max_distance
);
797 return AVERROR_INVALIDDATA
;
800 flags
= nut
->frame_code
[frame_code
].flags
;
801 size_mul
= nut
->frame_code
[frame_code
].size_mul
;
802 size
= nut
->frame_code
[frame_code
].size_lsb
;
803 *stream_id
= nut
->frame_code
[frame_code
].stream_id
;
804 pts_delta
= nut
->frame_code
[frame_code
].pts_delta
;
805 reserved_count
= nut
->frame_code
[frame_code
].reserved_count
;
806 *header_idx
= nut
->frame_code
[frame_code
].header_idx
;
808 if (flags
& FLAG_INVALID
)
809 return AVERROR_INVALIDDATA
;
810 if (flags
& FLAG_CODED
)
811 flags
^= ffio_read_varlen(bc
);
812 if (flags
& FLAG_STREAM_ID
) {
813 GET_V(*stream_id
, tmp
< s
->nb_streams
);
815 stc
= &nut
->stream
[*stream_id
];
816 if (flags
& FLAG_CODED_PTS
) {
817 int coded_pts
= ffio_read_varlen(bc
);
818 // FIXME check last_pts validity?
819 if (coded_pts
< (1 << stc
->msb_pts_shift
)) {
820 *pts
= ff_lsb2full(stc
, coded_pts
);
822 *pts
= coded_pts
- (1 << stc
->msb_pts_shift
);
824 *pts
= stc
->last_pts
+ pts_delta
;
825 if (flags
& FLAG_SIZE_MSB
)
826 size
+= size_mul
* ffio_read_varlen(bc
);
827 if (flags
& FLAG_MATCH_TIME
)
829 if (flags
& FLAG_HEADER_IDX
)
830 *header_idx
= ffio_read_varlen(bc
);
831 if (flags
& FLAG_RESERVED
)
832 reserved_count
= ffio_read_varlen(bc
);
833 for (i
= 0; i
< reserved_count
; i
++)
834 ffio_read_varlen(bc
);
836 if (*header_idx
>= (unsigned)nut
->header_count
) {
837 av_log(s
, AV_LOG_ERROR
, "header_idx invalid\n");
838 return AVERROR_INVALIDDATA
;
842 size
-= nut
->header_len
[*header_idx
];
844 if (flags
& FLAG_CHECKSUM
) {
845 avio_rb32(bc
); // FIXME check this
846 } else if (!(nut
->flags
& NUT_PIPE
) &&
847 size
> 2 * nut
->max_distance
||
848 FFABS(stc
->last_pts
- *pts
) > stc
->max_pts_distance
) {
849 av_log(s
, AV_LOG_ERROR
, "frame size > 2max_distance and no checksum\n");
850 return AVERROR_INVALIDDATA
;
853 stc
->last_pts
= *pts
;
854 stc
->last_flags
= flags
;
859 static int decode_frame(NUTContext
*nut
, AVPacket
*pkt
, int frame_code
)
861 AVFormatContext
*s
= nut
->avf
;
862 AVIOContext
*bc
= s
->pb
;
863 int size
, stream_id
, discard
, ret
;
864 int64_t pts
, last_IP_pts
;
868 size
= decode_frame_header(nut
, &pts
, &stream_id
, &header_idx
, frame_code
);
872 stc
= &nut
->stream
[stream_id
];
874 if (stc
->last_flags
& FLAG_KEY
)
875 stc
->skip_until_key_frame
= 0;
877 discard
= s
->streams
[stream_id
]->discard
;
878 last_IP_pts
= s
->streams
[stream_id
]->last_IP_pts
;
879 if ((discard
>= AVDISCARD_NONKEY
&& !(stc
->last_flags
& FLAG_KEY
)) ||
880 (discard
>= AVDISCARD_BIDIR
&& last_IP_pts
!= AV_NOPTS_VALUE
&&
881 last_IP_pts
> pts
) ||
882 discard
>= AVDISCARD_ALL
||
883 stc
->skip_until_key_frame
) {
888 ret
= av_new_packet(pkt
, size
+ nut
->header_len
[header_idx
]);
891 memcpy(pkt
->data
, nut
->header
[header_idx
], nut
->header_len
[header_idx
]);
892 pkt
->pos
= avio_tell(bc
); // FIXME
893 avio_read(bc
, pkt
->data
+ nut
->header_len
[header_idx
], size
);
895 pkt
->stream_index
= stream_id
;
896 if (stc
->last_flags
& FLAG_KEY
)
897 pkt
->flags
|= AV_PKT_FLAG_KEY
;
903 static int nut_read_packet(AVFormatContext
*s
, AVPacket
*pkt
)
905 NUTContext
*nut
= s
->priv_data
;
906 AVIOContext
*bc
= s
->pb
;
907 int i
, frame_code
= 0, ret
, skip
;
908 int64_t ts
, back_ptr
;
911 int64_t pos
= avio_tell(bc
);
912 uint64_t tmp
= nut
->next_startcode
;
913 nut
->next_startcode
= 0;
918 frame_code
= avio_r8(bc
);
921 if (frame_code
== 'N') {
923 for (i
= 1; i
< 8; i
++)
924 tmp
= (tmp
<< 8) + avio_r8(bc
);
929 case STREAM_STARTCODE
:
930 case INDEX_STARTCODE
:
931 skip
= get_packetheader(nut
, bc
, 0, tmp
);
935 if (decode_info_header(nut
) < 0)
938 case SYNCPOINT_STARTCODE
:
939 if (decode_syncpoint(nut
, &ts
, &back_ptr
) < 0)
941 frame_code
= avio_r8(bc
);
943 ret
= decode_frame(nut
, pkt
, frame_code
);
946 else if (ret
== 1) // OK but discard packet
950 av_log(s
, AV_LOG_DEBUG
, "syncing from %"PRId64
"\n", pos
);
951 tmp
= find_any_startcode(bc
, nut
->last_syncpoint_pos
+ 1);
953 return AVERROR_INVALIDDATA
;
954 av_log(s
, AV_LOG_DEBUG
, "sync\n");
955 nut
->next_startcode
= tmp
;
960 static int64_t nut_read_timestamp(AVFormatContext
*s
, int stream_index
,
961 int64_t *pos_arg
, int64_t pos_limit
)
963 NUTContext
*nut
= s
->priv_data
;
964 AVIOContext
*bc
= s
->pb
;
965 int64_t pos
, pts
, back_ptr
;
966 av_log(s
, AV_LOG_DEBUG
, "read_timestamp(X,%d,%"PRId64
",%"PRId64
")\n",
967 stream_index
, *pos_arg
, pos_limit
);
971 pos
= find_startcode(bc
, SYNCPOINT_STARTCODE
, pos
) + 1;
973 assert(nut
->next_startcode
== 0);
974 av_log(s
, AV_LOG_ERROR
, "read_timestamp failed.\n");
975 return AV_NOPTS_VALUE
;
977 } while (decode_syncpoint(nut
, &pts
, &back_ptr
) < 0);
979 assert(nut
->last_syncpoint_pos
== *pos_arg
);
981 av_log(s
, AV_LOG_DEBUG
, "return %"PRId64
" %"PRId64
"\n", pts
, back_ptr
);
982 if (stream_index
== -1)
984 else if (stream_index
== -2)
987 return AV_NOPTS_VALUE
;
990 static int read_seek(AVFormatContext
*s
, int stream_index
,
991 int64_t pts
, int flags
)
993 NUTContext
*nut
= s
->priv_data
;
994 AVStream
*st
= s
->streams
[stream_index
];
995 Syncpoint dummy
= { .ts
= pts
* av_q2d(st
->time_base
) * AV_TIME_BASE
};
996 Syncpoint nopts_sp
= { .ts
= AV_NOPTS_VALUE
, .back_ptr
= AV_NOPTS_VALUE
};
997 Syncpoint
*sp
, *next_node
[2] = { &nopts_sp
, &nopts_sp
};
998 int64_t pos
, pos2
, ts
;
1001 if (nut
->flags
& NUT_PIPE
) {
1002 return AVERROR(ENOSYS
);
1005 if (st
->index_entries
) {
1006 int index
= av_index_search_timestamp(st
, pts
, flags
);
1010 pos2
= st
->index_entries
[index
].pos
;
1011 ts
= st
->index_entries
[index
].timestamp
;
1013 av_tree_find(nut
->syncpoints
, &dummy
, (void *) ff_nut_sp_pts_cmp
,
1014 (void **) next_node
);
1015 av_log(s
, AV_LOG_DEBUG
, "%"PRIu64
"-%"PRIu64
" %"PRId64
"-%"PRId64
"\n",
1016 next_node
[0]->pos
, next_node
[1]->pos
, next_node
[0]->ts
,
1018 pos
= ff_gen_search(s
, -1, dummy
.ts
, next_node
[0]->pos
,
1019 next_node
[1]->pos
, next_node
[1]->pos
,
1020 next_node
[0]->ts
, next_node
[1]->ts
,
1021 AVSEEK_FLAG_BACKWARD
, &ts
, nut_read_timestamp
);
1023 if (!(flags
& AVSEEK_FLAG_BACKWARD
)) {
1024 dummy
.pos
= pos
+ 16;
1025 next_node
[1] = &nopts_sp
;
1026 av_tree_find(nut
->syncpoints
, &dummy
, (void *) ff_nut_sp_pos_cmp
,
1027 (void **) next_node
);
1028 pos2
= ff_gen_search(s
, -2, dummy
.pos
, next_node
[0]->pos
,
1029 next_node
[1]->pos
, next_node
[1]->pos
,
1030 next_node
[0]->back_ptr
, next_node
[1]->back_ptr
,
1031 flags
, &ts
, nut_read_timestamp
);
1034 // FIXME dir but I think it does not matter
1037 sp
= av_tree_find(nut
->syncpoints
, &dummy
, (void *) ff_nut_sp_pos_cmp
,
1041 pos2
= sp
->back_ptr
- 15;
1043 av_log(NULL
, AV_LOG_DEBUG
, "SEEKTO: %"PRId64
"\n", pos2
);
1044 pos
= find_startcode(s
->pb
, SYNCPOINT_STARTCODE
, pos2
);
1045 avio_seek(s
->pb
, pos
, SEEK_SET
);
1046 av_log(NULL
, AV_LOG_DEBUG
, "SP: %"PRId64
"\n", pos
);
1047 if (pos2
> pos
|| pos2
+ 15 < pos
)
1048 av_log(NULL
, AV_LOG_ERROR
, "no syncpoint at backptr pos\n");
1049 for (i
= 0; i
< s
->nb_streams
; i
++)
1050 nut
->stream
[i
].skip_until_key_frame
= 1;
1055 AVInputFormat ff_nut_demuxer
= {
1057 .long_name
= NULL_IF_CONFIG_SMALL("NUT"),
1058 .priv_data_size
= sizeof(NUTContext
),
1059 .read_probe
= nut_probe
,
1060 .read_header
= nut_read_header
,
1061 .read_packet
= nut_read_packet
,
1062 .read_close
= nut_read_close
,
1063 .read_seek
= read_seek
,
1064 .extensions
= "nut",
1065 .codec_tag
= ff_nut_codec_tags
,