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/bswap.h"
25 #include "libavutil/tree.h"
31 static int get_str(ByteIOContext
*bc
, char *string
, unsigned int maxlen
){
32 unsigned int len
= ff_get_v(bc
);
35 get_buffer(bc
, string
, FFMIN(len
, maxlen
));
42 string
[FFMIN(len
, maxlen
-1)]= 0;
50 static int64_t get_s(ByteIOContext
*bc
){
51 int64_t v
= ff_get_v(bc
) + 1;
53 if (v
&1) return -(v
>>1);
57 static uint64_t get_fourcc(ByteIOContext
*bc
){
58 unsigned int len
= ff_get_v(bc
);
60 if (len
==2) return get_le16(bc
);
61 else if(len
==4) return get_le32(bc
);
66 static inline uint64_t get_v_trace(ByteIOContext
*bc
, char *file
, char *func
, int line
){
67 uint64_t v
= ff_get_v(bc
);
69 av_log(NULL
, AV_LOG_DEBUG
, "get_v %5"PRId64
" / %"PRIX64
" in %s %s:%d\n", v
, v
, file
, func
, line
);
73 static inline int64_t get_s_trace(ByteIOContext
*bc
, char *file
, char *func
, int line
){
76 av_log(NULL
, AV_LOG_DEBUG
, "get_s %5"PRId64
" / %"PRIX64
" in %s %s:%d\n", v
, v
, file
, func
, line
);
80 static inline uint64_t get_vb_trace(ByteIOContext
*bc
, char *file
, char *func
, int line
){
81 uint64_t v
= get_vb(bc
);
83 av_log(NULL
, AV_LOG_DEBUG
, "get_vb %5"PRId64
" / %"PRIX64
" in %s %s:%d\n", v
, v
, file
, func
, line
);
86 #define ff_get_v(bc) get_v_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__)
87 #define get_s(bc) get_s_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__)
88 #define get_vb(bc) get_vb_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__)
91 static int get_packetheader(NUTContext
*nut
, ByteIOContext
*bc
, int calculate_checksum
, uint64_t startcode
)
94 // start= url_ftell(bc) - 8;
96 startcode
= be2me_64(startcode
);
97 startcode
= ff_crc04C11DB7_update(0, &startcode
, 8);
99 init_checksum(bc
, ff_crc04C11DB7_update
, startcode
);
103 if(get_checksum(bc
) && size
> 4096)
106 init_checksum(bc
, calculate_checksum
? ff_crc04C11DB7_update
: NULL
, 0);
111 static uint64_t find_any_startcode(ByteIOContext
*bc
, int64_t pos
){
115 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
117 while(!url_feof(bc
)){
118 state
= (state
<<8) | get_byte(bc
);
119 if((state
>>56) != 'N')
123 case STREAM_STARTCODE
:
124 case SYNCPOINT_STARTCODE
:
126 case INDEX_STARTCODE
:
135 * Find the given startcode.
136 * @param code the startcode
137 * @param pos the start position of the search, or -1 if the current position
138 * @returns the position of the startcode or -1 if not found
140 static int64_t find_startcode(ByteIOContext
*bc
, uint64_t code
, int64_t pos
){
142 uint64_t startcode
= find_any_startcode(bc
, pos
);
143 if(startcode
== code
)
144 return url_ftell(bc
) - 8;
145 else if(startcode
== 0)
151 static int nut_probe(AVProbeData
*p
){
155 for (i
= 0; i
< p
->buf_size
; i
++) {
156 code
= (code
<< 8) | p
->buf
[i
];
157 if (code
== MAIN_STARTCODE
)
158 return AVPROBE_SCORE_MAX
;
163 #define GET_V(dst, check) \
166 av_log(s, AV_LOG_ERROR, "Error " #dst " is (%"PRId64")\n", tmp);\
171 static int skip_reserved(ByteIOContext
*bc
, int64_t pos
){
172 pos
-= url_ftell(bc
);
174 url_fseek(bc
, pos
, SEEK_CUR
);
183 static int decode_main_header(NUTContext
*nut
){
184 AVFormatContext
*s
= nut
->avf
;
185 ByteIOContext
*bc
= s
->pb
;
187 unsigned int stream_count
;
188 int i
, j
, tmp_stream
, tmp_mul
, tmp_pts
, tmp_size
, count
, tmp_res
, tmp_head_idx
;
191 end
= get_packetheader(nut
, bc
, 1, MAIN_STARTCODE
);
192 end
+= url_ftell(bc
);
194 GET_V(tmp
, tmp
>=2 && tmp
<= 3)
195 GET_V(stream_count
, tmp
> 0 && tmp
<=MAX_STREAMS
)
197 nut
->max_distance
= ff_get_v(bc
);
198 if(nut
->max_distance
> 65536){
199 av_log(s
, AV_LOG_DEBUG
, "max_distance %d\n", nut
->max_distance
);
200 nut
->max_distance
= 65536;
203 GET_V(nut
->time_base_count
, tmp
>0 && tmp
<INT_MAX
/ sizeof(AVRational
))
204 nut
->time_base
= av_malloc(nut
->time_base_count
* sizeof(AVRational
));
206 for(i
=0; i
<nut
->time_base_count
; i
++){
207 GET_V(nut
->time_base
[i
].num
, tmp
>0 && tmp
<(1ULL<<31))
208 GET_V(nut
->time_base
[i
].den
, tmp
>0 && tmp
<(1ULL<<31))
209 if(av_gcd(nut
->time_base
[i
].num
, nut
->time_base
[i
].den
) != 1){
210 av_log(s
, AV_LOG_ERROR
, "time base invalid\n");
217 tmp_match
= 1-(1LL<<62);
220 int tmp_flags
= ff_get_v(bc
);
221 int tmp_fields
= ff_get_v(bc
);
222 if(tmp_fields
>0) tmp_pts
= get_s(bc
);
223 if(tmp_fields
>1) tmp_mul
= ff_get_v(bc
);
224 if(tmp_fields
>2) tmp_stream
= ff_get_v(bc
);
225 if(tmp_fields
>3) tmp_size
= ff_get_v(bc
);
227 if(tmp_fields
>4) tmp_res
= ff_get_v(bc
);
229 if(tmp_fields
>5) count
= ff_get_v(bc
);
230 else count
= tmp_mul
- tmp_size
;
231 if(tmp_fields
>6) tmp_match
= get_s(bc
);
232 if(tmp_fields
>7) tmp_head_idx
= ff_get_v(bc
);
234 while(tmp_fields
-- > 8)
237 if(count
== 0 || i
+count
> 256){
238 av_log(s
, AV_LOG_ERROR
, "illegal count %d at %d\n", count
, i
);
241 if(tmp_stream
>= stream_count
){
242 av_log(s
, AV_LOG_ERROR
, "illegal stream number\n");
246 for(j
=0; j
<count
; j
++,i
++){
248 nut
->frame_code
[i
].flags
= FLAG_INVALID
;
252 nut
->frame_code
[i
].flags
= tmp_flags
;
253 nut
->frame_code
[i
].pts_delta
= tmp_pts
;
254 nut
->frame_code
[i
].stream_id
= tmp_stream
;
255 nut
->frame_code
[i
].size_mul
= tmp_mul
;
256 nut
->frame_code
[i
].size_lsb
= tmp_size
+j
;
257 nut
->frame_code
[i
].reserved_count
= tmp_res
;
258 nut
->frame_code
[i
].header_idx
= tmp_head_idx
;
261 assert(nut
->frame_code
['N'].flags
== FLAG_INVALID
);
263 if(end
> url_ftell(bc
) + 4){
265 GET_V(nut
->header_count
, tmp
<128U)
267 for(i
=1; i
<nut
->header_count
; i
++){
268 GET_V(nut
->header_len
[i
], tmp
>0 && tmp
<256);
269 rem
-= nut
->header_len
[i
];
271 av_log(s
, AV_LOG_ERROR
, "invalid elision header\n");
274 nut
->header
[i
]= av_malloc(nut
->header_len
[i
]);
275 get_buffer(bc
, nut
->header
[i
], nut
->header_len
[i
]);
277 assert(nut
->header_len
[0]==0);
280 if(skip_reserved(bc
, end
) || get_checksum(bc
)){
281 av_log(s
, AV_LOG_ERROR
, "main header checksum mismatch\n");
285 nut
->stream
= av_mallocz(sizeof(StreamContext
)*stream_count
);
286 for(i
=0; i
<stream_count
; i
++){
293 static int decode_stream_header(NUTContext
*nut
){
294 AVFormatContext
*s
= nut
->avf
;
295 ByteIOContext
*bc
= s
->pb
;
297 int class, stream_id
;
301 end
= get_packetheader(nut
, bc
, 1, STREAM_STARTCODE
);
302 end
+= url_ftell(bc
);
304 GET_V(stream_id
, tmp
< s
->nb_streams
&& !nut
->stream
[tmp
].time_base
);
305 stc
= &nut
->stream
[stream_id
];
307 st
= s
->streams
[stream_id
];
309 return AVERROR(ENOMEM
);
311 class = ff_get_v(bc
);
312 tmp
= get_fourcc(bc
);
313 st
->codec
->codec_tag
= tmp
;
317 st
->codec
->codec_type
= CODEC_TYPE_VIDEO
;
318 st
->codec
->codec_id
= codec_get_id(codec_bmp_tags
, tmp
);
321 st
->codec
->codec_type
= CODEC_TYPE_AUDIO
;
322 st
->codec
->codec_id
= codec_get_id(codec_wav_tags
, tmp
);
325 st
->codec
->codec_type
= CODEC_TYPE_SUBTITLE
;
326 st
->codec
->codec_id
= codec_get_id(ff_nut_subtitle_tags
, tmp
);
329 st
->codec
->codec_type
= CODEC_TYPE_DATA
;
332 av_log(s
, AV_LOG_ERROR
, "unknown stream class (%d)\n", class);
335 if(class<3 && st
->codec
->codec_id
== CODEC_ID_NONE
)
336 av_log(s
, AV_LOG_ERROR
, "Unknown codec?!\n");
338 GET_V(stc
->time_base_id
, tmp
< nut
->time_base_count
);
339 GET_V(stc
->msb_pts_shift
, tmp
< 16);
340 stc
->max_pts_distance
= ff_get_v(bc
);
341 GET_V(stc
->decode_delay
, tmp
< 1000); //sanity limit, raise this if Moore's law is true
342 st
->codec
->has_b_frames
= stc
->decode_delay
;
343 ff_get_v(bc
); //stream flags
345 GET_V(st
->codec
->extradata_size
, tmp
< (1<<30));
346 if(st
->codec
->extradata_size
){
347 st
->codec
->extradata
= av_mallocz(st
->codec
->extradata_size
+ FF_INPUT_BUFFER_PADDING_SIZE
);
348 get_buffer(bc
, st
->codec
->extradata
, st
->codec
->extradata_size
);
351 if (st
->codec
->codec_type
== CODEC_TYPE_VIDEO
){
352 GET_V(st
->codec
->width
, tmp
> 0)
353 GET_V(st
->codec
->height
, tmp
> 0)
354 st
->sample_aspect_ratio
.num
= ff_get_v(bc
);
355 st
->sample_aspect_ratio
.den
= ff_get_v(bc
);
356 if((!st
->sample_aspect_ratio
.num
) != (!st
->sample_aspect_ratio
.den
)){
357 av_log(s
, AV_LOG_ERROR
, "invalid aspect ratio %d/%d\n", st
->sample_aspect_ratio
.num
, st
->sample_aspect_ratio
.den
);
360 ff_get_v(bc
); /* csp type */
361 }else if (st
->codec
->codec_type
== CODEC_TYPE_AUDIO
){
362 GET_V(st
->codec
->sample_rate
, tmp
> 0)
363 ff_get_v(bc
); // samplerate_den
364 GET_V(st
->codec
->channels
, tmp
> 0)
366 if(skip_reserved(bc
, end
) || get_checksum(bc
)){
367 av_log(s
, AV_LOG_ERROR
, "stream header %d checksum mismatch\n", stream_id
);
370 stc
->time_base
= &nut
->time_base
[stc
->time_base_id
];
371 av_set_pts_info(s
->streams
[stream_id
], 63, stc
->time_base
->num
, stc
->time_base
->den
);
375 static void set_disposition_bits(AVFormatContext
* avf
, char* value
, int stream_id
){
377 for (i
=0; ff_nut_dispositions
[i
].flag
; ++i
) {
378 if (!strcmp(ff_nut_dispositions
[i
].str
, value
))
379 flag
= ff_nut_dispositions
[i
].flag
;
382 av_log(avf
, AV_LOG_INFO
, "unknown disposition type '%s'\n", value
);
383 for (i
= 0; i
< avf
->nb_streams
; ++i
)
384 if (stream_id
== i
|| stream_id
== -1)
385 avf
->streams
[i
]->disposition
|= flag
;
388 static int decode_info_header(NUTContext
*nut
){
389 AVFormatContext
*s
= nut
->avf
;
390 ByteIOContext
*bc
= s
->pb
;
392 unsigned int stream_id_plus1
, chapter_start
, chapter_len
, count
;
395 char name
[256], str_value
[1024], type_str
[256];
397 AVChapter
*chapter
= NULL
;
399 end
= get_packetheader(nut
, bc
, 1, INFO_STARTCODE
);
400 end
+= url_ftell(bc
);
402 GET_V(stream_id_plus1
, tmp
<= s
->nb_streams
)
403 chapter_id
= get_s(bc
);
404 chapter_start
= ff_get_v(bc
);
405 chapter_len
= ff_get_v(bc
);
406 count
= ff_get_v(bc
);
408 if(chapter_id
&& !stream_id_plus1
){
409 int64_t start
= chapter_start
/ nut
->time_base_count
;
410 chapter
= ff_new_chapter(s
, chapter_id
,
411 nut
->time_base
[chapter_start
% nut
->time_base_count
],
412 start
, start
+ chapter_len
, NULL
);
415 for(i
=0; i
<count
; i
++){
416 get_str(bc
, name
, sizeof(name
));
420 get_str(bc
, str_value
, sizeof(str_value
));
421 }else if(value
== -2){
422 get_str(bc
, type_str
, sizeof(type_str
));
424 get_str(bc
, str_value
, sizeof(str_value
));
425 }else if(value
== -3){
428 }else if(value
== -4){
431 }else if(value
< -4){
438 if (stream_id_plus1
> s
->nb_streams
) {
439 av_log(s
, AV_LOG_ERROR
, "invalid stream id for info packet\n");
443 if(chapter_id
==0 && !strcmp(type
, "UTF-8")){
444 if (!strcmp(name
, "Author"))
445 av_strlcpy(s
->author
, str_value
, sizeof(s
->author
));
446 else if(!strcmp(name
, "Title"))
447 av_strlcpy(s
->title
, str_value
, sizeof(s
->title
));
448 else if(!strcmp(name
, "Copyright"))
449 av_strlcpy(s
->copyright
, str_value
, sizeof(s
->copyright
));
450 else if(!strcmp(name
, "Description"))
451 av_strlcpy(s
->comment
, str_value
, sizeof(s
->comment
));
452 else if(!strcmp(name
, "Disposition"))
453 set_disposition_bits(s
, str_value
, stream_id_plus1
- 1);
455 if(chapter
&& !strcmp(type
, "UTF-8")){
456 if(!strcmp(name
, "Title"))
457 chapter
->title
= av_strdup(str_value
);
461 if(skip_reserved(bc
, end
) || get_checksum(bc
)){
462 av_log(s
, AV_LOG_ERROR
, "info header checksum mismatch\n");
468 static int decode_syncpoint(NUTContext
*nut
, int64_t *ts
, int64_t *back_ptr
){
469 AVFormatContext
*s
= nut
->avf
;
470 ByteIOContext
*bc
= s
->pb
;
473 nut
->last_syncpoint_pos
= url_ftell(bc
)-8;
475 end
= get_packetheader(nut
, bc
, 1, SYNCPOINT_STARTCODE
);
476 end
+= url_ftell(bc
);
479 *back_ptr
= nut
->last_syncpoint_pos
- 16*ff_get_v(bc
);
483 ff_nut_reset_ts(nut
, nut
->time_base
[tmp
% nut
->time_base_count
], tmp
/ nut
->time_base_count
);
485 if(skip_reserved(bc
, end
) || get_checksum(bc
)){
486 av_log(s
, AV_LOG_ERROR
, "sync point checksum mismatch\n");
490 *ts
= tmp
/ s
->nb_streams
* av_q2d(nut
->time_base
[tmp
% s
->nb_streams
])*AV_TIME_BASE
;
491 ff_nut_add_sp(nut
, nut
->last_syncpoint_pos
, *back_ptr
, *ts
);
496 static int find_and_decode_index(NUTContext
*nut
){
497 AVFormatContext
*s
= nut
->avf
;
498 ByteIOContext
*bc
= s
->pb
;
500 int i
, j
, syncpoint_count
;
501 int64_t filesize
= url_fsize(bc
);
503 int8_t *has_keyframe
;
506 url_fseek(bc
, filesize
-12, SEEK_SET
);
507 url_fseek(bc
, filesize
-get_be64(bc
), SEEK_SET
);
508 if(get_be64(bc
) != INDEX_STARTCODE
){
509 av_log(s
, AV_LOG_ERROR
, "no index at the end\n");
513 end
= get_packetheader(nut
, bc
, 1, INDEX_STARTCODE
);
514 end
+= url_ftell(bc
);
516 ff_get_v(bc
); //max_pts
517 GET_V(syncpoint_count
, tmp
< INT_MAX
/8 && tmp
> 0)
518 syncpoints
= av_malloc(sizeof(int64_t)*syncpoint_count
);
519 has_keyframe
= av_malloc(sizeof(int8_t)*(syncpoint_count
+1));
520 for(i
=0; i
<syncpoint_count
; i
++){
521 syncpoints
[i
] = ff_get_v(bc
);
522 if(syncpoints
[i
] <= 0)
525 syncpoints
[i
] += syncpoints
[i
-1];
528 for(i
=0; i
<s
->nb_streams
; i
++){
529 int64_t last_pts
= -1;
530 for(j
=0; j
<syncpoint_count
;){
531 uint64_t x
= ff_get_v(bc
);
538 if(n
+x
>= syncpoint_count
+ 1){
539 av_log(s
, AV_LOG_ERROR
, "index overflow A\n");
543 has_keyframe
[n
++]= flag
;
544 has_keyframe
[n
++]= !flag
;
547 if(n
>=syncpoint_count
+ 1){
548 av_log(s
, AV_LOG_ERROR
, "index overflow B\n");
551 has_keyframe
[n
++]= x
&1;
556 av_log(s
, AV_LOG_ERROR
, "keyframe before first syncpoint in index\n");
559 assert(n
<=syncpoint_count
+1);
560 for(; j
<n
&& j
<syncpoint_count
; j
++){
562 uint64_t B
, A
= ff_get_v(bc
);
566 //eor_pts[j][i] = last_pts + A + B
582 if(skip_reserved(bc
, end
) || get_checksum(bc
)){
583 av_log(s
, AV_LOG_ERROR
, "index checksum mismatch\n");
589 av_free(has_keyframe
);
593 static int nut_read_header(AVFormatContext
*s
, AVFormatParameters
*ap
)
595 NUTContext
*nut
= s
->priv_data
;
596 ByteIOContext
*bc
= s
->pb
;
598 int initialized_stream_count
;
605 pos
= find_startcode(bc
, MAIN_STARTCODE
, pos
)+1;
607 av_log(s
, AV_LOG_ERROR
, "No main startcode found.\n");
610 }while(decode_main_header(nut
) < 0);
614 for(initialized_stream_count
=0; initialized_stream_count
< s
->nb_streams
;){
615 pos
= find_startcode(bc
, STREAM_STARTCODE
, pos
)+1;
617 av_log(s
, AV_LOG_ERROR
, "Not all stream headers found.\n");
620 if(decode_stream_header(nut
) >= 0)
621 initialized_stream_count
++;
627 uint64_t startcode
= find_any_startcode(bc
, pos
);
631 av_log(s
, AV_LOG_ERROR
, "EOF before video frames\n");
633 }else if(startcode
== SYNCPOINT_STARTCODE
){
634 nut
->next_startcode
= startcode
;
636 }else if(startcode
!= INFO_STARTCODE
){
640 decode_info_header(nut
);
643 s
->data_offset
= pos
-8;
645 if(!url_is_streamed(bc
)){
646 int64_t orig_pos
= url_ftell(bc
);
647 find_and_decode_index(nut
);
648 url_fseek(bc
, orig_pos
, SEEK_SET
);
650 assert(nut
->next_startcode
== SYNCPOINT_STARTCODE
);
655 static int decode_frame_header(NUTContext
*nut
, int64_t *pts
, int *stream_id
, uint8_t *header_idx
, int frame_code
){
656 AVFormatContext
*s
= nut
->avf
;
657 ByteIOContext
*bc
= s
->pb
;
659 int size
, flags
, size_mul
, pts_delta
, i
, reserved_count
;
662 if(url_ftell(bc
) > nut
->last_syncpoint_pos
+ nut
->max_distance
){
663 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
);
667 flags
= nut
->frame_code
[frame_code
].flags
;
668 size_mul
= nut
->frame_code
[frame_code
].size_mul
;
669 size
= nut
->frame_code
[frame_code
].size_lsb
;
670 *stream_id
= nut
->frame_code
[frame_code
].stream_id
;
671 pts_delta
= nut
->frame_code
[frame_code
].pts_delta
;
672 reserved_count
= nut
->frame_code
[frame_code
].reserved_count
;
673 *header_idx
= nut
->frame_code
[frame_code
].header_idx
;
675 if(flags
& FLAG_INVALID
)
677 if(flags
& FLAG_CODED
)
678 flags
^= ff_get_v(bc
);
679 if(flags
& FLAG_STREAM_ID
){
680 GET_V(*stream_id
, tmp
< s
->nb_streams
)
682 stc
= &nut
->stream
[*stream_id
];
683 if(flags
&FLAG_CODED_PTS
){
684 int coded_pts
= ff_get_v(bc
);
685 //FIXME check last_pts validity?
686 if(coded_pts
< (1<<stc
->msb_pts_shift
)){
687 *pts
=ff_lsb2full(stc
, coded_pts
);
689 *pts
=coded_pts
- (1<<stc
->msb_pts_shift
);
691 *pts
= stc
->last_pts
+ pts_delta
;
692 if(flags
&FLAG_SIZE_MSB
){
693 size
+= size_mul
*ff_get_v(bc
);
695 if(flags
&FLAG_MATCH_TIME
)
697 if(flags
&FLAG_HEADER_IDX
)
698 *header_idx
= ff_get_v(bc
);
699 if(flags
&FLAG_RESERVED
)
700 reserved_count
= ff_get_v(bc
);
701 for(i
=0; i
<reserved_count
; i
++)
704 if(*header_idx
>= (unsigned)nut
->header_count
){
705 av_log(s
, AV_LOG_ERROR
, "header_idx invalid\n");
710 size
-= nut
->header_len
[*header_idx
];
712 if(flags
&FLAG_CHECKSUM
){
713 get_be32(bc
); //FIXME check this
714 }else if(size
> 2*nut
->max_distance
|| FFABS(stc
->last_pts
- *pts
) > stc
->max_pts_distance
){
715 av_log(s
, AV_LOG_ERROR
, "frame size > 2max_distance and no checksum\n");
720 stc
->last_flags
= flags
;
725 static int decode_frame(NUTContext
*nut
, AVPacket
*pkt
, int frame_code
){
726 AVFormatContext
*s
= nut
->avf
;
727 ByteIOContext
*bc
= s
->pb
;
728 int size
, stream_id
, discard
;
729 int64_t pts
, last_IP_pts
;
733 size
= decode_frame_header(nut
, &pts
, &stream_id
, &header_idx
, frame_code
);
737 stc
= &nut
->stream
[stream_id
];
739 if (stc
->last_flags
& FLAG_KEY
)
740 stc
->skip_until_key_frame
=0;
742 discard
= s
->streams
[ stream_id
]->discard
;
743 last_IP_pts
= s
->streams
[ stream_id
]->last_IP_pts
;
744 if( (discard
>= AVDISCARD_NONKEY
&& !(stc
->last_flags
& FLAG_KEY
))
745 ||(discard
>= AVDISCARD_BIDIR
&& last_IP_pts
!= AV_NOPTS_VALUE
&& last_IP_pts
> pts
)
746 || discard
>= AVDISCARD_ALL
747 || stc
->skip_until_key_frame
){
752 av_new_packet(pkt
, size
+ nut
->header_len
[header_idx
]);
753 memcpy(pkt
->data
, nut
->header
[header_idx
], nut
->header_len
[header_idx
]);
754 pkt
->pos
= url_ftell(bc
); //FIXME
755 get_buffer(bc
, pkt
->data
+ nut
->header_len
[header_idx
], size
);
757 pkt
->stream_index
= stream_id
;
758 if (stc
->last_flags
& FLAG_KEY
)
759 pkt
->flags
|= PKT_FLAG_KEY
;
765 static int nut_read_packet(AVFormatContext
*s
, AVPacket
*pkt
)
767 NUTContext
*nut
= s
->priv_data
;
768 ByteIOContext
*bc
= s
->pb
;
769 int i
, frame_code
=0, ret
, skip
;
770 int64_t ts
, back_ptr
;
773 int64_t pos
= url_ftell(bc
);
774 uint64_t tmp
= nut
->next_startcode
;
775 nut
->next_startcode
=0;
780 frame_code
= get_byte(bc
);
783 if(frame_code
== 'N'){
786 tmp
= (tmp
<<8) + get_byte(bc
);
791 case STREAM_STARTCODE
:
792 case INDEX_STARTCODE
:
793 skip
= get_packetheader(nut
, bc
, 0, tmp
);
794 url_fseek(bc
, skip
, SEEK_CUR
);
797 if(decode_info_header(nut
)<0)
800 case SYNCPOINT_STARTCODE
:
801 if(decode_syncpoint(nut
, &ts
, &back_ptr
)<0)
803 frame_code
= get_byte(bc
);
805 ret
= decode_frame(nut
, pkt
, frame_code
);
808 else if(ret
==1) //ok but discard packet
812 av_log(s
, AV_LOG_DEBUG
, "syncing from %"PRId64
"\n", pos
);
813 tmp
= find_any_startcode(bc
, nut
->last_syncpoint_pos
+1);
816 av_log(s
, AV_LOG_DEBUG
, "sync\n");
817 nut
->next_startcode
= tmp
;
822 static int64_t nut_read_timestamp(AVFormatContext
*s
, int stream_index
, int64_t *pos_arg
, int64_t pos_limit
){
823 NUTContext
*nut
= s
->priv_data
;
824 ByteIOContext
*bc
= s
->pb
;
825 int64_t pos
, pts
, back_ptr
;
826 av_log(s
, AV_LOG_DEBUG
, "read_timestamp(X,%d,%"PRId64
",%"PRId64
")\n", stream_index
, *pos_arg
, pos_limit
);
830 pos
= find_startcode(bc
, SYNCPOINT_STARTCODE
, pos
)+1;
832 assert(nut
->next_startcode
== 0);
833 av_log(s
, AV_LOG_ERROR
, "read_timestamp failed.\n");
834 return AV_NOPTS_VALUE
;
836 }while(decode_syncpoint(nut
, &pts
, &back_ptr
) < 0);
838 assert(nut
->last_syncpoint_pos
== *pos_arg
);
840 av_log(s
, AV_LOG_DEBUG
, "return %"PRId64
" %"PRId64
"\n", pts
,back_ptr
);
841 if (stream_index
== -1) return pts
;
842 else if(stream_index
== -2) return back_ptr
;
847 static int read_seek(AVFormatContext
*s
, int stream_index
, int64_t pts
, int flags
){
848 NUTContext
*nut
= s
->priv_data
;
849 AVStream
*st
= s
->streams
[stream_index
];
850 Syncpoint dummy
={.ts
= pts
*av_q2d(st
->time_base
)*AV_TIME_BASE
};
851 Syncpoint nopts_sp
= {.ts
= AV_NOPTS_VALUE
, .back_ptr
= AV_NOPTS_VALUE
};
852 Syncpoint
*sp
, *next_node
[2]= {&nopts_sp
, &nopts_sp
};
853 int64_t pos
, pos2
, ts
;
856 if(st
->index_entries
){
857 int index
= av_index_search_timestamp(st
, pts
, flags
);
861 pos2
= st
->index_entries
[index
].pos
;
862 ts
= st
->index_entries
[index
].timestamp
;
864 av_tree_find(nut
->syncpoints
, &dummy
, ff_nut_sp_pts_cmp
, next_node
);
865 av_log(s
, AV_LOG_DEBUG
, "%"PRIu64
"-%"PRIu64
" %"PRId64
"-%"PRId64
"\n", next_node
[0]->pos
, next_node
[1]->pos
,
866 next_node
[0]->ts
, next_node
[1]->ts
);
867 pos
= av_gen_search(s
, -1, dummy
.ts
, next_node
[0]->pos
, next_node
[1]->pos
, next_node
[1]->pos
,
868 next_node
[0]->ts
, next_node
[1]->ts
, AVSEEK_FLAG_BACKWARD
, &ts
, nut_read_timestamp
);
870 if(!(flags
& AVSEEK_FLAG_BACKWARD
)){
872 next_node
[1]= &nopts_sp
;
873 av_tree_find(nut
->syncpoints
, &dummy
, ff_nut_sp_pos_cmp
, next_node
);
874 pos2
= av_gen_search(s
, -2, dummy
.pos
, next_node
[0]->pos
, next_node
[1]->pos
, next_node
[1]->pos
,
875 next_node
[0]->back_ptr
, next_node
[1]->back_ptr
, flags
, &ts
, nut_read_timestamp
);
878 //FIXME dir but I think it does not matter
881 sp
= av_tree_find(nut
->syncpoints
, &dummy
, ff_nut_sp_pos_cmp
, NULL
);
884 pos2
= sp
->back_ptr
- 15;
886 av_log(NULL
, AV_LOG_DEBUG
, "SEEKTO: %"PRId64
"\n", pos2
);
887 pos
= find_startcode(s
->pb
, SYNCPOINT_STARTCODE
, pos2
);
888 url_fseek(s
->pb
, pos
, SEEK_SET
);
889 av_log(NULL
, AV_LOG_DEBUG
, "SP: %"PRId64
"\n", pos
);
890 if(pos2
> pos
|| pos2
+ 15 < pos
){
891 av_log(NULL
, AV_LOG_ERROR
, "no syncpoint at backptr pos\n");
893 for(i
=0; i
<s
->nb_streams
; i
++)
894 nut
->stream
[i
].skip_until_key_frame
=1;
899 static int nut_read_close(AVFormatContext
*s
)
901 NUTContext
*nut
= s
->priv_data
;
903 av_freep(&nut
->time_base
);
904 av_freep(&nut
->stream
);
909 #if CONFIG_NUT_DEMUXER
910 AVInputFormat nut_demuxer
= {
912 NULL_IF_CONFIG_SMALL("NUT format"),