2 * "NUT" Container Format demuxer
3 * Copyright (c) 2004-2006 Michael Niedermayer
4 * Copyright (c) 2003 Alex Beregszaszi
6 * This file is part of FFmpeg.
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.
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.
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
23 #include "libavutil/avstring.h"
24 #include "libavutil/tree.h"
30 static int get_str(ByteIOContext
*bc
, char *string
, unsigned int maxlen
){
31 unsigned int len
= ff_get_v(bc
);
34 get_buffer(bc
, string
, FFMIN(len
, maxlen
));
41 string
[FFMIN(len
, maxlen
-1)]= 0;
49 static int64_t get_s(ByteIOContext
*bc
){
50 int64_t v
= ff_get_v(bc
) + 1;
52 if (v
&1) return -(v
>>1);
56 static uint64_t get_fourcc(ByteIOContext
*bc
){
57 unsigned int len
= ff_get_v(bc
);
59 if (len
==2) return get_le16(bc
);
60 else if(len
==4) return get_le32(bc
);
65 static inline uint64_t get_v_trace(ByteIOContext
*bc
, char *file
, char *func
, int line
){
66 uint64_t v
= ff_get_v(bc
);
68 av_log(NULL
, AV_LOG_DEBUG
, "get_v %5"PRId64
" / %"PRIX64
" in %s %s:%d\n", v
, v
, file
, func
, line
);
72 static inline int64_t get_s_trace(ByteIOContext
*bc
, char *file
, char *func
, int line
){
75 av_log(NULL
, AV_LOG_DEBUG
, "get_s %5"PRId64
" / %"PRIX64
" in %s %s:%d\n", v
, v
, file
, func
, line
);
79 static inline uint64_t get_vb_trace(ByteIOContext
*bc
, char *file
, char *func
, int line
){
80 uint64_t v
= get_vb(bc
);
82 av_log(NULL
, AV_LOG_DEBUG
, "get_vb %5"PRId64
" / %"PRIX64
" in %s %s:%d\n", v
, v
, file
, func
, line
);
85 #define ff_get_v(bc) get_v_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__)
86 #define get_s(bc) get_s_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__)
87 #define get_vb(bc) get_vb_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__)
90 static int get_packetheader(NUTContext
*nut
, ByteIOContext
*bc
, int calculate_checksum
, uint64_t startcode
)
93 // start= url_ftell(bc) - 8;
95 startcode
= be2me_64(startcode
);
96 startcode
= ff_crc04C11DB7_update(0, &startcode
, 8);
98 init_checksum(bc
, ff_crc04C11DB7_update
, startcode
);
102 if(get_checksum(bc
) && size
> 4096)
105 init_checksum(bc
, calculate_checksum
? ff_crc04C11DB7_update
: NULL
, 0);
110 static uint64_t find_any_startcode(ByteIOContext
*bc
, int64_t pos
){
114 url_fseek(bc
, pos
, SEEK_SET
); //note, this may fail if the stream is not seekable, but that should not matter, as in this case we simply start where we currently are
116 while(!url_feof(bc
)){
117 state
= (state
<<8) | get_byte(bc
);
118 if((state
>>56) != 'N')
122 case STREAM_STARTCODE
:
123 case SYNCPOINT_STARTCODE
:
125 case INDEX_STARTCODE
:
134 * Find the given startcode.
135 * @param code the startcode
136 * @param pos the start position of the search, or -1 if the current position
137 * @returns the position of the startcode or -1 if not found
139 static int64_t find_startcode(ByteIOContext
*bc
, uint64_t code
, int64_t pos
){
141 uint64_t startcode
= find_any_startcode(bc
, pos
);
142 if(startcode
== code
)
143 return url_ftell(bc
) - 8;
144 else if(startcode
== 0)
150 static int nut_probe(AVProbeData
*p
){
154 for (i
= 0; i
< p
->buf_size
; i
++) {
155 code
= (code
<< 8) | p
->buf
[i
];
156 if (code
== MAIN_STARTCODE
)
157 return AVPROBE_SCORE_MAX
;
162 #define GET_V(dst, check) \
165 av_log(s, AV_LOG_ERROR, "Error " #dst " is (%"PRId64")\n", tmp);\
170 static int skip_reserved(ByteIOContext
*bc
, int64_t pos
){
171 pos
-= url_ftell(bc
);
173 url_fseek(bc
, pos
, SEEK_CUR
);
182 static int decode_main_header(NUTContext
*nut
){
183 AVFormatContext
*s
= nut
->avf
;
184 ByteIOContext
*bc
= s
->pb
;
186 unsigned int stream_count
;
187 int i
, j
, tmp_stream
, tmp_mul
, tmp_pts
, tmp_size
, count
, tmp_res
, tmp_head_idx
;
190 end
= get_packetheader(nut
, bc
, 1, MAIN_STARTCODE
);
191 end
+= url_ftell(bc
);
193 GET_V(tmp
, tmp
>=2 && tmp
<= 3)
194 GET_V(stream_count
, tmp
> 0 && tmp
<=MAX_STREAMS
)
196 nut
->max_distance
= ff_get_v(bc
);
197 if(nut
->max_distance
> 65536){
198 av_log(s
, AV_LOG_DEBUG
, "max_distance %d\n", nut
->max_distance
);
199 nut
->max_distance
= 65536;
202 GET_V(nut
->time_base_count
, tmp
>0 && tmp
<INT_MAX
/ sizeof(AVRational
))
203 nut
->time_base
= av_malloc(nut
->time_base_count
* sizeof(AVRational
));
205 for(i
=0; i
<nut
->time_base_count
; i
++){
206 GET_V(nut
->time_base
[i
].num
, tmp
>0 && tmp
<(1ULL<<31))
207 GET_V(nut
->time_base
[i
].den
, tmp
>0 && tmp
<(1ULL<<31))
208 if(ff_gcd(nut
->time_base
[i
].num
, nut
->time_base
[i
].den
) != 1){
209 av_log(s
, AV_LOG_ERROR
, "time base invalid\n");
216 tmp_match
= 1-(1LL<<62);
219 int tmp_flags
= ff_get_v(bc
);
220 int tmp_fields
= ff_get_v(bc
);
221 if(tmp_fields
>0) tmp_pts
= get_s(bc
);
222 if(tmp_fields
>1) tmp_mul
= ff_get_v(bc
);
223 if(tmp_fields
>2) tmp_stream
= ff_get_v(bc
);
224 if(tmp_fields
>3) tmp_size
= ff_get_v(bc
);
226 if(tmp_fields
>4) tmp_res
= ff_get_v(bc
);
228 if(tmp_fields
>5) count
= ff_get_v(bc
);
229 else count
= tmp_mul
- tmp_size
;
230 if(tmp_fields
>6) tmp_match
= get_s(bc
);
231 if(tmp_fields
>7) tmp_head_idx
= ff_get_v(bc
);
233 while(tmp_fields
-- > 8)
236 if(count
== 0 || i
+count
> 256){
237 av_log(s
, AV_LOG_ERROR
, "illegal count %d at %d\n", count
, i
);
240 if(tmp_stream
>= stream_count
){
241 av_log(s
, AV_LOG_ERROR
, "illegal stream number\n");
245 for(j
=0; j
<count
; j
++,i
++){
247 nut
->frame_code
[i
].flags
= FLAG_INVALID
;
251 nut
->frame_code
[i
].flags
= tmp_flags
;
252 nut
->frame_code
[i
].pts_delta
= tmp_pts
;
253 nut
->frame_code
[i
].stream_id
= tmp_stream
;
254 nut
->frame_code
[i
].size_mul
= tmp_mul
;
255 nut
->frame_code
[i
].size_lsb
= tmp_size
+j
;
256 nut
->frame_code
[i
].reserved_count
= tmp_res
;
257 nut
->frame_code
[i
].header_idx
= tmp_head_idx
;
260 assert(nut
->frame_code
['N'].flags
== FLAG_INVALID
);
262 if(end
> url_ftell(bc
) + 4){
264 GET_V(nut
->header_count
, tmp
<128U)
266 for(i
=1; i
<nut
->header_count
; i
++){
267 GET_V(nut
->header_len
[i
], tmp
>0 && tmp
<256);
268 rem
-= nut
->header_len
[i
];
270 av_log(s
, AV_LOG_ERROR
, "invalid elision header\n");
273 nut
->header
[i
]= av_malloc(nut
->header_len
[i
]);
274 get_buffer(bc
, nut
->header
[i
], nut
->header_len
[i
]);
276 assert(nut
->header_len
[0]==0);
279 if(skip_reserved(bc
, end
) || get_checksum(bc
)){
280 av_log(s
, AV_LOG_ERROR
, "main header checksum mismatch\n");
284 nut
->stream
= av_mallocz(sizeof(StreamContext
)*stream_count
);
285 for(i
=0; i
<stream_count
; i
++){
292 static int decode_stream_header(NUTContext
*nut
){
293 AVFormatContext
*s
= nut
->avf
;
294 ByteIOContext
*bc
= s
->pb
;
296 int class, stream_id
;
300 end
= get_packetheader(nut
, bc
, 1, STREAM_STARTCODE
);
301 end
+= url_ftell(bc
);
303 GET_V(stream_id
, tmp
< s
->nb_streams
&& !nut
->stream
[tmp
].time_base
);
304 stc
= &nut
->stream
[stream_id
];
306 st
= s
->streams
[stream_id
];
308 return AVERROR(ENOMEM
);
310 class = ff_get_v(bc
);
311 tmp
= get_fourcc(bc
);
312 st
->codec
->codec_tag
= tmp
;
316 st
->codec
->codec_type
= CODEC_TYPE_VIDEO
;
317 st
->codec
->codec_id
= codec_get_id(codec_bmp_tags
, tmp
);
320 st
->codec
->codec_type
= CODEC_TYPE_AUDIO
;
321 st
->codec
->codec_id
= codec_get_id(codec_wav_tags
, tmp
);
324 st
->codec
->codec_type
= CODEC_TYPE_SUBTITLE
;
325 st
->codec
->codec_id
= codec_get_id(ff_nut_subtitle_tags
, tmp
);
328 st
->codec
->codec_type
= CODEC_TYPE_DATA
;
331 av_log(s
, AV_LOG_ERROR
, "unknown stream class (%d)\n", class);
334 if(class<3 && st
->codec
->codec_id
== CODEC_ID_NONE
)
335 av_log(s
, AV_LOG_ERROR
, "Unknown codec?!\n");
337 GET_V(stc
->time_base_id
, tmp
< nut
->time_base_count
);
338 GET_V(stc
->msb_pts_shift
, tmp
< 16);
339 stc
->max_pts_distance
= ff_get_v(bc
);
340 GET_V(stc
->decode_delay
, tmp
< 1000); //sanity limit, raise this if Moore's law is true
341 st
->codec
->has_b_frames
= stc
->decode_delay
;
342 ff_get_v(bc
); //stream flags
344 GET_V(st
->codec
->extradata_size
, tmp
< (1<<30));
345 if(st
->codec
->extradata_size
){
346 st
->codec
->extradata
= av_mallocz(st
->codec
->extradata_size
+ FF_INPUT_BUFFER_PADDING_SIZE
);
347 get_buffer(bc
, st
->codec
->extradata
, st
->codec
->extradata_size
);
350 if (st
->codec
->codec_type
== CODEC_TYPE_VIDEO
){
351 GET_V(st
->codec
->width
, tmp
> 0)
352 GET_V(st
->codec
->height
, tmp
> 0)
353 st
->codec
->sample_aspect_ratio
.num
= ff_get_v(bc
);
354 st
->codec
->sample_aspect_ratio
.den
= ff_get_v(bc
);
355 if((!st
->codec
->sample_aspect_ratio
.num
) != (!st
->codec
->sample_aspect_ratio
.den
)){
356 av_log(s
, AV_LOG_ERROR
, "invalid aspect ratio %d/%d\n", st
->codec
->sample_aspect_ratio
.num
, st
->codec
->sample_aspect_ratio
.den
);
359 ff_get_v(bc
); /* csp type */
360 }else if (st
->codec
->codec_type
== CODEC_TYPE_AUDIO
){
361 GET_V(st
->codec
->sample_rate
, tmp
> 0)
362 ff_get_v(bc
); // samplerate_den
363 GET_V(st
->codec
->channels
, tmp
> 0)
365 if(skip_reserved(bc
, end
) || get_checksum(bc
)){
366 av_log(s
, AV_LOG_ERROR
, "stream header %d checksum mismatch\n", stream_id
);
369 stc
->time_base
= &nut
->time_base
[stc
->time_base_id
];
370 av_set_pts_info(s
->streams
[stream_id
], 63, stc
->time_base
->num
, stc
->time_base
->den
);
374 static void set_disposition_bits(AVFormatContext
* avf
, char* value
, int stream_id
){
376 for (i
=0; ff_nut_dispositions
[i
].flag
; ++i
) {
377 if (!strcmp(ff_nut_dispositions
[i
].str
, value
))
378 flag
= ff_nut_dispositions
[i
].flag
;
381 av_log(avf
, AV_LOG_INFO
, "unknown disposition type '%s'\n", value
);
382 for (i
= 0; i
< avf
->nb_streams
; ++i
)
383 if (stream_id
== i
|| stream_id
== -1)
384 avf
->streams
[i
]->disposition
|= flag
;
387 static int decode_info_header(NUTContext
*nut
){
388 AVFormatContext
*s
= nut
->avf
;
389 ByteIOContext
*bc
= s
->pb
;
391 unsigned int stream_id_plus1
, chapter_start
, chapter_len
, count
;
394 char name
[256], str_value
[1024], type_str
[256];
396 AVChapter
*chapter
= NULL
;
398 end
= get_packetheader(nut
, bc
, 1, INFO_STARTCODE
);
399 end
+= url_ftell(bc
);
401 GET_V(stream_id_plus1
, tmp
<= s
->nb_streams
)
402 chapter_id
= get_s(bc
);
403 chapter_start
= ff_get_v(bc
);
404 chapter_len
= ff_get_v(bc
);
405 count
= ff_get_v(bc
);
407 if(chapter_id
&& !stream_id_plus1
){
408 int64_t start
= chapter_start
/ nut
->time_base_count
;
409 chapter
= ff_new_chapter(s
, chapter_id
,
410 nut
->time_base
[chapter_start
% nut
->time_base_count
],
411 start
, start
+ chapter_len
, NULL
);
414 for(i
=0; i
<count
; i
++){
415 get_str(bc
, name
, sizeof(name
));
419 get_str(bc
, str_value
, sizeof(str_value
));
420 }else if(value
== -2){
421 get_str(bc
, type_str
, sizeof(type_str
));
423 get_str(bc
, str_value
, sizeof(str_value
));
424 }else if(value
== -3){
427 }else if(value
== -4){
430 }else if(value
< -4){
437 if (stream_id_plus1
> s
->nb_streams
) {
438 av_log(s
, AV_LOG_ERROR
, "invalid stream id for info packet\n");
442 if(chapter_id
==0 && !strcmp(type
, "UTF-8")){
443 if (!strcmp(name
, "Author"))
444 av_strlcpy(s
->author
, str_value
, sizeof(s
->author
));
445 else if(!strcmp(name
, "Title"))
446 av_strlcpy(s
->title
, str_value
, sizeof(s
->title
));
447 else if(!strcmp(name
, "Copyright"))
448 av_strlcpy(s
->copyright
, str_value
, sizeof(s
->copyright
));
449 else if(!strcmp(name
, "Description"))
450 av_strlcpy(s
->comment
, str_value
, sizeof(s
->comment
));
451 else if(!strcmp(name
, "Disposition"))
452 set_disposition_bits(s
, str_value
, stream_id_plus1
- 1);
454 if(chapter
&& !strcmp(type
, "UTF-8")){
455 if(!strcmp(name
, "Title"))
456 chapter
->title
= av_strdup(str_value
);
460 if(skip_reserved(bc
, end
) || get_checksum(bc
)){
461 av_log(s
, AV_LOG_ERROR
, "info header checksum mismatch\n");
467 static int decode_syncpoint(NUTContext
*nut
, int64_t *ts
, int64_t *back_ptr
){
468 AVFormatContext
*s
= nut
->avf
;
469 ByteIOContext
*bc
= s
->pb
;
472 nut
->last_syncpoint_pos
= url_ftell(bc
)-8;
474 end
= get_packetheader(nut
, bc
, 1, SYNCPOINT_STARTCODE
);
475 end
+= url_ftell(bc
);
478 *back_ptr
= nut
->last_syncpoint_pos
- 16*ff_get_v(bc
);
482 ff_nut_reset_ts(nut
, nut
->time_base
[tmp
% nut
->time_base_count
], tmp
/ nut
->time_base_count
);
484 if(skip_reserved(bc
, end
) || get_checksum(bc
)){
485 av_log(s
, AV_LOG_ERROR
, "sync point checksum mismatch\n");
489 *ts
= tmp
/ s
->nb_streams
* av_q2d(nut
->time_base
[tmp
% s
->nb_streams
])*AV_TIME_BASE
;
490 ff_nut_add_sp(nut
, nut
->last_syncpoint_pos
, *back_ptr
, *ts
);
495 static int find_and_decode_index(NUTContext
*nut
){
496 AVFormatContext
*s
= nut
->avf
;
497 ByteIOContext
*bc
= s
->pb
;
499 int i
, j
, syncpoint_count
;
500 int64_t filesize
= url_fsize(bc
);
502 int8_t *has_keyframe
;
505 url_fseek(bc
, filesize
-12, SEEK_SET
);
506 url_fseek(bc
, filesize
-get_be64(bc
), SEEK_SET
);
507 if(get_be64(bc
) != INDEX_STARTCODE
){
508 av_log(s
, AV_LOG_ERROR
, "no index at the end\n");
512 end
= get_packetheader(nut
, bc
, 1, INDEX_STARTCODE
);
513 end
+= url_ftell(bc
);
515 ff_get_v(bc
); //max_pts
516 GET_V(syncpoint_count
, tmp
< INT_MAX
/8 && tmp
> 0)
517 syncpoints
= av_malloc(sizeof(int64_t)*syncpoint_count
);
518 has_keyframe
= av_malloc(sizeof(int8_t)*(syncpoint_count
+1));
519 for(i
=0; i
<syncpoint_count
; i
++){
520 syncpoints
[i
] = ff_get_v(bc
);
521 if(syncpoints
[i
] <= 0)
524 syncpoints
[i
] += syncpoints
[i
-1];
527 for(i
=0; i
<s
->nb_streams
; i
++){
528 int64_t last_pts
= -1;
529 for(j
=0; j
<syncpoint_count
;){
530 uint64_t x
= ff_get_v(bc
);
537 if(n
+x
>= syncpoint_count
+ 1){
538 av_log(s
, AV_LOG_ERROR
, "index overflow A\n");
542 has_keyframe
[n
++]= flag
;
543 has_keyframe
[n
++]= !flag
;
546 if(n
>=syncpoint_count
+ 1){
547 av_log(s
, AV_LOG_ERROR
, "index overflow B\n");
550 has_keyframe
[n
++]= x
&1;
555 av_log(s
, AV_LOG_ERROR
, "keyframe before first syncpoint in index\n");
558 assert(n
<=syncpoint_count
+1);
559 for(; j
<n
&& j
<syncpoint_count
; j
++){
561 uint64_t B
, A
= ff_get_v(bc
);
565 //eor_pts[j][i] = last_pts + A + B
581 if(skip_reserved(bc
, end
) || get_checksum(bc
)){
582 av_log(s
, AV_LOG_ERROR
, "index checksum mismatch\n");
588 av_free(has_keyframe
);
592 static int nut_read_header(AVFormatContext
*s
, AVFormatParameters
*ap
)
594 NUTContext
*nut
= s
->priv_data
;
595 ByteIOContext
*bc
= s
->pb
;
597 int initialized_stream_count
;
604 pos
= find_startcode(bc
, MAIN_STARTCODE
, pos
)+1;
606 av_log(s
, AV_LOG_ERROR
, "No main startcode found.\n");
609 }while(decode_main_header(nut
) < 0);
613 for(initialized_stream_count
=0; initialized_stream_count
< s
->nb_streams
;){
614 pos
= find_startcode(bc
, STREAM_STARTCODE
, pos
)+1;
616 av_log(s
, AV_LOG_ERROR
, "Not all stream headers found.\n");
619 if(decode_stream_header(nut
) >= 0)
620 initialized_stream_count
++;
626 uint64_t startcode
= find_any_startcode(bc
, pos
);
630 av_log(s
, AV_LOG_ERROR
, "EOF before video frames\n");
632 }else if(startcode
== SYNCPOINT_STARTCODE
){
633 nut
->next_startcode
= startcode
;
635 }else if(startcode
!= INFO_STARTCODE
){
639 decode_info_header(nut
);
642 s
->data_offset
= pos
-8;
644 if(!url_is_streamed(bc
)){
645 int64_t orig_pos
= url_ftell(bc
);
646 find_and_decode_index(nut
);
647 url_fseek(bc
, orig_pos
, SEEK_SET
);
649 assert(nut
->next_startcode
== SYNCPOINT_STARTCODE
);
654 static int decode_frame_header(NUTContext
*nut
, int64_t *pts
, int *stream_id
, uint8_t *header_idx
, int frame_code
){
655 AVFormatContext
*s
= nut
->avf
;
656 ByteIOContext
*bc
= s
->pb
;
658 int size
, flags
, size_mul
, pts_delta
, i
, reserved_count
;
661 if(url_ftell(bc
) > nut
->last_syncpoint_pos
+ nut
->max_distance
){
662 av_log(s
, AV_LOG_ERROR
, "Last frame must have been damaged %"PRId64
" > %"PRId64
" + %d\n", url_ftell(bc
), nut
->last_syncpoint_pos
, nut
->max_distance
);
666 flags
= nut
->frame_code
[frame_code
].flags
;
667 size_mul
= nut
->frame_code
[frame_code
].size_mul
;
668 size
= nut
->frame_code
[frame_code
].size_lsb
;
669 *stream_id
= nut
->frame_code
[frame_code
].stream_id
;
670 pts_delta
= nut
->frame_code
[frame_code
].pts_delta
;
671 reserved_count
= nut
->frame_code
[frame_code
].reserved_count
;
672 *header_idx
= nut
->frame_code
[frame_code
].header_idx
;
674 if(flags
& FLAG_INVALID
)
676 if(flags
& FLAG_CODED
)
677 flags
^= ff_get_v(bc
);
678 if(flags
& FLAG_STREAM_ID
){
679 GET_V(*stream_id
, tmp
< s
->nb_streams
)
681 stc
= &nut
->stream
[*stream_id
];
682 if(flags
&FLAG_CODED_PTS
){
683 int coded_pts
= ff_get_v(bc
);
684 //FIXME check last_pts validity?
685 if(coded_pts
< (1<<stc
->msb_pts_shift
)){
686 *pts
=ff_lsb2full(stc
, coded_pts
);
688 *pts
=coded_pts
- (1<<stc
->msb_pts_shift
);
690 *pts
= stc
->last_pts
+ pts_delta
;
691 if(flags
&FLAG_SIZE_MSB
){
692 size
+= size_mul
*ff_get_v(bc
);
694 if(flags
&FLAG_MATCH_TIME
)
696 if(flags
&FLAG_HEADER_IDX
)
697 *header_idx
= ff_get_v(bc
);
698 if(flags
&FLAG_RESERVED
)
699 reserved_count
= ff_get_v(bc
);
700 for(i
=0; i
<reserved_count
; i
++)
703 if(*header_idx
>= (unsigned)nut
->header_count
){
704 av_log(s
, AV_LOG_ERROR
, "header_idx invalid\n");
709 size
-= nut
->header_len
[*header_idx
];
711 if(flags
&FLAG_CHECKSUM
){
712 get_be32(bc
); //FIXME check this
713 }else if(size
> 2*nut
->max_distance
|| FFABS(stc
->last_pts
- *pts
) > stc
->max_pts_distance
){
714 av_log(s
, AV_LOG_ERROR
, "frame size > 2max_distance and no checksum\n");
719 stc
->last_flags
= flags
;
724 static int decode_frame(NUTContext
*nut
, AVPacket
*pkt
, int frame_code
){
725 AVFormatContext
*s
= nut
->avf
;
726 ByteIOContext
*bc
= s
->pb
;
727 int size
, stream_id
, discard
;
728 int64_t pts
, last_IP_pts
;
732 size
= decode_frame_header(nut
, &pts
, &stream_id
, &header_idx
, frame_code
);
736 stc
= &nut
->stream
[stream_id
];
738 if (stc
->last_flags
& FLAG_KEY
)
739 stc
->skip_until_key_frame
=0;
741 discard
= s
->streams
[ stream_id
]->discard
;
742 last_IP_pts
= s
->streams
[ stream_id
]->last_IP_pts
;
743 if( (discard
>= AVDISCARD_NONKEY
&& !(stc
->last_flags
& FLAG_KEY
))
744 ||(discard
>= AVDISCARD_BIDIR
&& last_IP_pts
!= AV_NOPTS_VALUE
&& last_IP_pts
> pts
)
745 || discard
>= AVDISCARD_ALL
746 || stc
->skip_until_key_frame
){
751 av_new_packet(pkt
, size
+ nut
->header_len
[header_idx
]);
752 memcpy(pkt
->data
, nut
->header
[header_idx
], nut
->header_len
[header_idx
]);
753 pkt
->pos
= url_ftell(bc
); //FIXME
754 get_buffer(bc
, pkt
->data
+ nut
->header_len
[header_idx
], size
);
756 pkt
->stream_index
= stream_id
;
757 if (stc
->last_flags
& FLAG_KEY
)
758 pkt
->flags
|= PKT_FLAG_KEY
;
764 static int nut_read_packet(AVFormatContext
*s
, AVPacket
*pkt
)
766 NUTContext
*nut
= s
->priv_data
;
767 ByteIOContext
*bc
= s
->pb
;
768 int i
, frame_code
=0, ret
, skip
;
769 int64_t ts
, back_ptr
;
772 int64_t pos
= url_ftell(bc
);
773 uint64_t tmp
= nut
->next_startcode
;
774 nut
->next_startcode
=0;
779 frame_code
= get_byte(bc
);
782 if(frame_code
== 'N'){
785 tmp
= (tmp
<<8) + get_byte(bc
);
790 case STREAM_STARTCODE
:
791 case INDEX_STARTCODE
:
792 skip
= get_packetheader(nut
, bc
, 0, tmp
);
793 url_fseek(bc
, skip
, SEEK_CUR
);
796 if(decode_info_header(nut
)<0)
799 case SYNCPOINT_STARTCODE
:
800 if(decode_syncpoint(nut
, &ts
, &back_ptr
)<0)
802 frame_code
= get_byte(bc
);
804 ret
= decode_frame(nut
, pkt
, frame_code
);
807 else if(ret
==1) //ok but discard packet
811 av_log(s
, AV_LOG_DEBUG
, "syncing from %"PRId64
"\n", pos
);
812 tmp
= find_any_startcode(bc
, nut
->last_syncpoint_pos
+1);
815 av_log(s
, AV_LOG_DEBUG
, "sync\n");
816 nut
->next_startcode
= tmp
;
821 static int64_t nut_read_timestamp(AVFormatContext
*s
, int stream_index
, int64_t *pos_arg
, int64_t pos_limit
){
822 NUTContext
*nut
= s
->priv_data
;
823 ByteIOContext
*bc
= s
->pb
;
824 int64_t pos
, pts
, back_ptr
;
825 av_log(s
, AV_LOG_DEBUG
, "read_timestamp(X,%d,%"PRId64
",%"PRId64
")\n", stream_index
, *pos_arg
, pos_limit
);
829 pos
= find_startcode(bc
, SYNCPOINT_STARTCODE
, pos
)+1;
831 assert(nut
->next_startcode
== 0);
832 av_log(s
, AV_LOG_ERROR
, "read_timestamp failed.\n");
833 return AV_NOPTS_VALUE
;
835 }while(decode_syncpoint(nut
, &pts
, &back_ptr
) < 0);
837 assert(nut
->last_syncpoint_pos
== *pos_arg
);
839 av_log(s
, AV_LOG_DEBUG
, "return %"PRId64
" %"PRId64
"\n", pts
,back_ptr
);
840 if (stream_index
== -1) return pts
;
841 else if(stream_index
== -2) return back_ptr
;
846 static int read_seek(AVFormatContext
*s
, int stream_index
, int64_t pts
, int flags
){
847 NUTContext
*nut
= s
->priv_data
;
848 AVStream
*st
= s
->streams
[stream_index
];
849 syncpoint_t dummy
={.ts
= pts
*av_q2d(st
->time_base
)*AV_TIME_BASE
};
850 syncpoint_t nopts_sp
= {.ts
= AV_NOPTS_VALUE
, .back_ptr
= AV_NOPTS_VALUE
};
851 syncpoint_t
*sp
, *next_node
[2]= {&nopts_sp
, &nopts_sp
};
852 int64_t pos
, pos2
, ts
;
855 if(st
->index_entries
){
856 int index
= av_index_search_timestamp(st
, pts
, flags
);
860 pos2
= st
->index_entries
[index
].pos
;
861 ts
= st
->index_entries
[index
].timestamp
;
863 av_tree_find(nut
->syncpoints
, &dummy
, ff_nut_sp_pts_cmp
, next_node
);
864 av_log(s
, AV_LOG_DEBUG
, "%"PRIu64
"-%"PRIu64
" %"PRId64
"-%"PRId64
"\n", next_node
[0]->pos
, next_node
[1]->pos
,
865 next_node
[0]->ts
, next_node
[1]->ts
);
866 pos
= av_gen_search(s
, -1, dummy
.ts
, next_node
[0]->pos
, next_node
[1]->pos
, next_node
[1]->pos
,
867 next_node
[0]->ts
, next_node
[1]->ts
, AVSEEK_FLAG_BACKWARD
, &ts
, nut_read_timestamp
);
869 if(!(flags
& AVSEEK_FLAG_BACKWARD
)){
871 next_node
[1]= &nopts_sp
;
872 av_tree_find(nut
->syncpoints
, &dummy
, ff_nut_sp_pos_cmp
, next_node
);
873 pos2
= av_gen_search(s
, -2, dummy
.pos
, next_node
[0]->pos
, next_node
[1]->pos
, next_node
[1]->pos
,
874 next_node
[0]->back_ptr
, next_node
[1]->back_ptr
, flags
, &ts
, nut_read_timestamp
);
877 //FIXME dir but I think it does not matter
880 sp
= av_tree_find(nut
->syncpoints
, &dummy
, ff_nut_sp_pos_cmp
, NULL
);
883 pos2
= sp
->back_ptr
- 15;
885 av_log(NULL
, AV_LOG_DEBUG
, "SEEKTO: %"PRId64
"\n", pos2
);
886 pos
= find_startcode(s
->pb
, SYNCPOINT_STARTCODE
, pos2
);
887 url_fseek(s
->pb
, pos
, SEEK_SET
);
888 av_log(NULL
, AV_LOG_DEBUG
, "SP: %"PRId64
"\n", pos
);
889 if(pos2
> pos
|| pos2
+ 15 < pos
){
890 av_log(NULL
, AV_LOG_ERROR
, "no syncpoint at backptr pos\n");
892 for(i
=0; i
<s
->nb_streams
; i
++)
893 nut
->stream
[i
].skip_until_key_frame
=1;
898 static int nut_read_close(AVFormatContext
*s
)
900 NUTContext
*nut
= s
->priv_data
;
902 av_freep(&nut
->time_base
);
903 av_freep(&nut
->stream
);
908 #ifdef CONFIG_NUT_DEMUXER
909 AVInputFormat nut_demuxer
= {
911 NULL_IF_CONFIG_SMALL("NUT format"),