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);