Commit Graph

394 Commits

Author SHA1 Message Date
James Almer 9b8a398930 avformat: remove FF_API_AVIOCONTEXT_WRITTEN
Signed-off-by: James Almer <jamrial@gmail.com>
2023-02-09 15:35:14 +01:00
Andreas Rheinhardt 63b3156558 avformat/aviobuf: Don't use NULL as src for memcpy
This might happen in avio_write() if size == 0
when the direct codepath is taken. It is undefined behaviour
according to the spec although it happens to work in practice.
Fixes the webm-webvtt-remux FATE-test under UBSan.

Reviewed-by: James Almer <jamrial@gmail.com>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
2022-10-04 18:01:01 +02:00
Stefano Sabatini 7cae3d8b76 lavf/avio: add avio_vprintf()
This new function makes it possible to use avio_printf() functionality from
a function taking a variable list of arguments.

Signed-off-by: Marton Balint <cus@passwd.hu>
2022-06-13 22:42:55 +02:00
Michael Niedermayer c4b130e876 avformat/aviobuf: Check buf_size in ffio_ensure_seekback()
buffer_size is an int

Fixes: signed integer overflow: 9223372036854775754 + 32767 cannot be represented in type 'long'
Fixes: 45691/clusterfuzz-testcase-minimized-ffmpeg_IO_DEMUXER_fuzzer-5263458831040512

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2022-06-09 20:46:21 +02:00
Pierre-Anthony Lemieux c8b5f2848d
avformat/aviobuf: ffio_copy_url_options
Signed-off-by: Pierre-Anthony Lemieux <pal@palemieux.com>
Signed-off-by: Zane van Iperen <zane@zanevaniperen.com>
2021-12-19 00:35:24 +10:00
Steven Liu 3f46ffe956 avformat/aviobuf: fix double free by return early on error
Because the s->buffer has been freed by av_freep in avio_closep.
It should not av_freep the buffer in label fail after avio_closep.
Then just move the av_freep before avio_closep and remove the label fail.

Reported-by: TOTE Robot <oslab@tsinghua.edu.cn>
Reviewed-by: Zhao Zhili <zhilizhao@tencent.com>
Signed-off-by: Steven Liu <liuqi05@kuaishou.com>
2021-12-16 11:02:57 +08:00
Marton Balint 8a40cfa4da avformat/aviobuf: return stored AVIO context error on avio_close
Otherwise IO errors at avio_flush() before closing may be lost.

Signed-off-by: Marton Balint <cus@passwd.hu>
2021-12-12 00:32:20 +01:00
Limin Wang 3c74ffb01a avformat/aviobuf: check if read_packet() exist before read_packet_wrapper()
without it, read_packet_wrapper() will return AVERROR(EINVAL) and avio_read
will be failed.

Signed-off-by: Limin Wang <lance.lmwang@gmail.com>
2021-12-04 08:26:30 +08:00
Jan Ekström 682bafdb12 avformat/avio{,buf}: introduce public AVIOContext::bytes_{read,written}
Such fields can be seen as generally useful in cases where the
API user is not implementing custom AVIO callbacks, but still would
like to know if data is being read or written out, such as in case
data is being read from input but no AVPacket has been received yet.
2021-10-24 13:04:39 +03:00
Jan Ekström a5622ed16f avformat/avio{,buf}: deprecate AVIOContext::written
Originally added as a private entry in commit
3f75e5116b, but its grouping with
the comment noting its private state was missed during merging of
the field from Libav (most likely due to an already existing field
in between).
2021-10-24 13:04:39 +03:00
Jan Ekström d39b58dc32 avformat/avio: privatize source of truth for AVIOContext::written
Looking at 3f75e5116b, the field
was supposed to be private, but during merging the field and the
group that had the comment about it got separated.

