|
|
|
@@ -51,6 +51,8 @@ typedef struct FFMContext { |
|
|
|
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 @@ static void flush_packet(AVFormatContext *s) |
|
|
|
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 @@ static int ffm_write_header(AVFormatContext *s) |
|
|
|
/* 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 @@ static int ffm_read_data(AVFormatContext *s, |
|
|
|
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 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) |
|
|
|
{ |
|
|
|
FFMContext *ffm = s->priv_data; |
|
|
|
@@ -384,6 +449,7 @@ static int ffm_read_header(AVFormatContext *s, AVFormatParameters *ap) |
|
|
|
/* 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; |
|
|
|
} |
|
|
|
|