Opened 6 years ago
Last modified 6 years ago
#7592 new defect
FFmpeg download data twice
Reported by: | Adrian | Owned by: | |
---|---|---|---|
Priority: | normal | Component: | avformat |
Version: | unspecified | Keywords: | mov |
Cc: | Blocked By: | ||
Blocking: | Reproduced by developer: | no | |
Analyzed by developer: | no |
Description
In case of data muxed in a way, that video and audio packets for the same ptses are more than 1 sec distant (so when ff_configure_buffers_for_index changes size of AVIOContext buffers to 2 * biggest_distance_between_data_for_1_sec_pts) FFmpeg fetches the same data twice from the server. This is because in fill_buffer in aviobuf.c when we need data audio from pts x that we don't currently have in buffer, we drop the whole buffer and download new range. But afterward, we need video from pts x, which was in buffer already (before seek caused by audio), so we drop buffer again and seek to this position.
Attachments (2)
Change History (6)
by , 6 years ago
by , 6 years ago
./ffmpeg -v 9 -loglevel 99 -i "http://shadow.corp.vewd.com/atrzcinski/TVSDK-38215/a.mp4"
comment:1 by , 6 years ago
This is a solution I used to solve this problem:
diff --git a/third_party/ffmpeg/libavformat/avio.h b/third_party/ffmpeg/libavformat/avio.h index 75912ce6bed9..c44e1c7e9c9b 100644 --- a/third_party/ffmpeg/libavformat/avio.h +++ b/third_party/ffmpeg/libavformat/avio.h @@ -225,6 +225,7 @@ typedef struct AVIOContext { */ unsigned char *buffer; /**< Start of the buffer. */ int buffer_size; /**< Maximum buffer size */ + int time_units_in_buffer; /**< Number of time units in buffer */ unsigned char *buf_ptr; /**< Current position in the buffer */ unsigned char *buf_end; /**< End of the data, may be less than buffer+buffer_size if the read function returned diff --git a/third_party/ffmpeg/libavformat/aviobuf.c b/third_party/ffmpeg/libavformat/aviobuf.c index 5a33f82950c3..afccc61491bd 100644 --- a/third_party/ffmpeg/libavformat/aviobuf.c +++ b/third_party/ffmpeg/libavformat/aviobuf.c @@ -92,6 +92,7 @@ int ffio_init_context(AVIOContext *s, s->buffer = buffer; s->orig_buffer_size = s->buffer_size = buffer_size; + s->time_units_in_buffer = 0; s->buf_ptr = buffer; s->buf_ptr_max = buffer; s->opaque = opaque; @@ -550,9 +551,19 @@ static void fill_buffer(AVIOContext *s) { int max_buffer_size = s->max_packet_size ? s->max_packet_size : IO_BUFFER_SIZE; - uint8_t *dst = s->buf_end - s->buffer + max_buffer_size < s->buffer_size ? - s->buf_end : s->buffer; - int len = s->buffer_size - (dst - s->buffer); + int need_erase = !(s->buf_end - s->buffer + max_buffer_size < s->buffer_size); + uint8_t *dst = need_erase ? s->buffer : s->buf_end; + int len; + + if (need_erase && s->time_units_in_buffer > 1) { + const int bytes_in_time_unit = (s->buf_end - s->buffer) / s->time_units_in_buffer; + const int offset = bytes_in_time_unit * (s->time_units_in_buffer - 1); + memcpy(s->buffer, s->buffer + offset, bytes_in_time_unit); + dst = s->buf_end = s->buffer + bytes_in_time_unit; + s->buf_ptr = s->buf_ptr - s->buffer < offset ? s->buffer : s->buf_ptr - offset; + } + + len = s->buffer_size - (dst - s->buffer); /* can't fill the buffer without read_packet, just set EOF if appropriate */ if (!s->read_packet && s->buf_ptr >= s->buf_end) @@ -562,7 +573,7 @@ static void fill_buffer(AVIOContext *s) if (s->eof_reached) return; - if (s->update_checksum && dst == s->buffer) { + if (s->update_checksum && need_erase) { if (s->buf_end > s->checksum_ptr) s->checksum = s->update_checksum(s->checksum, s->checksum_ptr, s->buf_end - s->checksum_ptr); @@ -571,7 +582,7 @@ static void fill_buffer(AVIOContext *s) /* make buffer smaller in case it ended up large after probing */ if (s->read_packet && s->orig_buffer_size && s->buffer_size > s->orig_buffer_size) { - if (dst == s->buffer && s->buf_ptr != dst) { + if (need_erase && s->buf_ptr != dst) { int ret = ffio_set_buf_size(s, s->orig_buffer_size); if (ret < 0) av_log(s, AV_LOG_WARNING, "Failed to decrease buffer size\n"); diff --git a/third_party/ffmpeg/libavformat/utils.c b/third_party/ffmpeg/libavformat/utils.c index c6901174432c..3d5040025cfb 100644 --- a/third_party/ffmpeg/libavformat/utils.c +++ b/third_party/ffmpeg/libavformat/utils.c @@ -2137,6 +2137,7 @@ void ff_configure_buffers_for_index(AVFormatContext *s, int64_t time_tolerance) av_log(s, AV_LOG_VERBOSE, "Reconfiguring buffers to size %"PRId64"\n", pos_delta); ffio_set_buf_size(s->pb, pos_delta); s->pb->short_seek_threshold = FFMAX(s->pb->short_seek_threshold, pos_delta/2); + s->pb->time_units_in_buffer = 2; } if (skip < (1<<23)) {
comment:2 by , 6 years ago
Code in fill_buffer in
if (need_erase ....)
might be simplified taking into account, that buffer_size is always 0 or 2, so offset and time_unit is half if buffer_size is different than 0.
comment:3 by , 6 years ago
Keywords: | mov added |
---|
Looks like a duplicate of several other tickets.
If you really believe you may have fixed the issue please send your patch made with git format-patch
to the development mailing list.
comment:4 by , 6 years ago
What is the status of this ticket? Was patch sent to the development mailing list? Did developer reject it?
Thanks in advance.
data_order_in_file