Thus, move the actual privately utilized state of this variable
into the private FFIOContext. Additionally, name the private field
somewhat better, so that it does not get confused with the amount
of bytes written out.
2021-10-24 13:04:26 +03:00
Jan Ekström 847fd8de7c avformat/{aviobuf,avio_internal}: add max_len argument to ff_read_string_to_bprint_overwrite
This is especially useful when reading things such as null-terminated
strings from MOV/MP4-likes, where the size of the box is known, but
not the exact size of the string.

Signed-off-by: Jan Ekström <jan.ekstrom@24i.com>
2021-10-04 17:13:21 +03:00
Jan Ekström 151f46e84d avformat/{aviobuf,avio_internal}: add ff_read_string_to_bprint_overwrite
For now, same as ff_read_line_to_bprint_overwrite, but reads until
the end of a null-terminated string.

Signed-off-by: Jan Ekström <jan.ekstrom@24i.com>
2021-10-04 17:13:21 +03:00
Jan Ekström 94f227bac1 avformat/aviobuf: add a full string reading mode to read_line_to_bprint
Additionally:
* rename it to read_string_to_bprint
* split most of ff_read_line_to_bprint_overwrite into an internal
  function which can then be utilized to implement other
  functionality without duplicating code.

Signed-off-by: Jan Ekström <jan.ekstrom@24i.com>
2021-10-04 17:13:21 +03:00
Andreas Rheinhardt a46e78d5b7 avformat/aviobuf: Extend ffio_fill to 64bits
Reviewed-by: Paul B Mahol <onemda@gmail.com>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
2021-09-24 00:14:25 +02:00
Andreas Rheinhardt 52bd399972 avformat/aviobuf: Use ffio_fill for padding
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
2021-08-25 23:01:54 +02:00
Andreas Rheinhardt f5f984c9c3 avformat/aviobuf: Avoid allocation when using dynamic buffer
This can be achieved by allocating the AVIOContext and
the dynamic buffer's opaque and internal write buffer together.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
2021-08-25 23:01:54 +02:00
Andreas Rheinhardt 45bfe8b838 avformat/avio: Move internal AVIOContext fields to avio_internal.h
Currently AVIOContext's private fields are all over AVIOContext.
This commit moves them into a new structure in avio_internal.h instead.
Said structure contains the public AVIOContext as its first element
in order to avoid having to allocate a separate AVIOContextInternal
which is costly for those use cases where one just wants to access
an already existing buffer via the AVIOContext-API.
For these cases ffio_init_context() can't fail and always returned zero,
which was typically not checked. Therefore it has been made to not
return anything.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
2021-08-25 23:01:54 +02:00
Andreas Rheinhardt 530ac6aa30 avformat/aviobuf: Make ffio_set_buf_size() static
Possible since 9c3adb7ce2.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
2021-08-25 23:01:54 +02:00
Andreas Rheinhardt 19093100fd avformat/utils: Move ffio_limit() to aviobuf
It is the more natural place for it given that it only deals with I/O;
in fact, the function already has the ffio prefix and its declaration
already is in avio_internal.h.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
2021-08-25 23:01:53 +02:00
Andreas Rheinhardt 7cfff1512c avformat/aviobuf: Avoid calling function twice due to FFMAX()
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
2021-08-25 23:01:53 +02:00
Andreas Rheinhardt 642b202567 avformat/aviobuf: Make ff_read_line_to_bprint() static
It is only used in ff_read_line_to_bprint_overwrite().

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
2021-07-29 22:02:05 +02:00
James Almer 0bf3a7361d avutil: remove deprecated AVClass.child_class_next
Signed-off-by: James Almer <jamrial@gmail.com>
2021-04-27 11:48:04 -03:00
Andreas Rheinhardt 252500a78f avformat/aviobuf: End grace period of allowing 0 from read_packet
See a606f27f4c.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
Signed-off-by: James Almer <jamrial@gmail.com>
2021-04-27 10:43:09 -03:00
Andriy Gelman 9383885c0d avformat/aviobuf: don't reduce short seek threshold
Commit 8c8e5d5286 added a way to reduce
seek time by waiting for the windowed tcp packets instead of creating a
new socket connection. It implemented this by overwriting
s->short_seek_threshold in avio_seek(). However,
s->short_seek_threshold could already be set and be higher than the
threshold set by the protocol (i.e. s->short_seek_threshold is set in
ff_configure_buffers_for_index()).

