diff 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
line wrap: on
line diff
--- a/ffm.c	Sun Nov 16 14:26:50 2003 +0000
+++ b/ffm.c	Wed Nov 19 02:34:40 2003 +0000
@@ -51,6 +51,8 @@
     uint8_t packet[FFM_PACKET_SIZE];
 } FFMContext;
 
+static int64_t get_pts(AVFormatContext *s, offset_t pos);
+
 /* disable pts hack for testing */
 int ffm_nopts = 0;
 
@@ -64,6 +66,9 @@
     fill_size = ffm->packet_end - ffm->packet_ptr;
     memset(ffm->packet_ptr, 0, fill_size);
 
+    if (url_ftell(pb) % ffm->packet_size) 
+        av_abort();
+
     /* put header */
     put_be16(pb, PACKET_ID);
     put_be16(pb, fill_size);
@@ -202,6 +207,8 @@
     /* init packet mux */
     ffm->packet_ptr = ffm->packet;
     ffm->packet_end = ffm->packet + ffm->packet_size - FFM_HEADER_SIZE;
+    if (ffm->packet_end < ffm->packet)
+        av_abort();
     ffm->frame_offset = 0;
     ffm->pts = 0;
     ffm->first_packet = 1;
@@ -330,6 +337,8 @@
             frame_offset = get_be16(pb);
             get_buffer(pb, ffm->packet, ffm->packet_size - FFM_HEADER_SIZE);
             ffm->packet_end = ffm->packet + (ffm->packet_size - FFM_HEADER_SIZE - fill_size);
+            if (ffm->packet_end < ffm->packet)
+                av_abort();
             /* if first packet or resynchronization packet, we must
                handle it specifically */
             if (ffm->first_packet || (frame_offset & 0x8000)) {
@@ -363,6 +372,62 @@
 }
 
 
+static void adjust_write_index(AVFormatContext *s)
+{
+    FFMContext *ffm = s->priv_data;
+    ByteIOContext *pb = &s->pb;
+    int64_t pts;
+    //offset_t orig_write_index = ffm->write_index;
+    offset_t pos_min, pos_max;
+    int64_t pts_start;
+    offset_t ptr = url_ftell(pb);
+
+
+    pos_min = 0;
+    pos_max = ffm->file_size - 2 * FFM_PACKET_SIZE;
+
+    pts_start = get_pts(s, pos_min);
+
+    pts = get_pts(s, pos_max);
+
+    if (pts - 100000 > pts_start) 
+        return;
+
+    ffm->write_index = FFM_PACKET_SIZE;
+
+    pts_start = get_pts(s, pos_min);
+
+    pts = get_pts(s, pos_max);
+
+    if (pts - 100000 <= pts_start) {
+        while (1) {
+            offset_t newpos;
+            int64_t newpts;
+
+            newpos = ((pos_max + pos_min) / (2 * FFM_PACKET_SIZE)) * FFM_PACKET_SIZE;
+
+            if (newpos == pos_min)
+                break;
+
+            newpts = get_pts(s, newpos);
+
+            if (newpts - 100000 <= pts) {
+                pos_max = newpos;
+                pts = newpts;
+            } else {
+                pos_min = newpos;
+            }
+        }
+        ffm->write_index += pos_max;
+    }
+
+    //printf("Adjusted write index from %lld to %lld: pts=%0.6f\n", orig_write_index, ffm->write_index, pts / 1000000.);
+    //printf("pts range %0.6f - %0.6f\n", get_pts(s, 0) / 1000000. , get_pts(s, ffm->file_size - 2 * FFM_PACKET_SIZE) / 1000000. );
+
+    url_fseek(pb, ptr, SEEK_SET);
+}
+
+
 static int ffm_read_header(AVFormatContext *s, AVFormatParameters *ap)
 {
     FFMContext *ffm = s->priv_data;
@@ -384,6 +449,7 @@
     /* get also filesize */
     if (!url_is_streamed(pb)) {
         ffm->file_size = url_filesize(url_fileno(pb));
+        adjust_write_index(s);
     } else {
         ffm->file_size = (uint64_t_C(1) << 63) - 1;
     }