Mercurial > libavformat.hg
comparison ffm.c @ 318:54e915169d48 libavformat
Add more resilience in reading ffm files. In particular, don't assume
that the write pointer is correct. This can happen in certain failure
modes.
author | philipjsg |
---|---|
date | Wed, 19 Nov 2003 02:34:40 +0000 |
parents | a313e1080322 |
children | 3a40642dc4df |
comparison
equal
deleted
inserted
replaced
317:5cd41ae1debf | 318:54e915169d48 |
---|---|
49 int64_t pts; | 49 int64_t pts; |
50 uint8_t *packet_ptr, *packet_end; | 50 uint8_t *packet_ptr, *packet_end; |
51 uint8_t packet[FFM_PACKET_SIZE]; | 51 uint8_t packet[FFM_PACKET_SIZE]; |
52 } FFMContext; | 52 } FFMContext; |
53 | 53 |
54 static int64_t get_pts(AVFormatContext *s, offset_t pos); | |
55 | |
54 /* disable pts hack for testing */ | 56 /* disable pts hack for testing */ |
55 int ffm_nopts = 0; | 57 int ffm_nopts = 0; |
56 | 58 |
57 #ifdef CONFIG_ENCODERS | 59 #ifdef CONFIG_ENCODERS |
58 static void flush_packet(AVFormatContext *s) | 60 static void flush_packet(AVFormatContext *s) |
61 int fill_size, h; | 63 int fill_size, h; |
62 ByteIOContext *pb = &s->pb; | 64 ByteIOContext *pb = &s->pb; |
63 | 65 |
64 fill_size = ffm->packet_end - ffm->packet_ptr; | 66 fill_size = ffm->packet_end - ffm->packet_ptr; |
65 memset(ffm->packet_ptr, 0, fill_size); | 67 memset(ffm->packet_ptr, 0, fill_size); |
68 | |
69 if (url_ftell(pb) % ffm->packet_size) | |
70 av_abort(); | |
66 | 71 |
67 /* put header */ | 72 /* put header */ |
68 put_be16(pb, PACKET_ID); | 73 put_be16(pb, PACKET_ID); |
69 put_be16(pb, fill_size); | 74 put_be16(pb, fill_size); |
70 put_be64(pb, ffm->pts); | 75 put_be64(pb, ffm->pts); |
200 put_flush_packet(pb); | 205 put_flush_packet(pb); |
201 | 206 |
202 /* init packet mux */ | 207 /* init packet mux */ |
203 ffm->packet_ptr = ffm->packet; | 208 ffm->packet_ptr = ffm->packet; |
204 ffm->packet_end = ffm->packet + ffm->packet_size - FFM_HEADER_SIZE; | 209 ffm->packet_end = ffm->packet + ffm->packet_size - FFM_HEADER_SIZE; |
210 if (ffm->packet_end < ffm->packet) | |
211 av_abort(); | |
205 ffm->frame_offset = 0; | 212 ffm->frame_offset = 0; |
206 ffm->pts = 0; | 213 ffm->pts = 0; |
207 ffm->first_packet = 1; | 214 ffm->first_packet = 1; |
208 | 215 |
209 return 0; | 216 return 0; |
328 fill_size = get_be16(pb); | 335 fill_size = get_be16(pb); |
329 ffm->pts = get_be64(pb); | 336 ffm->pts = get_be64(pb); |
330 frame_offset = get_be16(pb); | 337 frame_offset = get_be16(pb); |
331 get_buffer(pb, ffm->packet, ffm->packet_size - FFM_HEADER_SIZE); | 338 get_buffer(pb, ffm->packet, ffm->packet_size - FFM_HEADER_SIZE); |
332 ffm->packet_end = ffm->packet + (ffm->packet_size - FFM_HEADER_SIZE - fill_size); | 339 ffm->packet_end = ffm->packet + (ffm->packet_size - FFM_HEADER_SIZE - fill_size); |
340 if (ffm->packet_end < ffm->packet) | |
341 av_abort(); | |
333 /* if first packet or resynchronization packet, we must | 342 /* if first packet or resynchronization packet, we must |
334 handle it specifically */ | 343 handle it specifically */ |
335 if (ffm->first_packet || (frame_offset & 0x8000)) { | 344 if (ffm->first_packet || (frame_offset & 0x8000)) { |
336 if (!frame_offset) { | 345 if (!frame_offset) { |
337 /* This packet has no frame headers in it */ | 346 /* This packet has no frame headers in it */ |
361 } | 370 } |
362 return size1 - size; | 371 return size1 - size; |
363 } | 372 } |
364 | 373 |
365 | 374 |
375 static void adjust_write_index(AVFormatContext *s) | |
376 { | |
377 FFMContext *ffm = s->priv_data; | |
378 ByteIOContext *pb = &s->pb; | |
379 int64_t pts; | |
380 //offset_t orig_write_index = ffm->write_index; | |
381 offset_t pos_min, pos_max; | |
382 int64_t pts_start; | |
383 offset_t ptr = url_ftell(pb); | |
384 | |
385 | |
386 pos_min = 0; | |
387 pos_max = ffm->file_size - 2 * FFM_PACKET_SIZE; | |
388 | |
389 pts_start = get_pts(s, pos_min); | |
390 | |
391 pts = get_pts(s, pos_max); | |
392 | |
393 if (pts - 100000 > pts_start) | |
394 return; | |
395 | |
396 ffm->write_index = FFM_PACKET_SIZE; | |
397 | |
398 pts_start = get_pts(s, pos_min); | |
399 | |
400 pts = get_pts(s, pos_max); | |
401 | |
402 if (pts - 100000 <= pts_start) { | |
403 while (1) { | |
404 offset_t newpos; | |
405 int64_t newpts; | |
406 | |
407 newpos = ((pos_max + pos_min) / (2 * FFM_PACKET_SIZE)) * FFM_PACKET_SIZE; | |
408 | |
409 if (newpos == pos_min) | |
410 break; | |
411 | |
412 newpts = get_pts(s, newpos); | |
413 | |
414 if (newpts - 100000 <= pts) { | |
415 pos_max = newpos; | |
416 pts = newpts; | |
417 } else { | |
418 pos_min = newpos; | |
419 } | |
420 } | |
421 ffm->write_index += pos_max; | |
422 } | |
423 | |
424 //printf("Adjusted write index from %lld to %lld: pts=%0.6f\n", orig_write_index, ffm->write_index, pts / 1000000.); | |
425 //printf("pts range %0.6f - %0.6f\n", get_pts(s, 0) / 1000000. , get_pts(s, ffm->file_size - 2 * FFM_PACKET_SIZE) / 1000000. ); | |
426 | |
427 url_fseek(pb, ptr, SEEK_SET); | |
428 } | |
429 | |
430 | |
366 static int ffm_read_header(AVFormatContext *s, AVFormatParameters *ap) | 431 static int ffm_read_header(AVFormatContext *s, AVFormatParameters *ap) |
367 { | 432 { |
368 FFMContext *ffm = s->priv_data; | 433 FFMContext *ffm = s->priv_data; |
369 AVStream *st; | 434 AVStream *st; |
370 FFMStream *fst; | 435 FFMStream *fst; |
382 goto fail; | 447 goto fail; |
383 ffm->write_index = get_be64(pb); | 448 ffm->write_index = get_be64(pb); |
384 /* get also filesize */ | 449 /* get also filesize */ |
385 if (!url_is_streamed(pb)) { | 450 if (!url_is_streamed(pb)) { |
386 ffm->file_size = url_filesize(url_fileno(pb)); | 451 ffm->file_size = url_filesize(url_fileno(pb)); |
452 adjust_write_index(s); | |
387 } else { | 453 } else { |
388 ffm->file_size = (uint64_t_C(1) << 63) - 1; | 454 ffm->file_size = (uint64_t_C(1) << 63) - 1; |
389 } | 455 } |
390 | 456 |
391 nb_streams = get_be32(pb); | 457 nb_streams = get_be32(pb); |