This new feature was only enabled for tls connections in
70d8077b79. As in Ticket #9148 it reduced
performance because instead of waiting to refill the AVIOContext buffers
with an existing connections, a new HTTP request was often made instead.

Fixes Ticket #9148.

Reviewed-by: Martin Storsjö <martin@martin.st>
Signed-off-by: Andriy Gelman <andriy.gelman@gmail.com>
2021-03-16 22:46:25 -04:00
Martin Storsjö 3fcfde2cea aviobuf: Increase the default SHORT_SEEK_THRESHOLD to 32 KB
The previous threshold, 4 KB, maybe was reasonable when it was set
(in 2010), but in today's settings and with typical network speeds
and data sizes, it's pretty small. 32 KB probably is a more reasonable
default now, regardless of input.

This changes the test references for two seek tests.

When using the normal seek function, which boils down to the lseek(2)
function, a seek to an out of bounds position doesn't return an error,
but that condition is only reported when doing the subsequent read
(which returns EOF). When doing more seeks by fast forwarding, the
fact that the seeked to destination is out of bounds is noticed and
reported sooner in these cases.

Signed-off-by: Martin Storsjö <martin@martin.st>
2020-11-12 14:05:43 +02:00
Michael Niedermayer 66ca6d0fe8 libavformat/aviobuf: Forward error from avio_read in ffio_read_size()
Suggested-by: Andreas Rheinhardt
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2020-11-04 23:30:53 +01:00
Marton Balint f076a5fef6 Revert "aviobuf: Discard old buffered, previously read data in ffio_read_partial"
This is unneeded after 2ca48e4666 and it breaks
ffio_ensure_seekback().

This reverts commit 53c25ee073.

Signed-off-by: Marton Balint <cus@passwd.hu>
2020-10-16 23:16:46 +02:00
Marton Balint a11cc04786 avformat/aviobuf: increase default read buffer size to 2*max_buffer_size for streamed data
This should increase the effectiveness of ffio_ensure_seekback by reducing the
number of buffer reallocations and memmoves/memcpys because even a small
seekback window requires max_buffer_size+window_size buffer space.

Signed-off-by: Marton Balint <cus@passwd.hu>
2020-10-09 21:07:18 +02:00
Marton Balint 25ced19aa3 avformat/aviobuf: fix indentation
Signed-off-by: Marton Balint <cus@passwd.hu>
2020-10-09 21:07:18 +02:00
Marton Balint 84d8815499 avformat/aviobuf: do not allocate a new buffer in ffio_ensure_seekback if not needed
Let's move unread data to the start of the old buffer instead.

Signed-off-by: Marton Balint <cus@passwd.hu>
2020-10-09 21:07:18 +02:00
Marton Balint da74a74061 avformat/aviobuf: discard part of the IO buffer in ffio_ensure_seekback if needed
Previously ffio_ensure_seekback never flushed the buffer, so successive
ffio_ensure_seekback calls were all respected. This could eventually cause
unlimited memory and CPU usage if a demuxer called ffio_ensure_seekback on all
it's read data.

Most demuxers however only rely on being able to seek back till the position of
the last ffio_ensure_seekback call, therefore we change the semantics of
ffio_ensure_seekback so that a new call can invalidate seek guarantees of the
old. In order to support some level of "nested" ffio_ensure_seekback calls, we
document that the function only invalidates the old window (and potentially
discards the already read data from the IO buffer), if the newly requested
window does not fit into the old one.

This way we limit the memory usage for ffio_ensure_seekback calls requesting
consecutive data windows.

Signed-off-by: Marton Balint <cus@passwd.hu>
2020-10-09 21:07:18 +02:00
Marton Balint a3943c4847 avformat/aviobuf: fix checks in ffio_ensure_seekback
The new buf_size was detemined too conservatively, maybe because of the
off-by-one issue which was fixed recently in fill_buffer. We can safely
substract 1 more from the new buffer size, because max_buffer_size space must
only be guaranteed when we are reading the last byte of the requested window.

