Commit 91628427 authored by Philip Gladstone's avatar Philip Gladstone

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.

Originally committed as revision 2524 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent d445a7e9
...@@ -51,6 +51,8 @@ typedef struct FFMContext { ...@@ -51,6 +51,8 @@ typedef struct FFMContext {
uint8_t packet[FFM_PACKET_SIZE]; uint8_t packet[FFM_PACKET_SIZE];
} FFMContext; } FFMContext;
static int64_t get_pts(AVFormatContext *s, offset_t pos);
/* disable pts hack for testing */ /* disable pts hack for testing */
int ffm_nopts = 0; int ffm_nopts = 0;
...@@ -64,6 +66,9 @@ static void flush_packet(AVFormatContext *s) ...@@ -64,6 +66,9 @@ static void flush_packet(AVFormatContext *s)
fill_size = ffm->packet_end - ffm->packet_ptr; fill_size = ffm->packet_end - ffm->packet_ptr;
memset(ffm->packet_ptr, 0, fill_size); memset(ffm->packet_ptr, 0, fill_size);
if (url_ftell(pb) % ffm->packet_size)
av_abort();
/* put header */ /* put header */
put_be16(pb, PACKET_ID); put_be16(pb, PACKET_ID);
put_be16(pb, fill_size); put_be16(pb, fill_size);
...@@ -202,6 +207,8 @@ static int ffm_write_header(AVFormatContext *s) ...@@ -202,6 +207,8 @@ static int ffm_write_header(AVFormatContext *s)
/* init packet mux */ /* init packet mux */
ffm->packet_ptr = ffm->packet; ffm->packet_ptr = ffm->packet;
ffm->packet_end = ffm->packet + ffm->packet_size - FFM_HEADER_SIZE; ffm->packet_end = ffm->packet + ffm->packet_size - FFM_HEADER_SIZE;
if (ffm->packet_end < ffm->packet)
av_abort();
ffm->frame_offset = 0; ffm->frame_offset = 0;
ffm->pts = 0; ffm->pts = 0;
ffm->first_packet = 1; ffm->first_packet = 1;
...@@ -330,6 +337,8 @@ static int ffm_read_data(AVFormatContext *s, ...@@ -330,6 +337,8 @@ static int ffm_read_data(AVFormatContext *s,
frame_offset = get_be16(pb); frame_offset = get_be16(pb);
get_buffer(pb, ffm->packet, ffm->packet_size - FFM_HEADER_SIZE); get_buffer(pb, ffm->packet, ffm->packet_size - FFM_HEADER_SIZE);
ffm->packet_end = ffm->packet + (ffm->packet_size - FFM_HEADER_SIZE - fill_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 /* if first packet or resynchronization packet, we must
handle it specifically */ handle it specifically */
if (ffm->first_packet || (frame_offset & 0x8000)) { if (ffm->first_packet || (frame_offset & 0x8000)) {
...@@ -363,6 +372,62 @@ static int ffm_read_data(AVFormatContext *s, ...@@ -363,6 +372,62 @@ static int ffm_read_data(AVFormatContext *s,
} }
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) static int ffm_read_header(AVFormatContext *s, AVFormatParameters *ap)
{ {
FFMContext *ffm = s->priv_data; FFMContext *ffm = s->priv_data;
...@@ -384,6 +449,7 @@ static int ffm_read_header(AVFormatContext *s, AVFormatParameters *ap) ...@@ -384,6 +449,7 @@ static int ffm_read_header(AVFormatContext *s, AVFormatParameters *ap)
/* get also filesize */ /* get also filesize */
if (!url_is_streamed(pb)) { if (!url_is_streamed(pb)) {
ffm->file_size = url_filesize(url_fileno(pb)); ffm->file_size = url_filesize(url_fileno(pb));
adjust_write_index(s);
} else { } else {
ffm->file_size = (uint64_t_C(1) << 63) - 1; ffm->file_size = (uint64_t_C(1) << 63) - 1;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment