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>
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>
This makes sure no field is ever used uninitialized.
Reviewed-by: Carl Eugen Hoyos <ceffmpeg@gmail.com>
Reviewed-by: wm4 <nfxjfg@googlemail.com>
Signed-off-by: James Almer <jamrial@gmail.com>
Print a warning to let applicatios fix their use.
After a deprecation period, check with a low-level assert.
Also make the constraint explicit in the doxygen comment.
Signed-off-by: Nicolas George <george@nsup.org>
transfer_func variable passed to retry_transfer_wrapper
are h->prot->url_read and h->prot->url_write functions.
These need to return EOF or other error properly.
In case of returning >= 0, url_read/url_write is retried
until error is returned.
Signed-off-by: Daniel Kucera <daniel.kucera@gmail.com>
Main use-case is proxying avio through a foreign I/O layer and a custom
AVIO context, without losing latency and performance characteristics.
Signed-off-by: Luca Barbato <lu_zero@gentoo.org>
Merged from Libav commit 173b56218f.
Before this commit, AVIOContext is to be freed with a plain av_free(),
which prevents us from adding any deeper structure to it.
(cherry picked from commit 99684f3ae7)
Signed-off-by: James Almer <jamrial@gmail.com>
Signed integer overflow is undefined behavior.
Detected with clang and -fsanitize=signed-integer-overflow
Signed-off-by: Vitaly Buka <vitalybuka@google.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
This patch makes aviobuf work more like traditinal file IO, which is how people
think about it.
For example, in the past, aviobuf only flushed buffers until the current buffer
position, even if more data was written to it previously, and a backward seek
was used to reposition the IO context.
From now, aviobuf will keep track of the written data, so no explicit seek will
be required till the end of the buffer, or till the end of file before flushing.
This fixes at least one regression, fate-vsynth3-flv was broken if
flush_packets option was set to false, an explicit seek was removed in
4e3cc4bdd8.
Also from now on, if a forward seek in the write buffer were to cause a gap
between the already written data and the new file position, a flush will
happen.
The must_flush varable is also removed, which might have caused needless
flushes with multiple seeks whithin the write buffer. Since we know the amount
of data written to it, we will know when to flush.
Signed-off-by: Marton Balint <cus@passwd.hu>
* commit '8ea35af7620e4f73f9e8c072e1c0fac9a04ec161':
avio: add a new flag for marking streams seekable by timestamp
Merged-by: James Almer <jamrial@gmail.com>
This commit optimizes HTTP performance by reducing forward seeks, instead
favoring a read-ahead and discard on the current connection (referred to
as a short seek) for seeks that are within a TCP window's worth of data.
This improves performance because with TCP flow control, a window's worth
of data will be in the local socket buffer already or in-flight from the
sender once congestion control on the sender is fully utilizing the window.
Note: this approach doesn't attempt to differentiate from a newly opened
connection which may not be fully utilizing the window due to congestion
control vs one that is. The receiver can't get at this information, so we
assume worst case; that full window is in use (we did advertise it after all)
and that data could be in-flight
The previous behavior of closing the connection, then opening a new
with a new HTTP range value results in a massive amounts of discarded
and re-sent data when large TCP windows are used. This has been observed
on MacOS/iOS which starts with an initial window of 256KB and grows up to
1MB depending on the bandwidth-product delay.
When seeking within a window's worth of data and we close the connection,
then open a new one within the same window's worth of data, we discard
from the current offset till the end of the window. Then on the new
connection the server ends up re-sending the previous data from new
offset till the end of old window.
Example (assumes full window utilization):
TCP window size: 64KB
Position: 32KB
Forward seek position: 40KB
* (Next window)
32KB |--------------| 96KB |---------------| 160KB
*
40KB |---------------| 104KB
Re-sent amount: 96KB - 40KB = 56KB
For a real world test example, I have MP4 file of ~25MB, which ffplay
only reads ~16MB and performs 177 seeks. With current ffmpeg, this results
in 177 HTTP GETs and ~73MB worth of TCP data communication. With this
patch, ffmpeg issues 4 HTTP GETs and 3 seeks for a total of ~22MB of TCP data
communication.
To support this feature, the short seek logic in avio_seek() has been
extended to call a function to get the short seek threshold value. This
callback has been plumbed to the URLProtocol structure, which now has
infrastructure in HTTP and TCP to get the underlying receiver window size
via SO_RCVBUF. If the underlying URL and protocol don't support returning
a short seek threshold, the default s->short_seek_threshold is used
This feature has been tested on Windows 7 and MacOS/iOS. Windows support
is slightly complicated by the fact that when TCP window auto-tuning is
enabled, SO_RCVBUF doesn't report the real window size, but it does if
SO_RCVBUF was manually set (disabling auto-tuning). So we can only use
this optimization on Windows in the later case
Signed-off-by: Joel Cunningham <joel.cunningham@me.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
This commit adds the avio_get_dyn_buf function which allows accessing
the
content of a DynBuffer without destroying it.
This is required in matroskaenc for preliminary writing (correct) mkv
headers.
Context for this change is fixing regression bug #5977.
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
It is supposed to be a flag. The only currently defined value is
AVIO_SEEKABLE_NORMAL, but other ones may be added in the future.
However all the current lavf code treats this field as a bool (mainly
for historical reasons).
Change all those cases to properly check for AVIO_SEEKABLE_NORMAL.
* commit 'db7968bff4851c2be79b15b2cb2ae747424d2fca':
avio: Allow custom IO users to get labels for the output bytestream
Merged-by: Matthieu Bouron <matthieu.bouron@stupeflix.com>
This allows callers with avio write callbacks to get the bytestream
positions that correspond to keyframes, suitable for live streaming.
In the simplest form, a caller could expect that a header is written
to the bytestream during the avformat_write_header, and the data
output to the avio context during e.g. av_write_frame corresponds
exactly to the current packet passed in.
When combined with av_interleaved_write_frame, and with muxers that
do buffering (most muxers that do some sort of fragmenting or
clustering), the mapping from input data to bytestream positions
is nontrivial.
This allows callers to get directly information about what part
of the bytestream is what, without having to resort to assumptions
about the muxer behaviour.
One keyframe/fragment/block can still be split into multiple (if
they are larger than the aviocontext buffer), which would call
the callback with e.g. AVIO_DATA_MARKER_SYNC_POINT, followed by
AVIO_DATA_MARKER_UNKNOWN for the second time it is called with
the following data.
Signed-off-by: Martin Storsjö <martin@martin.st>
Since all URLContexts have the same AVOptions, such AVOptions
will be applied on the outermost context only and removed from the
dict, while they probably make sense on all contexts.
This makes sure that rw_timeout gets propagated to the innermost
URLContext (to make sure it gets passed to the tcp protocol, when
opening a http connection for instance).
Alternatively, such matching options would be kept in the dict
and only removed after the ffurl_connect call.
Signed-off-by: Martin Storsjö <martin@martin.st>
This reverts commit 9f9ed79d4c.
The hlsopts member was never set anywhere and always NULL, furthermore
the HLS demuxer needs to retrieve the proper options from the underlying
http protocol (cookies, user-agent, etc), so a dummy context won't help.
Instead, use the AVIOContext directly to access the options.
Note to maintainers: update tools
Note to maintainers: set a default whitelist for your protocol
If that makes no sense then consider to set "none" and thus require the user to specify a white-list
for sub-protocols to be opened
Note, testing and checking for missing changes is needed
Reviewed-by: Andreas Cadhalpun <andreas.cadhalpun@googlemail.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
Fixes out of array read
Fixes: 03c406ec9530e594a074ce2979f8a1f0/asan_heap-oob_7dec26_4664_37c52495b2870a2eaac65f53958e76c1.flac
Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
Previous "currently size is limited" didn't give away
much in terms of useful info.
Signed-off-by: Reynaldo H. Verdejo Pinochet <reynaldo@osg.samsung.com>
Calling ffio_ensure_seekback() if ffio_init_checksum() has been called
on the same context can lead to out of bounds memory accesses and
crashes. The reason is that ffio_ensure_seekback() does not update
checksum_ptr after reallocating the buffer, resulting in a dangling
pointer.
This effectively fixes potential crashes when opening mp3 files.
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Don't prefix them ffio_url, which is misleading, sounding too
much like the urlprotocol layer (like ffurl_*).
Signed-off-by: Martin Storsjö <martin@martin.st>
* commit '8a273a746061a112e5e35066a8fd8e146d821a62':
avio: Add an internal utility function for freeing dynamic buffers
Merged-by: Michael Niedermayer <michaelni@gmx.at>
* commit '3c18a7b18807de81566381a1bcbe9f6103c0296b':
avio: Do not consider the end-of-buffer position valid
Conflicts:
libavformat/aviobuf.c
Merged-by: Michael Niedermayer <michaelni@gmx.at>
Trigger a refill if the seek action moves the pointer
at the end of the buffer.
Before this patch the read action following the seek would trigger
the refill, while write action would write outside the buffer.
In the Libav codebase few muxers seek forward outside of what
already has been written so it is quite unlikely to experience
the problem with the default buffer size.
CC: libav-stable@libav.org
* commit 'd7f530b0d67fe3996dbfa990a47c865e0d1400a2':
aviobuf: check context before using it
See: 7441d1ec33
Merged-by: Michael Niedermayer <michaelni@gmx.at>
avio_flush() did nothing useful for read streams. Fix it to behave as
expected, and discard the currently read buffer properly.
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
It's a public function and should use the avio_ namespace
Signed-off-by: James Almer <jamrial@gmail.com>
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
C++ chokes on the definition of AVBPrint.
Including avio.h from c++ code used to work.
Fix trac ticket #3800.
Signed-off-by: Nicolas George <george@nsup.org>
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
* commit '32d05934abc7427bb90380a4c1ab20a15fd7d821':
mp3dec: decode more data from Info header
Conflicts:
libavformat/mp3dec.c
Merged-by: Michael Niedermayer <michaelni@gmx.at>
* commit 'd07b51bf0733fe58bbfa13c448775dc325463cb4':
aviobuf: Handle a NULL buffer in avio_close_dyn_buf
Merged-by: Michael Niedermayer <michaelni@gmx.at>
This simplifies proper error handling in rtsp.c/rtspdec.c. When
broadcasting over RTSP in TCP mode, the AVIOContext is closed and
recreated for each sent packet, and if the recreation fails, we might
try to close a NULL buffer when freeing things at the end.
Previously, if recreating the buffer in rtspdec.c failed, this would
crash later due to trying to close a NULL buffer.
Signed-off-by: Martin Storsjö <martin@martin.st>
When av_reallocp fails, the associated variables that keep track of
the number of elements in the array (and in some cases, the
separate number of allocated elements) need to be reset.
Not all of these might technically be needed, but it's better to
reset them if in doubt, to make sure variables don't end up
conflicting.
Signed-off-by: Martin Storsjö <martin@martin.st>
Null buffers are useful for simulating writing to a real buffer
for the sake of measuring how many bytes are written.
Signed-off-by: Martin Storsjö <martin@martin.st>