Mercurial > libavformat.hg
annotate nutdec.c @ 5330:936a03bbd757 libavformat
Suppress ?params in the rtsp uri
Right now rtsp demuxer receives it's ffmpeg specific params encoded in the url
That made the server receiving requests with the url ending with "?udp",
"?multicast" and "?tcp". That may or may not cause problems to servers with
overly strict or overly simple uri parsers
Patch from Armand Bendanan (name.surnameATfreeDOTfr)
author | lu_zero |
---|---|
date | Sat, 24 Oct 2009 15:18:21 +0000 |
parents | 33a244b7ca65 |
children | 6b9c2a6d8fa4 |
rev | line source |
---|---|
1477 | 1 /* |
2 * "NUT" Container Format demuxer | |
3 * Copyright (c) 2004-2006 Michael Niedermayer | |
4 * Copyright (c) 2003 Alex Beregszaszi | |
5 * | |
6 * This file is part of FFmpeg. | |
7 * | |
8 * FFmpeg is free software; you can redistribute it and/or | |
9 * modify it under the terms of the GNU Lesser General Public | |
10 * License as published by the Free Software Foundation; either | |
11 * version 2.1 of the License, or (at your option) any later version. | |
12 * | |
13 * FFmpeg is distributed in the hope that it will be useful, | |
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 * Lesser General Public License for more details. | |
17 * | |
18 * You should have received a copy of the GNU Lesser General Public | |
19 * License along with FFmpeg; if not, write to the Free Software | |
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
21 */ | |
22 | |
4605 | 23 #include <strings.h> |
3286 | 24 #include "libavutil/avstring.h" |
4201
7d2f3f1b68d8
Fix build: Add intreadwrite.h and bswap.h #includes where necessary.
diego
parents:
4076
diff
changeset
|
25 #include "libavutil/bswap.h" |
3286 | 26 #include "libavutil/tree.h" |
1477 | 27 #include "nut.h" |
28 | |
29 #undef NDEBUG | |
30 #include <assert.h> | |
31 | |
32 static int get_str(ByteIOContext *bc, char *string, unsigned int maxlen){ | |
2700 | 33 unsigned int len= ff_get_v(bc); |
1477 | 34 |
35 if(len && maxlen) | |
36 get_buffer(bc, string, FFMIN(len, maxlen)); | |
37 while(len > maxlen){ | |
38 get_byte(bc); | |
39 len--; | |
40 } | |
41 | |
42 if(maxlen) | |
43 string[FFMIN(len, maxlen-1)]= 0; | |
44 | |
45 if(maxlen == len) | |
46 return -1; | |
47 else | |
48 return 0; | |
49 } | |
50 | |
51 static int64_t get_s(ByteIOContext *bc){ | |
2700 | 52 int64_t v = ff_get_v(bc) + 1; |
1477 | 53 |
54 if (v&1) return -(v>>1); | |
55 else return (v>>1); | |
56 } | |
57 | |
58 static uint64_t get_fourcc(ByteIOContext *bc){ | |
2700 | 59 unsigned int len= ff_get_v(bc); |
1477 | 60 |
61 if (len==2) return get_le16(bc); | |
62 else if(len==4) return get_le32(bc); | |
63 else return -1; | |
64 } | |
65 | |
66 #ifdef TRACE | |
67 static inline uint64_t get_v_trace(ByteIOContext *bc, char *file, char *func, int line){ | |
2700 | 68 uint64_t v= ff_get_v(bc); |
1477 | 69 |
2344 | 70 av_log(NULL, AV_LOG_DEBUG, "get_v %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line); |
1477 | 71 return v; |
72 } | |
73 | |
74 static inline int64_t get_s_trace(ByteIOContext *bc, char *file, char *func, int line){ | |
75 int64_t v= get_s(bc); | |
76 | |
2344 | 77 av_log(NULL, AV_LOG_DEBUG, "get_s %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line); |
1477 | 78 return v; |
79 } | |
80 | |
81 static inline uint64_t get_vb_trace(ByteIOContext *bc, char *file, char *func, int line){ | |
82 uint64_t v= get_vb(bc); | |
83 | |
2344 | 84 av_log(NULL, AV_LOG_DEBUG, "get_vb %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line); |
1477 | 85 return v; |
86 } | |
2700 | 87 #define ff_get_v(bc) get_v_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__) |
1477 | 88 #define get_s(bc) get_s_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__) |
89 #define get_vb(bc) get_vb_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__) | |
90 #endif | |
91 | |
2348 | 92 static int get_packetheader(NUTContext *nut, ByteIOContext *bc, int calculate_checksum, uint64_t startcode) |
1477 | 93 { |
2035 | 94 int64_t size; |
1477 | 95 // start= url_ftell(bc) - 8; |
96 | |
2348 | 97 startcode= be2me_64(startcode); |
2683
153d6efc05b8
rename av_crc04C11DB7_update to ff_crc04C11DB7_update and move it to aviobuf.c so it can be reused by other (de)muxers
bcoudurier
parents:
2553
diff
changeset
|
98 startcode= ff_crc04C11DB7_update(0, &startcode, 8); |
2348 | 99 |
2683
153d6efc05b8
rename av_crc04C11DB7_update to ff_crc04C11DB7_update and move it to aviobuf.c so it can be reused by other (de)muxers
bcoudurier
parents:
2553
diff
changeset
|
100 init_checksum(bc, ff_crc04C11DB7_update, startcode); |
2700 | 101 size= ff_get_v(bc); |
1820
ec025d5fbbe2
get_packetheader() forgot to read the header_checksum in big packets
lu_zero
parents:
1682
diff
changeset
|
102 if(size > 4096) |
2333 | 103 get_be32(bc); |
104 if(get_checksum(bc) && size > 4096) | |
105 return -1; | |
1477 | 106 |
2683
153d6efc05b8
rename av_crc04C11DB7_update to ff_crc04C11DB7_update and move it to aviobuf.c so it can be reused by other (de)muxers
bcoudurier
parents:
2553
diff
changeset
|
107 init_checksum(bc, calculate_checksum ? ff_crc04C11DB7_update : NULL, 0); |
1477 | 108 |
109 return size; | |
110 } | |
111 | |
112 static uint64_t find_any_startcode(ByteIOContext *bc, int64_t pos){ | |
113 uint64_t state=0; | |
114 | |
115 if(pos >= 0) | |
3142 | 116 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 |
1477 | 117 |
118 while(!url_feof(bc)){ | |
119 state= (state<<8) | get_byte(bc); | |
120 if((state>>56) != 'N') | |
121 continue; | |
122 switch(state){ | |
123 case MAIN_STARTCODE: | |
124 case STREAM_STARTCODE: | |
125 case SYNCPOINT_STARTCODE: | |
126 case INFO_STARTCODE: | |
127 case INDEX_STARTCODE: | |
128 return state; | |
129 } | |
130 } | |
131 | |
132 return 0; | |
133 } | |
134 | |
135 /** | |
2393 | 136 * Find the given startcode. |
1477 | 137 * @param code the startcode |
138 * @param pos the start position of the search, or -1 if the current position | |
139 * @returns the position of the startcode or -1 if not found | |
140 */ | |
141 static int64_t find_startcode(ByteIOContext *bc, uint64_t code, int64_t pos){ | |
142 for(;;){ | |
143 uint64_t startcode= find_any_startcode(bc, pos); | |
144 if(startcode == code) | |
145 return url_ftell(bc) - 8; | |
146 else if(startcode == 0) | |
147 return -1; | |
148 pos=-1; | |
149 } | |
150 } | |
151 | |
152 static int nut_probe(AVProbeData *p){ | |
153 int i; | |
154 uint64_t code= 0; | |
155 | |
156 for (i = 0; i < p->buf_size; i++) { | |
157 code = (code << 8) | p->buf[i]; | |
158 if (code == MAIN_STARTCODE) | |
159 return AVPROBE_SCORE_MAX; | |
160 } | |
161 return 0; | |
162 } | |
163 | |
164 #define GET_V(dst, check) \ | |
2700 | 165 tmp= ff_get_v(bc);\ |
1477 | 166 if(!(check)){\ |
167 av_log(s, AV_LOG_ERROR, "Error " #dst " is (%"PRId64")\n", tmp);\ | |
168 return -1;\ | |
169 }\ | |
170 dst= tmp; | |
171 | |
172 static int skip_reserved(ByteIOContext *bc, int64_t pos){ | |
173 pos -= url_ftell(bc); | |
174 if(pos<0){ | |
175 url_fseek(bc, pos, SEEK_CUR); | |
176 return -1; | |
177 }else{ | |
178 while(pos--) | |
179 get_byte(bc); | |
180 return 0; | |
181 } | |
182 } | |
183 | |
184 static int decode_main_header(NUTContext *nut){ | |
185 AVFormatContext *s= nut->avf; | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2700
diff
changeset
|
186 ByteIOContext *bc = s->pb; |
1477 | 187 uint64_t tmp, end; |
188 unsigned int stream_count; | |
3045 | 189 int i, j, tmp_stream, tmp_mul, tmp_pts, tmp_size, count, tmp_res, tmp_head_idx; |
3043 | 190 int64_t tmp_match; |
1477 | 191 |
2348 | 192 end= get_packetheader(nut, bc, 1, MAIN_STARTCODE); |
1485 | 193 end += url_ftell(bc); |
1477 | 194 |
195 GET_V(tmp , tmp >=2 && tmp <= 3) | |
196 GET_V(stream_count , tmp > 0 && tmp <=MAX_STREAMS) | |
197 | |
2700 | 198 nut->max_distance = ff_get_v(bc); |
1477 | 199 if(nut->max_distance > 65536){ |
200 av_log(s, AV_LOG_DEBUG, "max_distance %d\n", nut->max_distance); | |
201 nut->max_distance= 65536; | |
202 } | |
203 | |
204 GET_V(nut->time_base_count, tmp>0 && tmp<INT_MAX / sizeof(AVRational)) | |
205 nut->time_base= av_malloc(nut->time_base_count * sizeof(AVRational)); | |
206 | |
207 for(i=0; i<nut->time_base_count; i++){ | |
208 GET_V(nut->time_base[i].num, tmp>0 && tmp<(1ULL<<31)) | |
209 GET_V(nut->time_base[i].den, tmp>0 && tmp<(1ULL<<31)) | |
4242 | 210 if(av_gcd(nut->time_base[i].num, nut->time_base[i].den) != 1){ |
1477 | 211 av_log(s, AV_LOG_ERROR, "time base invalid\n"); |
212 return -1; | |
213 } | |
214 } | |
215 tmp_pts=0; | |
216 tmp_mul=1; | |
217 tmp_stream=0; | |
3043 | 218 tmp_match= 1-(1LL<<62); |
3045 | 219 tmp_head_idx= 0; |
1477 | 220 for(i=0; i<256;){ |
2700 | 221 int tmp_flags = ff_get_v(bc); |
222 int tmp_fields= ff_get_v(bc); | |
1477 | 223 if(tmp_fields>0) tmp_pts = get_s(bc); |
2700 | 224 if(tmp_fields>1) tmp_mul = ff_get_v(bc); |
225 if(tmp_fields>2) tmp_stream= ff_get_v(bc); | |
226 if(tmp_fields>3) tmp_size = ff_get_v(bc); | |
1477 | 227 else tmp_size = 0; |
2700 | 228 if(tmp_fields>4) tmp_res = ff_get_v(bc); |
1477 | 229 else tmp_res = 0; |
2700 | 230 if(tmp_fields>5) count = ff_get_v(bc); |
1477 | 231 else count = tmp_mul - tmp_size; |
3043 | 232 if(tmp_fields>6) tmp_match = get_s(bc); |
3045 | 233 if(tmp_fields>7) tmp_head_idx= ff_get_v(bc); |
1477 | 234 |
3045 | 235 while(tmp_fields-- > 8) |
2700 | 236 ff_get_v(bc); |
1477 | 237 |
238 if(count == 0 || i+count > 256){ | |
239 av_log(s, AV_LOG_ERROR, "illegal count %d at %d\n", count, i); | |
240 return -1; | |
241 } | |
242 if(tmp_stream >= stream_count){ | |
243 av_log(s, AV_LOG_ERROR, "illegal stream number\n"); | |
244 return -1; | |
245 } | |
246 | |
247 for(j=0; j<count; j++,i++){ | |
248 if (i == 'N') { | |
249 nut->frame_code[i].flags= FLAG_INVALID; | |
250 j--; | |
251 continue; | |
252 } | |
253 nut->frame_code[i].flags = tmp_flags ; | |
254 nut->frame_code[i].pts_delta = tmp_pts ; | |
255 nut->frame_code[i].stream_id = tmp_stream; | |
256 nut->frame_code[i].size_mul = tmp_mul ; | |
257 nut->frame_code[i].size_lsb = tmp_size+j; | |
258 nut->frame_code[i].reserved_count = tmp_res ; | |
3045 | 259 nut->frame_code[i].header_idx = tmp_head_idx; |
1477 | 260 } |
261 } | |
262 assert(nut->frame_code['N'].flags == FLAG_INVALID); | |
263 | |
3045 | 264 if(end > url_ftell(bc) + 4){ |
265 int rem= 1024; | |
266 GET_V(nut->header_count, tmp<128U) | |
267 nut->header_count++; | |
268 for(i=1; i<nut->header_count; i++){ | |
269 GET_V(nut->header_len[i], tmp>0 && tmp<256); | |
270 rem -= nut->header_len[i]; | |
271 if(rem < 0){ | |
272 av_log(s, AV_LOG_ERROR, "invalid elision header\n"); | |
273 return -1; | |
274 } | |
275 nut->header[i]= av_malloc(nut->header_len[i]); | |
276 get_buffer(bc, nut->header[i], nut->header_len[i]); | |
277 } | |
278 assert(nut->header_len[0]==0); | |
279 } | |
280 | |
1485 | 281 if(skip_reserved(bc, end) || get_checksum(bc)){ |
2393 | 282 av_log(s, AV_LOG_ERROR, "main header checksum mismatch\n"); |
1477 | 283 return -1; |
284 } | |
285 | |
286 nut->stream = av_mallocz(sizeof(StreamContext)*stream_count); | |
287 for(i=0; i<stream_count; i++){ | |
288 av_new_stream(s, i); | |
289 } | |
290 | |
291 return 0; | |
292 } | |
293 | |
294 static int decode_stream_header(NUTContext *nut){ | |
295 AVFormatContext *s= nut->avf; | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2700
diff
changeset
|
296 ByteIOContext *bc = s->pb; |
1477 | 297 StreamContext *stc; |
1516 | 298 int class, stream_id; |
1477 | 299 uint64_t tmp, end; |
300 AVStream *st; | |
301 | |
2348 | 302 end= get_packetheader(nut, bc, 1, STREAM_STARTCODE); |
1485 | 303 end += url_ftell(bc); |
1477 | 304 |
2327 | 305 GET_V(stream_id, tmp < s->nb_streams && !nut->stream[tmp].time_base); |
1477 | 306 stc= &nut->stream[stream_id]; |
307 | |
308 st = s->streams[stream_id]; | |
309 if (!st) | |
2273
7eb456c4ed8a
Replace all occurrences of AVERROR_NOMEM with AVERROR(ENOMEM).
takis
parents:
2228
diff
changeset
|
310 return AVERROR(ENOMEM); |
1477 | 311 |
2700 | 312 class = ff_get_v(bc); |
1477 | 313 tmp = get_fourcc(bc); |
314 st->codec->codec_tag= tmp; | |
315 switch(class) | |
316 { | |
317 case 0: | |
318 st->codec->codec_type = CODEC_TYPE_VIDEO; | |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
4605
diff
changeset
|
319 st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, tmp); |
1477 | 320 break; |
321 case 1: | |
322 st->codec->codec_type = CODEC_TYPE_AUDIO; | |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
4605
diff
changeset
|
323 st->codec->codec_id = ff_codec_get_id(ff_codec_wav_tags, tmp); |
1477 | 324 break; |
325 case 2: | |
3101 | 326 st->codec->codec_type = CODEC_TYPE_SUBTITLE; |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
4605
diff
changeset
|
327 st->codec->codec_id = ff_codec_get_id(ff_nut_subtitle_tags, tmp); |
3101 | 328 break; |
1477 | 329 case 3: |
330 st->codec->codec_type = CODEC_TYPE_DATA; | |
331 break; | |
332 default: | |
2393 | 333 av_log(s, AV_LOG_ERROR, "unknown stream class (%d)\n", class); |
1477 | 334 return -1; |
335 } | |
3102 | 336 if(class<3 && st->codec->codec_id == CODEC_ID_NONE) |
337 av_log(s, AV_LOG_ERROR, "Unknown codec?!\n"); | |
338 | |
1477 | 339 GET_V(stc->time_base_id , tmp < nut->time_base_count); |
340 GET_V(stc->msb_pts_shift , tmp < 16); | |
2700 | 341 stc->max_pts_distance= ff_get_v(bc); |
2393 | 342 GET_V(stc->decode_delay , tmp < 1000); //sanity limit, raise this if Moore's law is true |
1477 | 343 st->codec->has_b_frames= stc->decode_delay; |
2700 | 344 ff_get_v(bc); //stream flags |
1477 | 345 |
346 GET_V(st->codec->extradata_size, tmp < (1<<30)); | |
347 if(st->codec->extradata_size){ | |
348 st->codec->extradata= av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); | |
349 get_buffer(bc, st->codec->extradata, st->codec->extradata_size); | |
350 } | |
351 | |
352 if (st->codec->codec_type == CODEC_TYPE_VIDEO){ | |
353 GET_V(st->codec->width , tmp > 0) | |
354 GET_V(st->codec->height, tmp > 0) | |
3759
27537074f2a9
convert every muxer/demuxer to write/read sample_aspect_ratio from/to
aurel
parents:
3424
diff
changeset
|
355 st->sample_aspect_ratio.num= ff_get_v(bc); |
27537074f2a9
convert every muxer/demuxer to write/read sample_aspect_ratio from/to
aurel
parents:
3424
diff
changeset
|
356 st->sample_aspect_ratio.den= ff_get_v(bc); |
27537074f2a9
convert every muxer/demuxer to write/read sample_aspect_ratio from/to
aurel
parents:
3424
diff
changeset
|
357 if((!st->sample_aspect_ratio.num) != (!st->sample_aspect_ratio.den)){ |
27537074f2a9
convert every muxer/demuxer to write/read sample_aspect_ratio from/to
aurel
parents:
3424
diff
changeset
|
358 av_log(s, AV_LOG_ERROR, "invalid aspect ratio %d/%d\n", st->sample_aspect_ratio.num, st->sample_aspect_ratio.den); |
1477 | 359 return -1; |
360 } | |
2700 | 361 ff_get_v(bc); /* csp type */ |
1477 | 362 }else if (st->codec->codec_type == CODEC_TYPE_AUDIO){ |
363 GET_V(st->codec->sample_rate , tmp > 0) | |
3013 | 364 ff_get_v(bc); // samplerate_den |
1477 | 365 GET_V(st->codec->channels, tmp > 0) |
366 } | |
1485 | 367 if(skip_reserved(bc, end) || get_checksum(bc)){ |
2393 | 368 av_log(s, AV_LOG_ERROR, "stream header %d checksum mismatch\n", stream_id); |
1477 | 369 return -1; |
370 } | |
2327 | 371 stc->time_base= &nut->time_base[stc->time_base_id]; |
372 av_set_pts_info(s->streams[stream_id], 63, stc->time_base->num, stc->time_base->den); | |
1477 | 373 return 0; |
374 } | |
375 | |
3120
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
376 static void set_disposition_bits(AVFormatContext* avf, char* value, int stream_id){ |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
377 int flag = 0, i; |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
378 for (i=0; ff_nut_dispositions[i].flag; ++i) { |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
379 if (!strcmp(ff_nut_dispositions[i].str, value)) |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
380 flag = ff_nut_dispositions[i].flag; |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
381 } |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
382 if (!flag) |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
383 av_log(avf, AV_LOG_INFO, "unknown disposition type '%s'\n", value); |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
384 for (i = 0; i < avf->nb_streams; ++i) |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
385 if (stream_id == i || stream_id == -1) |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
386 avf->streams[i]->disposition |= flag; |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
387 } |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
388 |
1477 | 389 static int decode_info_header(NUTContext *nut){ |
390 AVFormatContext *s= nut->avf; | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2700
diff
changeset
|
391 ByteIOContext *bc = s->pb; |
1477 | 392 uint64_t tmp; |
393 unsigned int stream_id_plus1, chapter_start, chapter_len, count; | |
394 int chapter_id, i; | |
395 int64_t value, end; | |
3005 | 396 char name[256], str_value[1024], type_str[256]; |
3006
fa2fb523fd6b
Fix info packet type, found by oded as well as the new pedantic const
michael
parents:
3005
diff
changeset
|
397 const char *type; |
3331
f89173ea4c5e
Chapter demuxing support. (untested as I have no nuts with chapters)
michael
parents:
3286
diff
changeset
|
398 AVChapter *chapter= NULL; |
4605 | 399 AVStream *st= NULL; |
1477 | 400 |
2348 | 401 end= get_packetheader(nut, bc, 1, INFO_STARTCODE); |
1485 | 402 end += url_ftell(bc); |
1477 | 403 |
404 GET_V(stream_id_plus1, tmp <= s->nb_streams) | |
405 chapter_id = get_s(bc); | |
2700 | 406 chapter_start= ff_get_v(bc); |
407 chapter_len = ff_get_v(bc); | |
408 count = ff_get_v(bc); | |
3331
f89173ea4c5e
Chapter demuxing support. (untested as I have no nuts with chapters)
michael
parents:
3286
diff
changeset
|
409 |
f89173ea4c5e
Chapter demuxing support. (untested as I have no nuts with chapters)
michael
parents:
3286
diff
changeset
|
410 if(chapter_id && !stream_id_plus1){ |
f89173ea4c5e
Chapter demuxing support. (untested as I have no nuts with chapters)
michael
parents:
3286
diff
changeset
|
411 int64_t start= chapter_start / nut->time_base_count; |
3334
7a823a401282
Pass time_base as argument to new_chapter() as well.
michael
parents:
3331
diff
changeset
|
412 chapter= ff_new_chapter(s, chapter_id, |
7a823a401282
Pass time_base as argument to new_chapter() as well.
michael
parents:
3331
diff
changeset
|
413 nut->time_base[chapter_start % nut->time_base_count], |
7a823a401282
Pass time_base as argument to new_chapter() as well.
michael
parents:
3331
diff
changeset
|
414 start, start + chapter_len, NULL); |
4605 | 415 } else if(stream_id_plus1) |
416 st= s->streams[stream_id_plus1 - 1]; | |
3331
f89173ea4c5e
Chapter demuxing support. (untested as I have no nuts with chapters)
michael
parents:
3286
diff
changeset
|
417 |
1477 | 418 for(i=0; i<count; i++){ |
419 get_str(bc, name, sizeof(name)); | |
420 value= get_s(bc); | |
421 if(value == -1){ | |
422 type= "UTF-8"; | |
423 get_str(bc, str_value, sizeof(str_value)); | |
424 }else if(value == -2){ | |
3006
fa2fb523fd6b
Fix info packet type, found by oded as well as the new pedantic const
michael
parents:
3005
diff
changeset
|
425 get_str(bc, type_str, sizeof(type_str)); |
fa2fb523fd6b
Fix info packet type, found by oded as well as the new pedantic const
michael
parents:
3005
diff
changeset
|
426 type= type_str; |
1477 | 427 get_str(bc, str_value, sizeof(str_value)); |
428 }else if(value == -3){ | |
429 type= "s"; | |
430 value= get_s(bc); | |
431 }else if(value == -4){ | |
432 type= "t"; | |
2700 | 433 value= ff_get_v(bc); |
1477 | 434 }else if(value < -4){ |
435 type= "r"; | |
436 get_s(bc); | |
437 }else{ | |
438 type= "v"; | |
439 } | |
440 | |
3275 | 441 if (stream_id_plus1 > s->nb_streams) { |
3120
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
442 av_log(s, AV_LOG_ERROR, "invalid stream id for info packet\n"); |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
443 continue; |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
444 } |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
445 |
4605 | 446 if(!strcmp(type, "UTF-8")){ |
447 AVMetadata **metadata = NULL; | |
448 if(chapter_id==0 && !strcmp(name, "Disposition")) | |
3120
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
449 set_disposition_bits(s, str_value, stream_id_plus1 - 1); |
4605 | 450 else if(chapter) metadata= &chapter->metadata; |
451 else if(stream_id_plus1) metadata= &st->metadata; | |
452 else metadata= &s->metadata; | |
453 if(metadata && strcasecmp(name,"Uses") | |
454 && strcasecmp(name,"Depends") && strcasecmp(name,"Replaces")) | |
455 av_metadata_set(metadata, name, str_value); | |
3331
f89173ea4c5e
Chapter demuxing support. (untested as I have no nuts with chapters)
michael
parents:
3286
diff
changeset
|
456 } |
1477 | 457 } |
458 | |
1485 | 459 if(skip_reserved(bc, end) || get_checksum(bc)){ |
2393 | 460 av_log(s, AV_LOG_ERROR, "info header checksum mismatch\n"); |
1477 | 461 return -1; |
462 } | |
463 return 0; | |
464 } | |
465 | |
1500 | 466 static int decode_syncpoint(NUTContext *nut, int64_t *ts, int64_t *back_ptr){ |
1477 | 467 AVFormatContext *s= nut->avf; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2700
diff
changeset
|
468 ByteIOContext *bc = s->pb; |
1500 | 469 int64_t end, tmp; |
1477 | 470 |
1478 | 471 nut->last_syncpoint_pos= url_ftell(bc)-8; |
1477 | 472 |
2348 | 473 end= get_packetheader(nut, bc, 1, SYNCPOINT_STARTCODE); |
1485 | 474 end += url_ftell(bc); |
1477 | 475 |
2700 | 476 tmp= ff_get_v(bc); |
477 *back_ptr= nut->last_syncpoint_pos - 16*ff_get_v(bc); | |
1500 | 478 if(*back_ptr < 0) |
479 return -1; | |
1477 | 480 |
3011
0439b354e005
ff_nut_reset_ts() expected to get 'ts*time_base_count', but muxer only
ods15
parents:
3006
diff
changeset
|
481 ff_nut_reset_ts(nut, nut->time_base[tmp % nut->time_base_count], tmp / nut->time_base_count); |
1477 | 482 |
1485 | 483 if(skip_reserved(bc, end) || get_checksum(bc)){ |
1478 | 484 av_log(s, AV_LOG_ERROR, "sync point checksum mismatch\n"); |
1477 | 485 return -1; |
486 } | |
1500 | 487 |
488 *ts= tmp / s->nb_streams * av_q2d(nut->time_base[tmp % s->nb_streams])*AV_TIME_BASE; | |
2349 | 489 ff_nut_add_sp(nut, nut->last_syncpoint_pos, *back_ptr, *ts); |
1500 | 490 |
1477 | 491 return 0; |
492 } | |
493 | |
1484 | 494 static int find_and_decode_index(NUTContext *nut){ |
495 AVFormatContext *s= nut->avf; | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2700
diff
changeset
|
496 ByteIOContext *bc = s->pb; |
1484 | 497 uint64_t tmp, end; |
498 int i, j, syncpoint_count; | |
499 int64_t filesize= url_fsize(bc); | |
500 int64_t *syncpoints; | |
501 int8_t *has_keyframe; | |
3377 | 502 int ret= -1; |
1484 | 503 |
504 url_fseek(bc, filesize-12, SEEK_SET); | |
505 url_fseek(bc, filesize-get_be64(bc), SEEK_SET); | |
506 if(get_be64(bc) != INDEX_STARTCODE){ | |
507 av_log(s, AV_LOG_ERROR, "no index at the end\n"); | |
508 return -1; | |
509 } | |
510 | |
2348 | 511 end= get_packetheader(nut, bc, 1, INDEX_STARTCODE); |
1485 | 512 end += url_ftell(bc); |
1484 | 513 |
2700 | 514 ff_get_v(bc); //max_pts |
1484 | 515 GET_V(syncpoint_count, tmp < INT_MAX/8 && tmp > 0) |
516 syncpoints= av_malloc(sizeof(int64_t)*syncpoint_count); | |
517 has_keyframe= av_malloc(sizeof(int8_t)*(syncpoint_count+1)); | |
518 for(i=0; i<syncpoint_count; i++){ | |
3377 | 519 syncpoints[i] = ff_get_v(bc); |
520 if(syncpoints[i] <= 0) | |
521 goto fail; | |
1484 | 522 if(i) |
523 syncpoints[i] += syncpoints[i-1]; | |
524 } | |
525 | |
526 for(i=0; i<s->nb_streams; i++){ | |
527 int64_t last_pts= -1; | |
528 for(j=0; j<syncpoint_count;){ | |
2700 | 529 uint64_t x= ff_get_v(bc); |
1484 | 530 int type= x&1; |
531 int n= j; | |
532 x>>=1; | |
533 if(type){ | |
534 int flag= x&1; | |
535 x>>=1; | |
536 if(n+x >= syncpoint_count + 1){ | |
537 av_log(s, AV_LOG_ERROR, "index overflow A\n"); | |
3377 | 538 goto fail; |
1484 | 539 } |
540 while(x--) | |
541 has_keyframe[n++]= flag; | |
542 has_keyframe[n++]= !flag; | |
543 }else{ | |
544 while(x != 1){ | |
545 if(n>=syncpoint_count + 1){ | |
546 av_log(s, AV_LOG_ERROR, "index overflow B\n"); | |
3377 | 547 goto fail; |
1484 | 548 } |
549 has_keyframe[n++]= x&1; | |
550 x>>=1; | |
551 } | |
552 } | |
553 if(has_keyframe[0]){ | |
554 av_log(s, AV_LOG_ERROR, "keyframe before first syncpoint in index\n"); | |
3377 | 555 goto fail; |
1484 | 556 } |
557 assert(n<=syncpoint_count+1); | |
3012
2214e8b1cb4d
missing " && j<syncpoint_count" protection in the index parsing, as the
ods15
parents:
3011
diff
changeset
|
558 for(; j<n && j<syncpoint_count; j++){ |
1484 | 559 if(has_keyframe[j]){ |
2700 | 560 uint64_t B, A= ff_get_v(bc); |
1484 | 561 if(!A){ |
2700 | 562 A= ff_get_v(bc); |
563 B= ff_get_v(bc); | |
1484 | 564 //eor_pts[j][i] = last_pts + A + B |
565 }else | |
566 B= 0; | |
567 av_add_index_entry( | |
568 s->streams[i], | |
569 16*syncpoints[j-1], | |
570 last_pts + A, | |
571 0, | |
572 0, | |
573 AVINDEX_KEYFRAME); | |
574 last_pts += A + B; | |
575 } | |
576 } | |
577 } | |
578 } | |
579 | |
1485 | 580 if(skip_reserved(bc, end) || get_checksum(bc)){ |
2393 | 581 av_log(s, AV_LOG_ERROR, "index checksum mismatch\n"); |
3377 | 582 goto fail; |
1484 | 583 } |
3377 | 584 ret= 0; |
585 fail: | |
586 av_free(syncpoints); | |
587 av_free(has_keyframe); | |
588 return ret; | |
1484 | 589 } |
590 | |
1477 | 591 static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap) |
592 { | |
593 NUTContext *nut = s->priv_data; | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2700
diff
changeset
|
594 ByteIOContext *bc = s->pb; |
1477 | 595 int64_t pos; |
3035 | 596 int initialized_stream_count; |
1477 | 597 |
598 nut->avf= s; | |
599 | |
600 /* main header */ | |
601 pos=0; | |
1480 | 602 do{ |
1477 | 603 pos= find_startcode(bc, MAIN_STARTCODE, pos)+1; |
604 if (pos<0+1){ | |
2393 | 605 av_log(s, AV_LOG_ERROR, "No main startcode found.\n"); |
1477 | 606 return -1; |
607 } | |
1480 | 608 }while(decode_main_header(nut) < 0); |
1477 | 609 |
610 /* stream headers */ | |
611 pos=0; | |
3035 | 612 for(initialized_stream_count=0; initialized_stream_count < s->nb_streams;){ |
1477 | 613 pos= find_startcode(bc, STREAM_STARTCODE, pos)+1; |
614 if (pos<0+1){ | |
2393 | 615 av_log(s, AV_LOG_ERROR, "Not all stream headers found.\n"); |
1477 | 616 return -1; |
617 } | |
618 if(decode_stream_header(nut) >= 0) | |
3035 | 619 initialized_stream_count++; |
1477 | 620 } |
621 | |
622 /* info headers */ | |
623 pos=0; | |
624 for(;;){ | |
625 uint64_t startcode= find_any_startcode(bc, pos); | |
626 pos= url_ftell(bc); | |
627 | |
628 if(startcode==0){ | |
629 av_log(s, AV_LOG_ERROR, "EOF before video frames\n"); | |
630 return -1; | |
631 }else if(startcode == SYNCPOINT_STARTCODE){ | |
632 nut->next_startcode= startcode; | |
633 break; | |
634 }else if(startcode != INFO_STARTCODE){ | |
635 continue; | |
636 } | |
637 | |
638 decode_info_header(nut); | |
639 } | |
640 | |
1478 | 641 s->data_offset= pos-8; |
642 | |
1501 | 643 if(!url_is_streamed(bc)){ |
1484 | 644 int64_t orig_pos= url_ftell(bc); |
645 find_and_decode_index(nut); | |
646 url_fseek(bc, orig_pos, SEEK_SET); | |
647 } | |
648 assert(nut->next_startcode == SYNCPOINT_STARTCODE); | |
649 | |
1477 | 650 return 0; |
651 } | |
652 | |
3045 | 653 static int decode_frame_header(NUTContext *nut, int64_t *pts, int *stream_id, uint8_t *header_idx, int frame_code){ |
1477 | 654 AVFormatContext *s= nut->avf; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2700
diff
changeset
|
655 ByteIOContext *bc = s->pb; |
1477 | 656 StreamContext *stc; |
657 int size, flags, size_mul, pts_delta, i, reserved_count; | |
658 uint64_t tmp; | |
659 | |
660 if(url_ftell(bc) > nut->last_syncpoint_pos + nut->max_distance){ | |
2393 | 661 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); |
1477 | 662 return -1; |
663 } | |
664 | |
665 flags = nut->frame_code[frame_code].flags; | |
666 size_mul = nut->frame_code[frame_code].size_mul; | |
667 size = nut->frame_code[frame_code].size_lsb; | |
668 *stream_id = nut->frame_code[frame_code].stream_id; | |
669 pts_delta = nut->frame_code[frame_code].pts_delta; | |
670 reserved_count = nut->frame_code[frame_code].reserved_count; | |
3045 | 671 *header_idx = nut->frame_code[frame_code].header_idx; |
1477 | 672 |
673 if(flags & FLAG_INVALID) | |
674 return -1; | |
675 if(flags & FLAG_CODED) | |
2700 | 676 flags ^= ff_get_v(bc); |
1477 | 677 if(flags & FLAG_STREAM_ID){ |
678 GET_V(*stream_id, tmp < s->nb_streams) | |
679 } | |
680 stc= &nut->stream[*stream_id]; | |
681 if(flags&FLAG_CODED_PTS){ | |
2700 | 682 int coded_pts= ff_get_v(bc); |
1477 | 683 //FIXME check last_pts validity? |
684 if(coded_pts < (1<<stc->msb_pts_shift)){ | |
2338 | 685 *pts=ff_lsb2full(stc, coded_pts); |
1477 | 686 }else |
687 *pts=coded_pts - (1<<stc->msb_pts_shift); | |
688 }else | |
689 *pts= stc->last_pts + pts_delta; | |
690 if(flags&FLAG_SIZE_MSB){ | |
2700 | 691 size += size_mul*ff_get_v(bc); |
1477 | 692 } |
3044 | 693 if(flags&FLAG_MATCH_TIME) |
694 get_s(bc); | |
3045 | 695 if(flags&FLAG_HEADER_IDX) |
696 *header_idx= ff_get_v(bc); | |
1477 | 697 if(flags&FLAG_RESERVED) |
2700 | 698 reserved_count= ff_get_v(bc); |
1477 | 699 for(i=0; i<reserved_count; i++) |
2700 | 700 ff_get_v(bc); |
3045 | 701 |
702 if(*header_idx >= (unsigned)nut->header_count){ | |
703 av_log(s, AV_LOG_ERROR, "header_idx invalid\n"); | |
704 return -1; | |
705 } | |
706 if(size > 4096) | |
707 *header_idx=0; | |
708 size -= nut->header_len[*header_idx]; | |
709 | |
1477 | 710 if(flags&FLAG_CHECKSUM){ |
711 get_be32(bc); //FIXME check this | |
1518 | 712 }else if(size > 2*nut->max_distance || FFABS(stc->last_pts - *pts) > stc->max_pts_distance){ |
1509
edc979a1ecb5
check for frames with 2*size > max_dist and no crc
michael
parents:
1508
diff
changeset
|
713 av_log(s, AV_LOG_ERROR, "frame size > 2max_distance and no checksum\n"); |
edc979a1ecb5
check for frames with 2*size > max_dist and no crc
michael
parents:
1508
diff
changeset
|
714 return -1; |
1477 | 715 } |
716 | |
717 stc->last_pts= *pts; | |
1518 | 718 stc->last_flags= flags; |
1477 | 719 |
720 return size; | |
721 } | |
722 | |
723 static int decode_frame(NUTContext *nut, AVPacket *pkt, int frame_code){ | |
724 AVFormatContext *s= nut->avf; | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2700
diff
changeset
|
725 ByteIOContext *bc = s->pb; |
1518 | 726 int size, stream_id, discard; |
1477 | 727 int64_t pts, last_IP_pts; |
1518 | 728 StreamContext *stc; |
3045 | 729 uint8_t header_idx; |
1477 | 730 |
3045 | 731 size= decode_frame_header(nut, &pts, &stream_id, &header_idx, frame_code); |
1477 | 732 if(size < 0) |
733 return -1; | |
734 | |
1518 | 735 stc= &nut->stream[stream_id]; |
736 | |
737 if (stc->last_flags & FLAG_KEY) | |
738 stc->skip_until_key_frame=0; | |
1517
51b29c17bd1f
skip non keyframes after seeking between syncpoint and the first keyframe
michael
parents:
1516
diff
changeset
|
739 |
1477 | 740 discard= s->streams[ stream_id ]->discard; |
741 last_IP_pts= s->streams[ stream_id ]->last_IP_pts; | |
1518 | 742 if( (discard >= AVDISCARD_NONKEY && !(stc->last_flags & FLAG_KEY)) |
1477 | 743 ||(discard >= AVDISCARD_BIDIR && last_IP_pts != AV_NOPTS_VALUE && last_IP_pts > pts) |
1517
51b29c17bd1f
skip non keyframes after seeking between syncpoint and the first keyframe
michael
parents:
1516
diff
changeset
|
744 || discard >= AVDISCARD_ALL |
1518 | 745 || stc->skip_until_key_frame){ |
1477 | 746 url_fskip(bc, size); |
747 return 1; | |
748 } | |
749 | |
3045 | 750 av_new_packet(pkt, size + nut->header_len[header_idx]); |
751 memcpy(pkt->data, nut->header[header_idx], nut->header_len[header_idx]); | |
752 pkt->pos= url_ftell(bc); //FIXME | |
753 get_buffer(bc, pkt->data + nut->header_len[header_idx], size); | |
754 | |
1477 | 755 pkt->stream_index = stream_id; |
1518 | 756 if (stc->last_flags & FLAG_KEY) |
1477 | 757 pkt->flags |= PKT_FLAG_KEY; |
758 pkt->pts = pts; | |
759 | |
760 return 0; | |
761 } | |
762 | |
763 static int nut_read_packet(AVFormatContext *s, AVPacket *pkt) | |
764 { | |
765 NUTContext *nut = s->priv_data; | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2700
diff
changeset
|
766 ByteIOContext *bc = s->pb; |
1477 | 767 int i, frame_code=0, ret, skip; |
1500 | 768 int64_t ts, back_ptr; |
1477 | 769 |
770 for(;;){ | |
771 int64_t pos= url_ftell(bc); | |
772 uint64_t tmp= nut->next_startcode; | |
773 nut->next_startcode=0; | |
774 | |
775 if(tmp){ | |
776 pos-=8; | |
777 }else{ | |
778 frame_code = get_byte(bc); | |
1933 | 779 if(url_feof(bc)) |
780 return -1; | |
1477 | 781 if(frame_code == 'N'){ |
782 tmp= frame_code; | |
783 for(i=1; i<8; i++) | |
784 tmp = (tmp<<8) + get_byte(bc); | |
785 } | |
786 } | |
787 switch(tmp){ | |
788 case MAIN_STARTCODE: | |
789 case STREAM_STARTCODE: | |
790 case INDEX_STARTCODE: | |
2348 | 791 skip= get_packetheader(nut, bc, 0, tmp); |
1477 | 792 url_fseek(bc, skip, SEEK_CUR); |
793 break; | |
794 case INFO_STARTCODE: | |
795 if(decode_info_header(nut)<0) | |
796 goto resync; | |
797 break; | |
798 case SYNCPOINT_STARTCODE: | |
1500 | 799 if(decode_syncpoint(nut, &ts, &back_ptr)<0) |
1477 | 800 goto resync; |
801 frame_code = get_byte(bc); | |
802 case 0: | |
803 ret= decode_frame(nut, pkt, frame_code); | |
804 if(ret==0) | |
805 return 0; | |
806 else if(ret==1) //ok but discard packet | |
807 break; | |
808 default: | |
809 resync: | |
810 av_log(s, AV_LOG_DEBUG, "syncing from %"PRId64"\n", pos); | |
1508 | 811 tmp= find_any_startcode(bc, nut->last_syncpoint_pos+1); |
1477 | 812 if(tmp==0) |
813 return -1; | |
814 av_log(s, AV_LOG_DEBUG, "sync\n"); | |
815 nut->next_startcode= tmp; | |
816 } | |
817 } | |
818 } | |
819 | |
1478 | 820 static int64_t nut_read_timestamp(AVFormatContext *s, int stream_index, int64_t *pos_arg, int64_t pos_limit){ |
821 NUTContext *nut = s->priv_data; | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2700
diff
changeset
|
822 ByteIOContext *bc = s->pb; |
1500 | 823 int64_t pos, pts, back_ptr; |
1478 | 824 av_log(s, AV_LOG_DEBUG, "read_timestamp(X,%d,%"PRId64",%"PRId64")\n", stream_index, *pos_arg, pos_limit); |
825 | |
826 pos= *pos_arg; | |
827 do{ | |
828 pos= find_startcode(bc, SYNCPOINT_STARTCODE, pos)+1; | |
829 if(pos < 1){ | |
830 assert(nut->next_startcode == 0); | |
2393 | 831 av_log(s, AV_LOG_ERROR, "read_timestamp failed.\n"); |
1478 | 832 return AV_NOPTS_VALUE; |
833 } | |
1500 | 834 }while(decode_syncpoint(nut, &pts, &back_ptr) < 0); |
1478 | 835 *pos_arg = pos-1; |
836 assert(nut->last_syncpoint_pos == *pos_arg); | |
837 | |
2170 | 838 av_log(s, AV_LOG_DEBUG, "return %"PRId64" %"PRId64"\n", pts,back_ptr ); |
1500 | 839 if (stream_index == -1) return pts; |
840 else if(stream_index == -2) return back_ptr; | |
841 | |
842 assert(0); | |
1478 | 843 } |
844 | |
1500 | 845 static int read_seek(AVFormatContext *s, int stream_index, int64_t pts, int flags){ |
846 NUTContext *nut = s->priv_data; | |
847 AVStream *st= s->streams[stream_index]; | |
4076 | 848 Syncpoint dummy={.ts= pts*av_q2d(st->time_base)*AV_TIME_BASE}; |
849 Syncpoint nopts_sp= {.ts= AV_NOPTS_VALUE, .back_ptr= AV_NOPTS_VALUE}; | |
850 Syncpoint *sp, *next_node[2]= {&nopts_sp, &nopts_sp}; | |
1500 | 851 int64_t pos, pos2, ts; |
1517
51b29c17bd1f
skip non keyframes after seeking between syncpoint and the first keyframe
michael
parents:
1516
diff
changeset
|
852 int i; |
1500 | 853 |
1501 | 854 if(st->index_entries){ |
855 int index= av_index_search_timestamp(st, pts, flags); | |
856 if(index<0) | |
857 return -1; | |
858 | |
859 pos2= st->index_entries[index].pos; | |
860 ts = st->index_entries[index].timestamp; | |
861 }else{ | |
2349 | 862 av_tree_find(nut->syncpoints, &dummy, ff_nut_sp_pts_cmp, next_node); |
2170 | 863 av_log(s, AV_LOG_DEBUG, "%"PRIu64"-%"PRIu64" %"PRId64"-%"PRId64"\n", next_node[0]->pos, next_node[1]->pos, |
1502 | 864 next_node[0]->ts , next_node[1]->ts); |
865 pos= av_gen_search(s, -1, dummy.ts, next_node[0]->pos, next_node[1]->pos, next_node[1]->pos, | |
866 next_node[0]->ts , next_node[1]->ts, AVSEEK_FLAG_BACKWARD, &ts, nut_read_timestamp); | |
1500 | 867 |
1502 | 868 if(!(flags & AVSEEK_FLAG_BACKWARD)){ |
869 dummy.pos= pos+16; | |
870 next_node[1]= &nopts_sp; | |
2349 | 871 av_tree_find(nut->syncpoints, &dummy, ff_nut_sp_pos_cmp, next_node); |
1502 | 872 pos2= av_gen_search(s, -2, dummy.pos, next_node[0]->pos , next_node[1]->pos, next_node[1]->pos, |
873 next_node[0]->back_ptr, next_node[1]->back_ptr, flags, &ts, nut_read_timestamp); | |
874 if(pos2>=0) | |
875 pos= pos2; | |
3139 | 876 //FIXME dir but I think it does not matter |
1502 | 877 } |
878 dummy.pos= pos; | |
2349 | 879 sp= av_tree_find(nut->syncpoints, &dummy, ff_nut_sp_pos_cmp, NULL); |
1500 | 880 |
1502 | 881 assert(sp); |
882 pos2= sp->back_ptr - 15; | |
1501 | 883 } |
884 av_log(NULL, AV_LOG_DEBUG, "SEEKTO: %"PRId64"\n", pos2); | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2700
diff
changeset
|
885 pos= find_startcode(s->pb, SYNCPOINT_STARTCODE, pos2); |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2700
diff
changeset
|
886 url_fseek(s->pb, pos, SEEK_SET); |
1500 | 887 av_log(NULL, AV_LOG_DEBUG, "SP: %"PRId64"\n", pos); |
1501 | 888 if(pos2 > pos || pos2 + 15 < pos){ |
1500 | 889 av_log(NULL, AV_LOG_ERROR, "no syncpoint at backptr pos\n"); |
890 } | |
1517
51b29c17bd1f
skip non keyframes after seeking between syncpoint and the first keyframe
michael
parents:
1516
diff
changeset
|
891 for(i=0; i<s->nb_streams; i++) |
51b29c17bd1f
skip non keyframes after seeking between syncpoint and the first keyframe
michael
parents:
1516
diff
changeset
|
892 nut->stream[i].skip_until_key_frame=1; |
51b29c17bd1f
skip non keyframes after seeking between syncpoint and the first keyframe
michael
parents:
1516
diff
changeset
|
893 |
1500 | 894 return 0; |
895 } | |
896 | |
1477 | 897 static int nut_read_close(AVFormatContext *s) |
898 { | |
899 NUTContext *nut = s->priv_data; | |
900 | |
901 av_freep(&nut->time_base); | |
902 av_freep(&nut->stream); | |
903 | |
904 return 0; | |
905 } | |
906 | |
4206 | 907 #if CONFIG_NUT_DEMUXER |
1477 | 908 AVInputFormat nut_demuxer = { |
909 "nut", | |
3424
7a0230981402
Make long_names in lavf/lavdev optional depending on CONFIG_SMALL.
diego
parents:
3377
diff
changeset
|
910 NULL_IF_CONFIG_SMALL("NUT format"), |
1477 | 911 sizeof(NUTContext), |
912 nut_probe, | |
913 nut_read_header, | |
914 nut_read_packet, | |
915 nut_read_close, | |
1500 | 916 read_seek, |
1477 | 917 .extensions = "nut", |
918 }; | |
919 #endif |