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); \
191 static int skip_reserved(AVIOContext
*bc
, int64_t pos
)
193 pos
-= avio_tell(bc
);
195 avio_seek(bc
, pos
, SEEK_CUR
);
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 GET_V(tmp
, tmp
>= 2 && tmp
<= 3);
217 GET_V(stream_count
, tmp
> 0 && tmp
<= NUT_MAX_STREAMS
);
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;
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
));
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
;
240 for (i
= 0; i
< 256;) {
241 int tmp_flags
= ffio_read_varlen(bc
);
242 int tmp_fields
= ffio_read_varlen(bc
);
247 tmp_mul
= ffio_read_varlen(bc
);
249 tmp_stream
= ffio_read_varlen(bc
);
251 tmp_size
= ffio_read_varlen(bc
);
255 tmp_res
= ffio_read_varlen(bc
);
259 count
= ffio_read_varlen(bc
);
261 count
= tmp_mul
- tmp_size
;
265 tmp_head_idx
= ffio_read_varlen(bc
);
267 while (tmp_fields
-- > 8)
268 ffio_read_varlen(bc
);
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
;
274 if (tmp_stream
>= stream_count
) {
275 av_log(s
, AV_LOG_ERROR
, "illegal stream number\n");
276 return AVERROR_INVALIDDATA
;
279 for (j
= 0; j
< count
; j
++, i
++) {
281 nut
->frame_code
[i
].flags
= FLAG_INVALID
;
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
;
294 assert(nut
->frame_code
['N'].flags
== FLAG_INVALID
);
296 if (end
> avio_tell(bc
) + 4) {
298 GET_V(nut
->header_count
, tmp
< 128U);
300 for (i
= 1; i
< nut
->header_count
; i
++) {
302 GET_V(nut
->header_len
[i
], tmp
> 0 && tmp
< 256);
303 rem
-= nut
->header_len
[i
];
305 av_log(s
, AV_LOG_ERROR
, "invalid elision header\n");
306 return AVERROR_INVALIDDATA
;
308 hdr
= av_malloc(nut
->header_len
[i
]);
310 return AVERROR(ENOMEM
);
311 avio_read(bc
, hdr
, nut
->header_len
[i
]);
312 nut
->header
[i
] = hdr
;
314 assert(nut
->header_len
[0] == 0);
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
;
322 nut
->stream
= av_mallocz(sizeof(StreamContext
) * stream_count
);
323 for (i
= 0; i
< stream_count
; i
++)
324 avformat_new_stream(s
, NULL
);
329 static int decode_stream_header(NUTContext
*nut
)
331 AVFormatContext
*s
= nut
->avf
;
332 AVIOContext
*bc
= s
->pb
;
334 int class, stream_id
;
338 end
= get_packetheader(nut
, bc
, 1, STREAM_STARTCODE
);
339 end
+= avio_tell(bc
);
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
];
345 return AVERROR(ENOMEM
);
347 class = ffio_read_varlen(bc
);
348 tmp
= get_fourcc(bc
);
349 st
->codec
->codec_tag
= tmp
;
352 st
->codec
->codec_type
= AVMEDIA_TYPE_VIDEO
;
353 st
->codec
->codec_id
= av_codec_get_id((const AVCodecTag
* const []) {
361 st
->codec
->codec_type
= AVMEDIA_TYPE_AUDIO
;
362 st
->codec
->codec_id
= av_codec_get_id((const AVCodecTag
* const []) {
370 st
->codec
->codec_type
= AVMEDIA_TYPE_SUBTITLE
;
371 st
->codec
->codec_id
= ff_codec_get_id(ff_nut_subtitle_tags
, tmp
);
374 st
->codec
->codec_type
= AVMEDIA_TYPE_DATA
;
375 st
->codec
->codec_id
= ff_codec_get_id(ff_nut_data_tags
, tmp
);
378 av_log(s
, AV_LOG_ERROR
, "unknown stream class (%d)\n", class);
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
);
386 GET_V(stc
->time_base_id
, tmp
< nut
->time_base_count
);
387 GET_V(stc
->msb_pts_shift
, tmp
< 16);
388 stc
->max_pts_distance
= ffio_read_varlen(bc
);
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
393 GET_V(st
->codec
->extradata_size
, tmp
< (1 << 30));
394 if (st
->codec
->extradata_size
) {
395 st
->codec
->extradata
= av_mallocz(st
->codec
->extradata_size
+
396 FF_INPUT_BUFFER_PADDING_SIZE
);
397 avio_read(bc
, st
->codec
->extradata
, st
->codec
->extradata_size
);
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);
403 st
->sample_aspect_ratio
.num
= ffio_read_varlen(bc
);
404 st
->sample_aspect_ratio
.den
= ffio_read_varlen(bc
);
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",
407 st
->sample_aspect_ratio
.num
, st
->sample_aspect_ratio
.den
);
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);
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
);
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
);
427 static void set_disposition_bits(AVFormatContext
*avf
, char *value
,
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
;
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
;
442 static int decode_info_header(NUTContext
*nut
)
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
;
450 char name
[256], str_value
[1024], type_str
[256];
452 AVChapter
*chapter
= NULL
;
454 AVDictionary
**metadata
= NULL
;
456 end
= get_packetheader(nut
, bc
, 1, INFO_STARTCODE
);
457 end
+= avio_tell(bc
);
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
);
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
;
476 metadata
= &s
->metadata
;
478 for (i
= 0; i
< count
; i
++) {
479 get_str(bc
, name
, sizeof(name
));
483 get_str(bc
, str_value
, sizeof(str_value
));
484 } else if (value
== -2) {
485 get_str(bc
, type_str
, sizeof(type_str
));
487 get_str(bc
, str_value
, sizeof(str_value
));
488 } else if (value
== -3) {
491 } else if (value
== -4) {
493 value
= ffio_read_varlen(bc
);
494 } else if (value
< -4) {
501 if (stream_id_plus1
> s
->nb_streams
) {
502 av_log(s
, AV_LOG_ERROR
, "invalid stream id for info packet\n");
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);
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);
517 if (skip_reserved(bc
, end
) || ffio_get_checksum(bc
)) {
518 av_log(s
, AV_LOG_ERROR
, "info header checksum mismatch\n");
524 static int decode_syncpoint(NUTContext
*nut
, int64_t *ts
, int64_t *back_ptr
)
526 AVFormatContext
*s
= nut
->avf
;
527 AVIOContext
*bc
= s
->pb
;
530 nut
->last_syncpoint_pos
= avio_tell(bc
) - 8;
532 end
= get_packetheader(nut
, bc
, 1, SYNCPOINT_STARTCODE
);
533 end
+= avio_tell(bc
);
535 tmp
= ffio_read_varlen(bc
);
536 *back_ptr
= nut
->last_syncpoint_pos
- 16 * ffio_read_varlen(bc
);
540 ff_nut_reset_ts(nut
, nut
->time_base
[tmp
% nut
->time_base_count
],
541 tmp
/ nut
->time_base_count
);
543 if (skip_reserved(bc
, end
) || ffio_get_checksum(bc
)) {
544 av_log(s
, AV_LOG_ERROR
, "sync point checksum mismatch\n");
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
);
555 static int find_and_decode_index(NUTContext
*nut
)
557 AVFormatContext
*s
= nut
->avf
;
558 AVIOContext
*bc
= s
->pb
;
560 int i
, j
, syncpoint_count
;
561 int64_t filesize
= avio_size(bc
);
563 int8_t *has_keyframe
;
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");
573 end
= get_packetheader(nut
, bc
, 1, INDEX_STARTCODE
);
574 end
+= avio_tell(bc
);
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)
585 syncpoints
[i
] += syncpoints
[i
- 1];
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
);
598 if (n
+ x
>= syncpoint_count
+ 1) {
599 av_log(s
, AV_LOG_ERROR
, "index overflow A\n");
603 has_keyframe
[n
++] = flag
;
604 has_keyframe
[n
++] = !flag
;
607 if (n
>= syncpoint_count
+ 1) {
608 av_log(s
, AV_LOG_ERROR
, "index overflow B\n");
611 has_keyframe
[n
++] = x
& 1;
615 if (has_keyframe
[0]) {
616 av_log(s
, AV_LOG_ERROR
, "keyframe before first syncpoint in index\n");
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
);
624 A
= ffio_read_varlen(bc
);
625 B
= ffio_read_varlen(bc
);
626 // eor_pts[j][i] = last_pts + A + B
629 av_add_index_entry(s
->streams
[i
], 16 * syncpoints
[j
- 1],
630 last_pts
+ A
, 0, 0, AVINDEX_KEYFRAME
);
637 if (skip_reserved(bc
, end
) || ffio_get_checksum(bc
)) {
638 av_log(s
, AV_LOG_ERROR
, "index checksum mismatch\n");
645 av_free(has_keyframe
);
649 static int nut_read_header(AVFormatContext
*s
)
651 NUTContext
*nut
= s
->priv_data
;
652 AVIOContext
*bc
= s
->pb
;
654 int initialized_stream_count
;
661 pos
= find_startcode(bc
, MAIN_STARTCODE
, pos
) + 1;
663 av_log(s
, AV_LOG_ERROR
, "No main startcode found.\n");
664 return AVERROR_INVALIDDATA
;
666 } while (decode_main_header(nut
) < 0);
670 for (initialized_stream_count
= 0; initialized_stream_count
< s
->nb_streams
;) {
671 pos
= find_startcode(bc
, STREAM_STARTCODE
, pos
) + 1;
673 av_log(s
, AV_LOG_ERROR
, "Not all stream headers found.\n");
674 return AVERROR_INVALIDDATA
;
676 if (decode_stream_header(nut
) >= 0)
677 initialized_stream_count
++;
683 uint64_t startcode
= find_any_startcode(bc
, pos
);
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
;
692 } else if (startcode
!= INFO_STARTCODE
) {
696 decode_info_header(nut
);
699 s
->data_offset
= pos
- 8;
702 int64_t orig_pos
= avio_tell(bc
);
703 find_and_decode_index(nut
);
704 avio_seek(bc
, orig_pos
, SEEK_SET
);
706 assert(nut
->next_startcode
== SYNCPOINT_STARTCODE
);
708 ff_metadata_conv_ctx(s
, NULL
, ff_nut_metadata_conv
);
713 static int decode_frame_header(NUTContext
*nut
, int64_t *pts
, int *stream_id
,
714 uint8_t *header_idx
, int frame_code
)
716 AVFormatContext
*s
= nut
->avf
;
717 AVIOContext
*bc
= s
->pb
;
719 int size
, flags
, size_mul
, pts_delta
, i
, reserved_count
;
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
;
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
;
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
);
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
);
751 *pts
= coded_pts
- (1 << stc
->msb_pts_shift
);
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
)
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
);
765 if (*header_idx
>= (unsigned)nut
->header_count
) {
766 av_log(s
, AV_LOG_ERROR
, "header_idx invalid\n");
767 return AVERROR_INVALIDDATA
;
771 size
-= nut
->header_len
[*header_idx
];
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
;
781 stc
->last_pts
= *pts
;
782 stc
->last_flags
= flags
;
787 static int decode_frame(NUTContext
*nut
, AVPacket
*pkt
, int frame_code
)
789 AVFormatContext
*s
= nut
->avf
;
790 AVIOContext
*bc
= s
->pb
;
791 int size
, stream_id
, discard
;
792 int64_t pts
, last_IP_pts
;
796 size
= decode_frame_header(nut
, &pts
, &stream_id
, &header_idx
, frame_code
);
800 stc
= &nut
->stream
[stream_id
];
802 if (stc
->last_flags
& FLAG_KEY
)
803 stc
->skip_until_key_frame
= 0;
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
) {
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
);
821 pkt
->stream_index
= stream_id
;
822 if (stc
->last_flags
& FLAG_KEY
)
823 pkt
->flags
|= AV_PKT_FLAG_KEY
;
829 static int nut_read_packet(AVFormatContext
*s
, AVPacket
*pkt
)
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
;
837 int64_t pos
= avio_tell(bc
);
838 uint64_t tmp
= nut
->next_startcode
;
839 nut
->next_startcode
= 0;
844 frame_code
= avio_r8(bc
);
847 if (frame_code
== 'N') {
849 for (i
= 1; i
< 8; i
++)
850 tmp
= (tmp
<< 8) + avio_r8(bc
);
855 case STREAM_STARTCODE
:
856 case INDEX_STARTCODE
:
857 skip
= get_packetheader(nut
, bc
, 0, tmp
);
861 if (decode_info_header(nut
) < 0)
864 case SYNCPOINT_STARTCODE
:
865 if (decode_syncpoint(nut
, &ts
, &back_ptr
) < 0)
867 frame_code
= avio_r8(bc
);
869 ret
= decode_frame(nut
, pkt
, frame_code
);
872 else if (ret
== 1) // OK but discard packet
876 av_log(s
, AV_LOG_DEBUG
, "syncing from %"PRId64
"\n", pos
);
877 tmp
= find_any_startcode(bc
, nut
->last_syncpoint_pos
+ 1);
879 return AVERROR_INVALIDDATA
;
880 av_log(s
, AV_LOG_DEBUG
, "sync\n");
881 nut
->next_startcode
= tmp
;
886 static int64_t nut_read_timestamp(AVFormatContext
*s
, int stream_index
,
887 int64_t *pos_arg
, int64_t pos_limit
)
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
);
897 pos
= find_startcode(bc
, SYNCPOINT_STARTCODE
, pos
) + 1;
899 assert(nut
->next_startcode
== 0);
900 av_log(s
, AV_LOG_ERROR
, "read_timestamp failed.\n");
901 return AV_NOPTS_VALUE
;
903 } while (decode_syncpoint(nut
, &pts
, &back_ptr
) < 0);
905 assert(nut
->last_syncpoint_pos
== *pos_arg
);
907 av_log(s
, AV_LOG_DEBUG
, "return %"PRId64
" %"PRId64
"\n", pts
, back_ptr
);
908 if (stream_index
== -1)
910 else if (stream_index
== -2)
913 return AV_NOPTS_VALUE
;
916 static int read_seek(AVFormatContext
*s
, int stream_index
,
917 int64_t pts
, int flags
)
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
;
927 if (st
->index_entries
) {
928 int index
= av_index_search_timestamp(st
, pts
, flags
);
932 pos2
= st
->index_entries
[index
].pos
;
933 ts
= st
->index_entries
[index
].timestamp
;
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
,
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
,
943 AVSEEK_FLAG_BACKWARD
, &ts
, nut_read_timestamp
);
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
);
956 // FIXME dir but I think it does not matter
959 sp
= av_tree_find(nut
->syncpoints
, &dummy
, (void *) ff_nut_sp_pos_cmp
,
963 pos2
= sp
->back_ptr
- 15;
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;
977 static int nut_read_close(AVFormatContext
*s
)
979 NUTContext
*nut
= s
->priv_data
;
982 av_freep(&nut
->time_base
);
983 av_freep(&nut
->stream
);
985 for (i
= 1; i
< nut
->header_count
; i
++)
986 av_freep(&nut
->header
[i
]);
991 AVInputFormat ff_nut_demuxer
= {
993 .long_name
= NULL_IF_CONFIG_SMALL("NUT"),
994 .priv_data_size
= sizeof(NUTContext
),
995 .read_probe
= nut_probe
,
996 .read_header
= nut_read_header
,
997 .read_packet
= nut_read_packet
,
998 .read_close
= nut_read_close
,
999 .read_seek
= read_seek
,
1000 .extensions
= "nut",
1001 .codec_tag
= ff_nut_codec_tags
,