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