Comparing the new buf_size against filled did not make a lot of sense, what
makes sense is that we want to reallocate the buffer if the new buf_size is
bigger than the old, therefore the change in the check.

Signed-off-by: Marton Balint <cus@passwd.hu>
2020-10-09 21:07:18 +02:00
Marton Balint 6d972beb23 avformat/aviobuf: check if requested seekback buffer is already read
Existing code did not check if the requested seekback buffer is
already read entirely. In this case, nothing has to be done to guarantee
seekback.

Signed-off-by: Marton Balint <cus@passwd.hu>
2020-10-09 21:07:18 +02:00
Marton Balint 74c70efd12 avformat/aviobuf: write data into the IO buffer till the very end of the buffer
There was an off-by-one error when checking if the IO buffer still has enough
space till the end. One more byte can be safely written.

Signed-off-by: Marton Balint <cus@passwd.hu>
2020-10-09 21:07:18 +02:00
Andreas Rheinhardt c33e56c7a6 avformat/aviobuf: Also return truncated buffer in avio_get_dyn_buf()
Two kinds of errors can happen when working with dynamic buffers:
(Re)allocation errors or truncation errors (one has to truncate the
buffer to a size of INT_MAX because avio_close_dyn_buf() and
avio_get_dyn_buf() both return an int). Right now, avio_get_dyn_buf()
returns an empty buffer in either case. But given that
avio_get_dyn_buf() does not destroy the dynamic buffer, one can return
the buffer in case of truncation and let the user check the error flags
and decide for himself instead of hardcoding a single way to proceed
in case of truncation.

(This actually restores the behaviour from before commit
163bb9ac0af495a5cb95441bdb5c02170440d28c.)

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
2020-06-11 04:03:38 +02:00
Andreas Rheinhardt 7be9b0bb38 avformat/aviobuf: Return better error codes
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
2020-06-11 03:29:22 +02:00
Andreas Rheinhardt fa0bc627c5 avformat/aviobuf: Stop restricting dynamic buffer sizes to INT_MAX/2
This has originally been done in 568e18b15e
as a precaution against integer overflows, but it is actually easy to
support the full range of int without overflows.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
2020-06-11 03:09:56 +02:00
Andreas Rheinhardt 88d5ae068f avformat/aviobuf: Simplify dyn_buf_write() a bit
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
2020-06-11 02:01:56 +02:00
Andreas Rheinhardt 28a078eded avformat/aviobuf: Don't check for overflow after it happened
If adding two ints overflows, it doesn't matter whether the result will
be stored in an unsigned or not; and checking afterwards does not make it
retroactively defined.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
2020-06-11 01:18:54 +02:00
Anton Khirnov 2cbd544519 AVIOContext: switch to child_class_iterate() 2020-06-10 12:36:44 +02:00
Andreas Rheinhardt 781c7a6217 avformat/aviobuf, nutenc: Move ff_puv_v, ff_get_v_length to nutenc.c
and make it static again.

These functions have been moved from nutenc to aviobuf and internal.h
in f8280ff4c0 in order to use them in a
forthcoming patch in utils.c. Said patch never happened, so this commit
moves them back and makes them static, effectively reverting said
commit as well as f8280ff4c0 (which added
the ff-prefix to these functions).

Reviewed-by: Michael Niedermayer <michael@niedermayer.cc>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
2020-05-05 19:28:28 +02:00
Andreas Rheinhardt 639728f51a avformat/aviobuf: Add function to reset dynamic buffer
Resetting a dynamic buffer means to keep the AVIOContext and the
internal buffer used by the dynamic buffer. This is done in order to
save (re)allocations when one has a workflow where one opens and closes
dynamic buffers in sequence.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
2020-03-30 05:50:49 +02:00
Paul B Mahol d64cbd4fda remove CHAR_MIN/CHAR_MAX usage
It is not needed at all.
2020-03-17 22:46:36 +01:00
Andreas Rheinhardt 6e8e8431e1 avformat/aviobuf: Remove AVIOInternal and one level of indirection
In the Libav commit cae448cf, the opaque of every AVIOContext opened
by ffio_fdopen() (which is used internally by avio_open() and avio_open2())
changed: It was a simple pointer to an URLContext before, but now it was
a structure (namely AVIOInternal) containing a pointer to an URLContext
as its only member. The next commits (namely 8c0ceafb and ec4c4839) added
members to AVIOInternal to allow white-/blacklisting of protocols.

But these two commits were never merged into FFmpeg (they were only
merged as no-ops in 510046c2 and 063b26d3), because FFmpeg chose
a different way to implement this (in 93629735); and so our AVIOInternal
still has exactly one member.

This of course means that it is unnecessary to use AVIOInternal as
opaque as it is just adding a level of indirection (not only pointer
dereference, but also wrapper functions). Therefore this commit
removes AVIOInternal entirely and essentially reverts cae448cf.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
Reviewed-by: Paul B Mahol <onemda@gmail.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2020-01-30 18:47:21 +01:00
Andreas Rheinhardt 220846f74f avformat/aviobuf: Honor avio_open[2] documentation
The documentation of both avio_open() as well as avio_open2() states
that on failure, the pointer to an AVIOContext given to this function
(via a pointer to a pointer to an AVIOContext) will be set to NULL. Yet
it didn't happen upon failure of ffurl_open_whitelist() or when allocating
the internal buffer failed. This commit changes this.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2020-01-07 02:44:05 +01:00
Andreas Rheinhardt 163bb9ac0a avformat/aviobuf: Avoid allocating buffer when using dynamic buffer
Up until now, using a dynamic buffer entailed at least three
allocations: One for the AVIOContext, one for the AVIOContext's opaque
(which, among other things, contains the small write buffer), and one
for the big buffer that is independently allocated that is returned when
calling avio_close_dyn_buf().

It is possible to avoid the third allocation if one doesn't use a
packetized dynamic buffer, if all the data written so far fit into the
write buffer and if one does not require the actual (big) buffer to have
an indefinite lifetime. This is done by making avio_get_dyn_buf() return
a pointer to the data in the write buffer if nothing has been written to
the main buffer yet. The dynamic buffer will then be freed using
ffio_free_dynamic_buffer (which needed to be modified not to call
avio_close_dyn_buf() internally).

So a typical use-case like:

size = avio_close_dyn_buf(dyn_pb, &buf);
do something with buf
av_free(buf);

can be converted to:

size = avio_get_dyn_buf(dyn_pb, &buf);
do something with buf
ffio_free_dynamic_buffer(&dyn_pb);

In more complex scenarios this can simplify freeing as well, because it
is now clear that freeing always has to be performed via
ffio_free_dynamic_buffer().

Of course, in case this saves an allocation it also saves a memcpy.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
2019-11-28 15:20:36 -03:00
Marton Balint 95fa73a2b4 avformat/avio: remove 4k limit from avio_printf
We do this by switching to AVBPrint.

v2: Also set IO context error flag in case of ENOMEM.

Signed-off-by: Marton Balint <cus@passwd.hu>
2019-08-17 18:39:49 +02:00
Marton Balint a82f8f2f10 avformat/avio: add avio_print_string_array and avio_print
These functions can be used to print a variable number of strings consecutively
to the IO context. Unlike av_bprintf, no temporary buffer is necessary.

Signed-off-by: Marton Balint <cus@passwd.hu>
2019-08-17 18:39:49 +02:00
tomajsjiang 3d1506c630 lavf/avio: add a ffio_realloc_buf API for AVIO buffer realloc
Add new API ffio_realloc_buf for AVIO buffer realloc.

Signed-off-by: Zhongxing Jiang <tomajsjiang@tencent.com>
2019-08-15 09:27:11 +08:00