2010-01-30 22:26:47 +00:00
|
|
|
/*
|
2015-04-13 07:36:54 +00:00
|
|
|
* This file is part of mpv.
|
2010-01-30 22:26:47 +00:00
|
|
|
*
|
stream: change license to LGPL
All relevant authors have agreed.
There are two exceptions, patches by authors who could not be reached.
This commit tries to remove their copyright.
a0f08fbe: messes with the seeking code corner cases. The EOF flag logic
was changed at some point, and always had a flaky history (see e.g.
347cf972 50274ca3 70411f27 5999efb9 0d5e6084 ff08d0c3 2e2f77e3 de5566f0
9554a844, all which happened after that patch, MPlayer ones without that
patch). I claim that all of the copyright the patch might have added is
gone. Except the message in stream_seek(), which this commit removes.
The other code removed/changed in stream_seek() is probably not from
that patch, but it doesn't hurt to be sure, and also makes it more
readable. (It might change the behavior so that sometimes the eof flag
is set after a seek, but it doesn't matter here.)
2aa6acd9: it looks like the seek_forward() modified by this patch was
later moved to stream.c and renamed to stream_skip_read() in a790f2133.
(Looking closer at it, it was actually modified again a bunch of times,
fixing the logic.) I rewrote it in this commit. The code ended up rather
similar, which probably could lead to doubts whether this was done
properly, but I guess the reader of this will just have to believe me. I
knew what stream_skip_read() was supposed to do (which was reinforced
when I tried to replace it on the caller side), without reading the
pre-existing code in detail. I had to "relearn" the logic how buf_pos
and bug_len work - it was actually easy to see from stream_read_char()
how to skip the data, essentially by generalizing its logic from 1 byte
to N bytes. From the old code I only "used" the fact that it's obviously
a while(len>0) look, that has to call stream_fill_buffer repeatedly to
make progress. At first I actually didn't use stream_fill_buffer_by(),
but the variant without _by, but readded it when I checked why the old
code used it (see cd7ec016e7). This has to be good enough. In the end,
it's hard to argue that this could be implemented in a way not using
such a loop.
Other than this, I could add the usual remarks about how this code was
not modularized in the past, and how stream.c contained DVD code, and
how this was later modularized, moving the copyright to other files, and
so on. Also, if someone wrote a stream module, and was not asked about
LGPL relicensing, we don't consider the entry in stream_list[]
copyrightable.
2017-06-19 14:07:42 +00:00
|
|
|
* mpv is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
2010-01-30 22:26:47 +00:00
|
|
|
*
|
2015-04-13 07:36:54 +00:00
|
|
|
* mpv is distributed in the hope that it will be useful,
|
2010-01-30 22:26:47 +00:00
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
stream: change license to LGPL
All relevant authors have agreed.
There are two exceptions, patches by authors who could not be reached.
This commit tries to remove their copyright.
a0f08fbe: messes with the seeking code corner cases. The EOF flag logic
was changed at some point, and always had a flaky history (see e.g.
347cf972 50274ca3 70411f27 5999efb9 0d5e6084 ff08d0c3 2e2f77e3 de5566f0
9554a844, all which happened after that patch, MPlayer ones without that
patch). I claim that all of the copyright the patch might have added is
gone. Except the message in stream_seek(), which this commit removes.
The other code removed/changed in stream_seek() is probably not from
that patch, but it doesn't hurt to be sure, and also makes it more
readable. (It might change the behavior so that sometimes the eof flag
is set after a seek, but it doesn't matter here.)
2aa6acd9: it looks like the seek_forward() modified by this patch was
later moved to stream.c and renamed to stream_skip_read() in a790f2133.
(Looking closer at it, it was actually modified again a bunch of times,
fixing the logic.) I rewrote it in this commit. The code ended up rather
similar, which probably could lead to doubts whether this was done
properly, but I guess the reader of this will just have to believe me. I
knew what stream_skip_read() was supposed to do (which was reinforced
when I tried to replace it on the caller side), without reading the
pre-existing code in detail. I had to "relearn" the logic how buf_pos
and bug_len work - it was actually easy to see from stream_read_char()
how to skip the data, essentially by generalizing its logic from 1 byte
to N bytes. From the old code I only "used" the fact that it's obviously
a while(len>0) look, that has to call stream_fill_buffer repeatedly to
make progress. At first I actually didn't use stream_fill_buffer_by(),
but the variant without _by, but readded it when I checked why the old
code used it (see cd7ec016e7). This has to be good enough. In the end,
it's hard to argue that this could be implemented in a way not using
such a loop.
Other than this, I could add the usual remarks about how this code was
not modularized in the past, and how stream.c contained DVD code, and
how this was later modularized, moving the copyright to other files, and
so on. Also, if someone wrote a stream module, and was not asked about
LGPL relicensing, we don't consider the entry in stream_list[]
copyrightable.
2017-06-19 14:07:42 +00:00
|
|
|
* GNU Lesser General Public License for more details.
|
2010-01-30 22:26:47 +00:00
|
|
|
*
|
stream: change license to LGPL
All relevant authors have agreed.
There are two exceptions, patches by authors who could not be reached.
This commit tries to remove their copyright.
a0f08fbe: messes with the seeking code corner cases. The EOF flag logic
was changed at some point, and always had a flaky history (see e.g.
347cf972 50274ca3 70411f27 5999efb9 0d5e6084 ff08d0c3 2e2f77e3 de5566f0
9554a844, all which happened after that patch, MPlayer ones without that
patch). I claim that all of the copyright the patch might have added is
gone. Except the message in stream_seek(), which this commit removes.
The other code removed/changed in stream_seek() is probably not from
that patch, but it doesn't hurt to be sure, and also makes it more
readable. (It might change the behavior so that sometimes the eof flag
is set after a seek, but it doesn't matter here.)
2aa6acd9: it looks like the seek_forward() modified by this patch was
later moved to stream.c and renamed to stream_skip_read() in a790f2133.
(Looking closer at it, it was actually modified again a bunch of times,
fixing the logic.) I rewrote it in this commit. The code ended up rather
similar, which probably could lead to doubts whether this was done
properly, but I guess the reader of this will just have to believe me. I
knew what stream_skip_read() was supposed to do (which was reinforced
when I tried to replace it on the caller side), without reading the
pre-existing code in detail. I had to "relearn" the logic how buf_pos
and bug_len work - it was actually easy to see from stream_read_char()
how to skip the data, essentially by generalizing its logic from 1 byte
to N bytes. From the old code I only "used" the fact that it's obviously
a while(len>0) look, that has to call stream_fill_buffer repeatedly to
make progress. At first I actually didn't use stream_fill_buffer_by(),
but the variant without _by, but readded it when I checked why the old
code used it (see cd7ec016e7). This has to be good enough. In the end,
it's hard to argue that this could be implemented in a way not using
such a loop.
Other than this, I could add the usual remarks about how this code was
not modularized in the past, and how stream.c contained DVD code, and
how this was later modularized, moving the copyright to other files, and
so on. Also, if someone wrote a stream module, and was not asked about
LGPL relicensing, we don't consider the entry in stream_list[]
copyrightable.
2017-06-19 14:07:42 +00:00
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
|
2010-01-30 22:26:47 +00:00
|
|
|
*/
|
2001-02-24 20:28:24 +00:00
|
|
|
|
2001-08-01 09:14:02 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
2015-01-21 11:11:37 +00:00
|
|
|
#include <limits.h>
|
2001-02-24 20:28:24 +00:00
|
|
|
|
2003-04-02 16:25:07 +00:00
|
|
|
#include <strings.h>
|
2011-02-10 21:25:38 +00:00
|
|
|
#include <assert.h>
|
2001-04-22 16:56:20 +00:00
|
|
|
|
lua: add an utility function for starting processes
Because 1) Lua is terrible, and 2) popen() is terrible. Unfortunately,
since Unix is also terrible, this turned out more complicated than I
hoped. As a consequence and to avoid that this code has to be maintained
forever, add a disclaimer that any function in Lua's utils module can
disappear any time. The complexity seems a bit ridiculous, especially
for a feature so far removed from actual video playback, so if it turns
out that we don't really need this function, it will be dropped again.
The motivation for this commit is the same as with 8e4fa5fc.
Note that there is an "#ifndef __GLIBC__". The GNU people are very
special people and thought it'd be convenient to actually declare
"environ", even though the POSIX people, which are also very special
people, state that no header declares this and that the user has to
declare this manually. Since the GNU people overtook the Unix world with
their very clever "embrace, extend, extinguish" strategy, but not 100%,
and trying to build without _GNU_SOURCE is hopeless; but since there
might be Unix environments which support _GNU_SOURCE features partially,
this means that in practice "environ" will be randomly declared or not
declared by system headers. Also, gcc was written by very clever people
too, and prints a warning if an external variable is declared twice (I
didn't check, but I suppose redeclaring is legal C, and not even the gcc
people are clever enough to only warn against a definitely not legal C
construct, although sometimes they do this), ...and since we at mpv hate
compiler warnings, we seek to silence them all. Adding a configure test
just for a warning seems too radical, so we special-case this against
__GLIBC__, which is hopefully not defined on other libcs, especially not
libcs which don't implement all aspects of _GNU_SOURCE, and redefine
"environ" on systems even if the headers define it already (because they
support _GNU_SOURCE - as I mentioned before, the clever GNU people wrote
software THAT portable that other libcs just gave up and implemented
parts of _GNU_SOURCE, although probably not all), which means that
compiling mpv will print a warning about "environ" being redefined, but
at least this won't happen on my system, so all is fine. However, should
someone complain about this warning, I will force whoever complained
about this warning to read this ENTIRE commit message, and if possible,
will also force them to eat a printed-out copy of the GNU Manifesto, and
if that is not enough, maybe this person could even be forced to
convince the very clever POSIX people of not doing crap like this:
having the user to manually declare somewhat central symbols - but I
doubt it's possible, because the POSIX people are too far gone and only
care about maintaining compatibility with old versions of AIX and HP-UX.
Oh, also, this code contains some subtle and obvious issues, but writing
about this is not fun.
2014-10-18 23:42:28 +00:00
|
|
|
#include "osdep/io.h"
|
2012-02-01 18:01:16 +00:00
|
|
|
|
2016-01-11 18:03:40 +00:00
|
|
|
#include "mpv_talloc.h"
|
2011-02-25 16:10:00 +00:00
|
|
|
|
2001-08-01 09:14:02 +00:00
|
|
|
#include "config.h"
|
2003-06-11 16:48:09 +00:00
|
|
|
|
2013-12-17 01:39:45 +00:00
|
|
|
#include "common/common.h"
|
2013-12-21 19:36:45 +00:00
|
|
|
#include "common/global.h"
|
2014-08-29 10:09:04 +00:00
|
|
|
#include "misc/bstr.h"
|
2018-05-17 18:58:49 +00:00
|
|
|
#include "misc/thread_tools.h"
|
2013-12-17 01:39:45 +00:00
|
|
|
#include "common/msg.h"
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
#include "options/m_config.h"
|
2014-05-19 21:27:09 +00:00
|
|
|
#include "options/options.h"
|
2013-12-17 01:02:25 +00:00
|
|
|
#include "options/path.h"
|
2010-05-30 13:39:41 +00:00
|
|
|
#include "osdep/timer.h"
|
2001-04-22 16:56:20 +00:00
|
|
|
#include "stream.h"
|
2001-02-24 20:28:24 +00:00
|
|
|
|
2013-12-17 01:02:25 +00:00
|
|
|
#include "options/m_option.h"
|
|
|
|
#include "options/m_config.h"
|
2003-04-02 16:25:07 +00:00
|
|
|
|
2007-12-02 13:22:53 +00:00
|
|
|
extern const stream_info_t stream_info_cdda;
|
|
|
|
extern const stream_info_t stream_info_dvb;
|
|
|
|
extern const stream_info_t stream_info_null;
|
2013-06-27 15:21:46 +00:00
|
|
|
extern const stream_info_t stream_info_memory;
|
2007-12-02 13:22:53 +00:00
|
|
|
extern const stream_info_t stream_info_mf;
|
2009-11-17 16:09:17 +00:00
|
|
|
extern const stream_info_t stream_info_ffmpeg;
|
2014-08-31 17:49:39 +00:00
|
|
|
extern const stream_info_t stream_info_ffmpeg_unsafe;
|
demux_lavf: add support for libavdevice
libavdevice supports various "special" video and audio inputs, such
as screen-capture or libavfilter filter graphs.
libavdevice inputs are implemented as demuxers. They don't use the
custom stream callbacks (in AVFormatContext.pb). Instead, input
parameters are passed as filename. This means the mpv stream layer has
to be disabled. Do this by adding the pseudo stream handler avdevice://,
whose only purpose is passing the filename to demux_lavf, without
actually doing anything.
Change the logic how the filename is passed to libavformat. Remove
handling of the filename from demux_open_lavf() and move it to
lavf_check_file(). (This also fixes a possible bug when skipping the
"lavf://" prefix.)
libavdevice now can be invoked by specifying demuxer and args as in:
mpv avdevice://demuxer:args
The args are passed as filename to libavformat. When using libavdevice
demuxers, their actual meaning is highly implementation specific. They
don't refer to actual filenames.
Note:
libavdevice is disabled by default. There is one problem: libavdevice
pulls in libavfilter, which in turn causes symbol clashes with mpv
internals. The problem is that libavfilter includes a mplayer filter
bridge, which is used to interface with a set of nearly unmodified
mplayer filters copied into libavfilter. This filter bridge uses the
same symbol names as mplayer/mpv's filter chain, which results in symbol
clashes at link-time.
This can be prevented by building ffmpeg with --disable-filter=mp, but
unfortunately this is not the default.
This means linking to libavdevice (which in turn forces linking with
libavfilter by default) must be disabled. We try doing this by compiling
a test file that defines one of the clashing symbols (vf_mpi_clear).
To enable libavdevice input, ffmpeg should be built with the options:
--disable-filter=mp
and mpv with:
--enable-libavdevice
Originally, I tried to auto-detect it. But the resulting complications
in configure did't seem worth the trouble.
2012-11-30 17:41:04 +00:00
|
|
|
extern const stream_info_t stream_info_avdevice;
|
2007-12-02 13:22:53 +00:00
|
|
|
extern const stream_info_t stream_info_file;
|
2020-08-16 21:46:13 +00:00
|
|
|
extern const stream_info_t stream_info_slice;
|
2020-03-08 17:43:31 +00:00
|
|
|
extern const stream_info_t stream_info_fd;
|
2014-09-25 21:54:58 +00:00
|
|
|
extern const stream_info_t stream_info_ifo_dvdnav;
|
2014-07-14 23:49:02 +00:00
|
|
|
extern const stream_info_t stream_info_dvdnav;
|
2014-09-25 22:14:58 +00:00
|
|
|
extern const stream_info_t stream_info_bdmv_dir;
|
2014-07-14 23:49:02 +00:00
|
|
|
extern const stream_info_t stream_info_bluray;
|
|
|
|
extern const stream_info_t stream_info_bdnav;
|
2013-11-19 21:26:35 +00:00
|
|
|
extern const stream_info_t stream_info_edl;
|
stream: libarchive wrapper for reading compressed archives
This works similar to the existing .rar support, but uses libarchive.
libarchive supports a number of formats, including zip and (most of)
rar.
Unfortunately, seeking does not work too well. Most libarchive readers
do not support seeking, so it's emulated by skipping data until the
target position. On backwards seek, the file is reopened. This works
fine on a local machine (and if the file is not too large), but will
perform not so well over network connection.
This is disabled by default for now. One reason is that we try
libarchive on every file we open, before trying libavformat, and I'm not
sure if I trust libarchive that much yet. Another reason is that this
breaks multivolume rar support. While libarchive supports seeking in
rar, and (probably) supports multivolume archive, our support of
libarchive (probably) does not. I don't care about multivolume rar, but
vocal users do.
2015-08-16 22:55:26 +00:00
|
|
|
extern const stream_info_t stream_info_libarchive;
|
2016-08-07 16:10:05 +00:00
|
|
|
extern const stream_info_t stream_info_cb;
|
2003-04-02 16:25:07 +00:00
|
|
|
|
2013-08-25 20:50:16 +00:00
|
|
|
static const stream_info_t *const stream_list[] = {
|
2013-07-16 11:28:28 +00:00
|
|
|
#if HAVE_CDDA
|
2013-01-24 16:43:07 +00:00
|
|
|
&stream_info_cdda,
|
2003-04-06 16:36:17 +00:00
|
|
|
#endif
|
2013-09-22 00:40:29 +00:00
|
|
|
&stream_info_ffmpeg,
|
2014-08-31 17:49:39 +00:00
|
|
|
&stream_info_ffmpeg_unsafe,
|
2013-01-24 16:43:07 +00:00
|
|
|
&stream_info_avdevice,
|
2013-07-16 11:28:28 +00:00
|
|
|
#if HAVE_DVBIN
|
2013-01-24 16:43:07 +00:00
|
|
|
&stream_info_dvb,
|
2003-08-11 00:02:46 +00:00
|
|
|
#endif
|
2014-07-14 23:49:02 +00:00
|
|
|
#if HAVE_DVDNAV
|
2014-09-25 21:54:58 +00:00
|
|
|
&stream_info_ifo_dvdnav,
|
2014-07-14 23:49:02 +00:00
|
|
|
&stream_info_dvdnav,
|
|
|
|
#endif
|
|
|
|
#if HAVE_LIBBLURAY
|
2014-09-25 22:14:58 +00:00
|
|
|
&stream_info_bdmv_dir,
|
2014-07-14 23:49:02 +00:00
|
|
|
&stream_info_bluray,
|
|
|
|
&stream_info_bdnav,
|
|
|
|
#endif
|
stream: libarchive wrapper for reading compressed archives
This works similar to the existing .rar support, but uses libarchive.
libarchive supports a number of formats, including zip and (most of)
rar.
Unfortunately, seeking does not work too well. Most libarchive readers
do not support seeking, so it's emulated by skipping data until the
target position. On backwards seek, the file is reopened. This works
fine on a local machine (and if the file is not too large), but will
perform not so well over network connection.
This is disabled by default for now. One reason is that we try
libarchive on every file we open, before trying libavformat, and I'm not
sure if I trust libarchive that much yet. Another reason is that this
breaks multivolume rar support. While libarchive supports seeking in
rar, and (probably) supports multivolume archive, our support of
libarchive (probably) does not. I don't care about multivolume rar, but
vocal users do.
2015-08-16 22:55:26 +00:00
|
|
|
#if HAVE_LIBARCHIVE
|
|
|
|
&stream_info_libarchive,
|
|
|
|
#endif
|
2013-06-27 15:21:46 +00:00
|
|
|
&stream_info_memory,
|
2013-01-24 16:43:07 +00:00
|
|
|
&stream_info_null,
|
|
|
|
&stream_info_mf,
|
2013-11-19 21:26:35 +00:00
|
|
|
&stream_info_edl,
|
2013-01-24 16:43:07 +00:00
|
|
|
&stream_info_file,
|
2020-08-16 21:46:13 +00:00
|
|
|
&stream_info_slice,
|
2020-03-08 17:43:31 +00:00
|
|
|
&stream_info_fd,
|
2016-08-07 16:10:05 +00:00
|
|
|
&stream_info_cb,
|
2013-01-24 16:43:07 +00:00
|
|
|
NULL
|
2003-04-02 16:25:07 +00:00
|
|
|
};
|
|
|
|
|
2019-11-06 20:54:41 +00:00
|
|
|
// Because of guarantees documented on STREAM_BUFFER_SIZE.
|
|
|
|
// Half the buffer is used as forward buffer, the other for seek-back.
|
|
|
|
#define STREAM_MIN_BUFFER_SIZE (STREAM_BUFFER_SIZE * 2)
|
2020-04-10 08:54:02 +00:00
|
|
|
// Sort of arbitrary; keep *2 of it comfortably within integer limits.
|
|
|
|
// Must be power of 2.
|
|
|
|
#define STREAM_MAX_BUFFER_SIZE (512 * 1024 * 1024)
|
2019-11-06 20:54:41 +00:00
|
|
|
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
struct stream_opts {
|
|
|
|
int64_t buffer_size;
|
stream, demux: redo origin policy thing
mpv has a very weak and very annoying policy that determines whether a
playlist should be used or not. For example, if you play a remote
playlist, you usually don't want it to be able to read local filesystem
entries. (Although for a media player the impact is small I guess.)
It's weak and annoying as in that it does not prevent certain cases
which could be interpreted as bad in some cases, such as allowing
playlists on the local filesystem to reference remote URLs. It probably
barely makes sense, but we just want to exclude some other "definitely
not a good idea" things, all while playlists generally just work, so
whatever.
The policy is:
- from the command line anything is played
- local playlists can reference anything except "unsafe" streams
("unsafe" means special stream inputs like libavfilter graphs)
- remote playlists can reference only remote URLs
- things like "memory://" and archives are "transparent" to this
This commit does... something. It replaces the weird stream flags with a
slightly clearer "origin" value, which is now consequently passed down
and used everywhere. It fixes some deviations from the described policy.
I wanted to force archives to reference only content within them, but
this would probably have been more complicated (or required different
abstractions), and I'm too lazy to figure it out, so archives are now
"transparent" (playlists within archives behave the same outside).
There may be a lot of bugs in this.
This is unfortunately a very noisy commit because:
- every stream open call now needs to pass the origin
- so does every demuxer open call (=> params param. gets mandatory)
- most stream were changed to provide the "origin" value
- the origin value needed to be passed along in a lot of places
- I was too lazy to split the commit
Fixes: #7274
2019-12-20 08:41:42 +00:00
|
|
|
int load_unsafe_playlists;
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#define OPT_BASE_STRUCT struct stream_opts
|
|
|
|
|
|
|
|
const struct m_sub_options stream_conf = {
|
|
|
|
.opts = (const struct m_option[]){
|
options: change option macros and all option declarations
Change all OPT_* macros such that they don't define the entire m_option
initializer, and instead expand only to a part of it, which sets certain
fields. This requires changing almost every option declaration, because
they all use these macros. A declaration now always starts with
{"name", ...
followed by designated initializers only (possibly wrapped in macros).
The OPT_* macros now initialize the .offset and .type fields only,
sometimes also .priv and others.
I think this change makes the option macros less tricky. The old code
had to stuff everything into macro arguments (and attempted to allow
setting arbitrary fields by letting the user pass designated
initializers in the vararg parts). Some of this was made messy due to
C99 and C11 not allowing 0-sized varargs with ',' removal. It's also
possible that this change is pointless, other than cosmetic preferences.
Not too happy about some things. For example, the OPT_CHOICE()
indentation I applied looks a bit ugly.
Much of this change was done with regex search&replace, but some places
required manual editing. In particular, code in "obscure" areas (which I
didn't include in compilation) might be broken now.
In wayland_common.c the author of some option declarations confused the
flags parameter with the default value (though the default value was
also properly set below). I fixed this with this change.
2020-03-14 20:28:01 +00:00
|
|
|
{"stream-buffer-size", OPT_BYTE_SIZE(buffer_size),
|
2020-04-10 08:54:02 +00:00
|
|
|
M_RANGE(STREAM_MIN_BUFFER_SIZE, STREAM_MAX_BUFFER_SIZE)},
|
options: change option macros and all option declarations
Change all OPT_* macros such that they don't define the entire m_option
initializer, and instead expand only to a part of it, which sets certain
fields. This requires changing almost every option declaration, because
they all use these macros. A declaration now always starts with
{"name", ...
followed by designated initializers only (possibly wrapped in macros).
The OPT_* macros now initialize the .offset and .type fields only,
sometimes also .priv and others.
I think this change makes the option macros less tricky. The old code
had to stuff everything into macro arguments (and attempted to allow
setting arbitrary fields by letting the user pass designated
initializers in the vararg parts). Some of this was made messy due to
C99 and C11 not allowing 0-sized varargs with ',' removal. It's also
possible that this change is pointless, other than cosmetic preferences.
Not too happy about some things. For example, the OPT_CHOICE()
indentation I applied looks a bit ugly.
Much of this change was done with regex search&replace, but some places
required manual editing. In particular, code in "obscure" areas (which I
didn't include in compilation) might be broken now.
In wayland_common.c the author of some option declarations confused the
flags parameter with the default value (though the default value was
also properly set below). I fixed this with this change.
2020-03-14 20:28:01 +00:00
|
|
|
{"load-unsafe-playlists", OPT_FLAG(load_unsafe_playlists)},
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
{0}
|
|
|
|
},
|
|
|
|
.size = sizeof(struct stream_opts),
|
|
|
|
.defaults = &(const struct stream_opts){
|
2019-11-06 20:57:31 +00:00
|
|
|
.buffer_size = 128 * 1024,
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
},
|
|
|
|
};
|
2013-05-24 15:47:01 +00:00
|
|
|
|
2017-06-13 17:50:25 +00:00
|
|
|
// return -1 if not hex char
|
|
|
|
static int hex2dec(char c)
|
2013-08-02 15:03:30 +00:00
|
|
|
{
|
|
|
|
if (c >= '0' && c <= '9')
|
|
|
|
return c - '0';
|
2017-06-13 17:50:25 +00:00
|
|
|
if (c >= 'A' && c <= 'F')
|
|
|
|
return 10 + c - 'A';
|
|
|
|
if (c >= 'a' && c <= 'f')
|
|
|
|
return 10 + c - 'a';
|
2013-08-02 15:03:30 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Replace escape sequences in an URL (or a part of an URL)
|
2017-06-13 17:50:25 +00:00
|
|
|
void mp_url_unescape_inplace(char *url)
|
2013-08-02 15:03:30 +00:00
|
|
|
{
|
2017-06-13 17:50:25 +00:00
|
|
|
for (int len = strlen(url), i = 0, o = 0; i <= len;) {
|
|
|
|
if ((url[i] != '%') || (i > len - 3)) { // %NN can't start after len-3
|
|
|
|
url[o++] = url[i++];
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
int msd = hex2dec(url[i + 1]),
|
|
|
|
lsd = hex2dec(url[i + 2]);
|
|
|
|
|
|
|
|
if (msd >= 0 && lsd >= 0) {
|
|
|
|
url[o++] = 16 * msd + lsd;
|
|
|
|
i += 3;
|
|
|
|
} else {
|
|
|
|
url[o++] = url[i++];
|
|
|
|
url[o++] = url[i++];
|
|
|
|
url[o++] = url[i++];
|
2013-08-02 15:03:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-13 17:50:25 +00:00
|
|
|
static const char hex_digits[] = "0123456789ABCDEF";
|
|
|
|
|
|
|
|
|
|
|
|
static const char url_default_ok[] = "abcdefghijklmnopqrstuvwxyz"
|
|
|
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
|
|
"0123456789"
|
|
|
|
"-._~";
|
|
|
|
|
2013-08-25 20:58:29 +00:00
|
|
|
// Escape according to http://tools.ietf.org/html/rfc3986#section-2.1
|
|
|
|
// Only unreserved characters are not escaped.
|
|
|
|
// The argument ok (if not NULL) is as follows:
|
|
|
|
// ok[0] != '~': additional characters that are not escaped
|
|
|
|
// ok[0] == '~': do not escape anything but these characters
|
|
|
|
// (can't override the unreserved characters, which are
|
2015-01-21 11:10:45 +00:00
|
|
|
// never escaped)
|
2017-06-13 17:50:25 +00:00
|
|
|
char *mp_url_escape(void *talloc_ctx, const char *url, const char *ok)
|
2013-08-25 20:58:29 +00:00
|
|
|
{
|
2017-06-13 17:50:25 +00:00
|
|
|
char *rv = talloc_size(talloc_ctx, strlen(url) * 3 + 1);
|
|
|
|
char *out = rv;
|
|
|
|
bool negate = ok && ok[0] == '~';
|
|
|
|
|
|
|
|
for (char c; (c = *url); url++) {
|
|
|
|
bool as_is = negate ? !strchr(ok + 1, c)
|
|
|
|
: (strchr(url_default_ok, c) || (ok && strchr(ok, c)));
|
|
|
|
if (as_is) {
|
|
|
|
*out++ = c;
|
2013-08-25 20:58:29 +00:00
|
|
|
} else {
|
2017-06-13 17:50:25 +00:00
|
|
|
unsigned char v = c;
|
|
|
|
*out++ = '%';
|
|
|
|
*out++ = hex_digits[v / 16];
|
|
|
|
*out++ = hex_digits[v % 16];
|
2013-08-25 20:58:29 +00:00
|
|
|
}
|
|
|
|
}
|
2017-06-13 17:50:25 +00:00
|
|
|
|
|
|
|
*out = 0;
|
|
|
|
return rv;
|
2013-08-25 20:58:29 +00:00
|
|
|
}
|
|
|
|
|
2013-08-25 20:50:16 +00:00
|
|
|
static const char *match_proto(const char *url, const char *proto)
|
|
|
|
{
|
|
|
|
int l = strlen(proto);
|
|
|
|
if (l > 0) {
|
|
|
|
if (strncasecmp(url, proto, l) == 0 && strncmp("://", url + l, 3) == 0)
|
|
|
|
return url + l + 3;
|
2013-09-04 12:04:35 +00:00
|
|
|
} else if (!mp_is_url(bstr0(url))) {
|
|
|
|
return url; // pure filenames
|
2013-08-25 20:50:16 +00:00
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
stream, demux: redo origin policy thing
mpv has a very weak and very annoying policy that determines whether a
playlist should be used or not. For example, if you play a remote
playlist, you usually don't want it to be able to read local filesystem
entries. (Although for a media player the impact is small I guess.)
It's weak and annoying as in that it does not prevent certain cases
which could be interpreted as bad in some cases, such as allowing
playlists on the local filesystem to reference remote URLs. It probably
barely makes sense, but we just want to exclude some other "definitely
not a good idea" things, all while playlists generally just work, so
whatever.
The policy is:
- from the command line anything is played
- local playlists can reference anything except "unsafe" streams
("unsafe" means special stream inputs like libavfilter graphs)
- remote playlists can reference only remote URLs
- things like "memory://" and archives are "transparent" to this
This commit does... something. It replaces the weird stream flags with a
slightly clearer "origin" value, which is now consequently passed down
and used everywhere. It fixes some deviations from the described policy.
I wanted to force archives to reference only content within them, but
this would probably have been more complicated (or required different
abstractions), and I'm too lazy to figure it out, so archives are now
"transparent" (playlists within archives behave the same outside).
There may be a lot of bugs in this.
This is unfortunately a very noisy commit because:
- every stream open call now needs to pass the origin
- so does every demuxer open call (=> params param. gets mandatory)
- most stream were changed to provide the "origin" value
- the origin value needed to be passed along in a lot of places
- I was too lazy to split the commit
Fixes: #7274
2019-12-20 08:41:42 +00:00
|
|
|
// src and new are both STREAM_ORIGIN_* values. This checks whether a stream
|
|
|
|
// with flags "new" can be opened from the "src". On success, return
|
|
|
|
// new origin, on incompatibility return 0.
|
|
|
|
static int check_origin(int src, int new)
|
|
|
|
{
|
|
|
|
switch (src) {
|
|
|
|
case STREAM_ORIGIN_DIRECT:
|
|
|
|
case STREAM_ORIGIN_UNSAFE:
|
|
|
|
// Allow anything, but constrain it to the new origin.
|
|
|
|
return new;
|
|
|
|
case STREAM_ORIGIN_FS:
|
|
|
|
// From unix FS, allow all but unsafe.
|
|
|
|
if (new == STREAM_ORIGIN_FS || new == STREAM_ORIGIN_NET)
|
|
|
|
return new;
|
|
|
|
break;
|
|
|
|
case STREAM_ORIGIN_NET:
|
|
|
|
// Allow only other network links.
|
|
|
|
if (new == STREAM_ORIGIN_NET)
|
|
|
|
return new;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
// Read len bytes from the start position, and wrap around as needed. Limit the
|
2019-11-07 13:49:41 +00:00
|
|
|
// actually read data to the size of the buffer. Return amount of copied bytes.
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
// len: max bytes to copy to dst
|
|
|
|
// pos: index into s->buffer[], e.g. s->buf_start is byte 0
|
|
|
|
// returns: bytes copied to dst (limited by len and available buffered data)
|
|
|
|
static int ring_copy(struct stream *s, void *dst, int len, int pos)
|
2018-10-02 17:57:01 +00:00
|
|
|
{
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
assert(len >= 0);
|
2018-10-02 17:57:01 +00:00
|
|
|
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
if (pos < s->buf_start || pos > s->buf_end)
|
|
|
|
return 0;
|
2018-10-02 17:57:01 +00:00
|
|
|
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
int copied = 0;
|
|
|
|
len = MPMIN(len, s->buf_end - pos);
|
2018-10-02 17:57:01 +00:00
|
|
|
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
if (len && pos <= s->buffer_mask) {
|
|
|
|
int copy = MPMIN(len, s->buffer_mask + 1 - pos);
|
|
|
|
memcpy(dst, &s->buffer[pos], copy);
|
|
|
|
copied += copy;
|
|
|
|
len -= copy;
|
|
|
|
pos += copy;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (len) {
|
|
|
|
memcpy((char *)dst + copied, &s->buffer[pos & s->buffer_mask], len);
|
|
|
|
copied += len;
|
|
|
|
}
|
|
|
|
|
|
|
|
return copied;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Resize the current stream buffer. Uses a larger size if needed to keep data.
|
|
|
|
// Does nothing if the size is adequate. Calling this with 0 ensures it uses the
|
|
|
|
// default buffer size if possible.
|
|
|
|
// The caller must check whether enough data was really allocated.
|
2020-04-10 10:29:03 +00:00
|
|
|
// keep: keep at least [buf_end-keep, buf_end] (used for assert()s only)
|
|
|
|
// new: new total size of buffer
|
|
|
|
// returns: false if buffer allocation failed, true if reallocated or size ok
|
|
|
|
static bool stream_resize_buffer(struct stream *s, int keep, int new)
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
{
|
2020-04-10 10:29:03 +00:00
|
|
|
assert(keep >= s->buf_end - s->buf_cur);
|
|
|
|
assert(keep <= new);
|
2018-10-02 17:57:01 +00:00
|
|
|
|
2020-04-10 08:54:02 +00:00
|
|
|
new = MPMAX(new, s->requested_buffer_size);
|
|
|
|
new = MPMIN(new, STREAM_MAX_BUFFER_SIZE);
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
new = mp_round_next_power_of_2(new);
|
|
|
|
|
2020-04-10 10:29:03 +00:00
|
|
|
assert(keep <= new); // can't fail (if old buffer size was valid)
|
|
|
|
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
if (new == s->buffer_mask + 1)
|
|
|
|
return true;
|
2018-10-02 17:57:01 +00:00
|
|
|
|
2020-04-10 10:29:03 +00:00
|
|
|
int old_pos = s->buf_cur - s->buf_start;
|
|
|
|
int old_used_len = s->buf_end - s->buf_start;
|
|
|
|
int skip = old_used_len > new ? old_used_len - new : 0;
|
|
|
|
|
|
|
|
MP_DBG(s, "resize stream to %d bytes, drop %d bytes\n", new, skip);
|
2018-10-02 17:57:01 +00:00
|
|
|
|
2019-11-06 20:54:41 +00:00
|
|
|
void *nbuf = ta_alloc_size(s, new);
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
if (!nbuf)
|
|
|
|
return false; // oom; tolerate it, caller needs to check if required
|
|
|
|
|
|
|
|
int new_len = 0;
|
|
|
|
if (s->buffer)
|
2020-04-10 10:29:03 +00:00
|
|
|
new_len = ring_copy(s, nbuf, new, s->buf_start + skip);
|
|
|
|
assert(new_len == old_used_len - skip);
|
|
|
|
assert(old_pos >= skip); // "keep" too low
|
|
|
|
assert(old_pos - skip <= new_len);
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
s->buf_start = 0;
|
2020-04-10 10:29:03 +00:00
|
|
|
s->buf_cur = old_pos - skip;
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
s->buf_end = new_len;
|
|
|
|
|
2019-11-06 20:54:41 +00:00
|
|
|
ta_free(s->buffer);
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
|
|
|
|
s->buffer = nbuf;
|
|
|
|
s->buffer_mask = new - 1;
|
|
|
|
|
|
|
|
return true;
|
2018-10-02 17:57:01 +00:00
|
|
|
}
|
|
|
|
|
2019-09-28 22:45:41 +00:00
|
|
|
static int stream_create_instance(const stream_info_t *sinfo,
|
|
|
|
struct stream_open_args *args,
|
|
|
|
struct stream **ret)
|
2008-04-23 03:35:36 +00:00
|
|
|
{
|
2019-09-28 22:45:41 +00:00
|
|
|
const char *url = args->url;
|
|
|
|
int flags = args->flags;
|
|
|
|
|
2019-06-19 14:48:46 +00:00
|
|
|
*ret = NULL;
|
|
|
|
|
2016-09-10 13:28:50 +00:00
|
|
|
const char *path = url;
|
2013-08-25 20:50:16 +00:00
|
|
|
|
2020-05-10 14:44:35 +00:00
|
|
|
if (flags & STREAM_LOCAL_FS_ONLY) {
|
|
|
|
if (!sinfo->local_fs)
|
|
|
|
return STREAM_NO_MATCH;
|
|
|
|
} else {
|
|
|
|
for (int n = 0; sinfo->protocols && sinfo->protocols[n]; n++) {
|
|
|
|
path = match_proto(url, sinfo->protocols[n]);
|
|
|
|
if (path)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!path)
|
|
|
|
return STREAM_NO_MATCH;
|
|
|
|
}
|
2015-02-27 18:51:14 +00:00
|
|
|
|
2018-10-02 17:57:01 +00:00
|
|
|
stream_t *s = talloc_zero(NULL, stream_t);
|
2019-09-28 22:45:41 +00:00
|
|
|
s->global = args->global;
|
stream, demux: redo origin policy thing
mpv has a very weak and very annoying policy that determines whether a
playlist should be used or not. For example, if you play a remote
playlist, you usually don't want it to be able to read local filesystem
entries. (Although for a media player the impact is small I guess.)
It's weak and annoying as in that it does not prevent certain cases
which could be interpreted as bad in some cases, such as allowing
playlists on the local filesystem to reference remote URLs. It probably
barely makes sense, but we just want to exclude some other "definitely
not a good idea" things, all while playlists generally just work, so
whatever.
The policy is:
- from the command line anything is played
- local playlists can reference anything except "unsafe" streams
("unsafe" means special stream inputs like libavfilter graphs)
- remote playlists can reference only remote URLs
- things like "memory://" and archives are "transparent" to this
This commit does... something. It replaces the weird stream flags with a
slightly clearer "origin" value, which is now consequently passed down
and used everywhere. It fixes some deviations from the described policy.
I wanted to force archives to reference only content within them, but
this would probably have been more complicated (or required different
abstractions), and I'm too lazy to figure it out, so archives are now
"transparent" (playlists within archives behave the same outside).
There may be a lot of bugs in this.
This is unfortunately a very noisy commit because:
- every stream open call now needs to pass the origin
- so does every demuxer open call (=> params param. gets mandatory)
- most stream were changed to provide the "origin" value
- the origin value needed to be passed along in a lot of places
- I was too lazy to split the commit
Fixes: #7274
2019-12-20 08:41:42 +00:00
|
|
|
struct stream_opts *opts = mp_get_config_group(s, s->global, &stream_conf);
|
2019-06-19 14:48:46 +00:00
|
|
|
if (flags & STREAM_SILENT) {
|
|
|
|
s->log = mp_null_log;
|
|
|
|
} else {
|
2019-09-28 22:45:41 +00:00
|
|
|
s->log = mp_log_new(s, s->global->log, sinfo->name);
|
2019-06-19 14:48:46 +00:00
|
|
|
}
|
2013-08-02 15:02:34 +00:00
|
|
|
s->info = sinfo;
|
2019-09-28 22:45:41 +00:00
|
|
|
s->cancel = args->cancel;
|
2013-08-02 15:02:34 +00:00
|
|
|
s->url = talloc_strdup(s, url);
|
|
|
|
s->path = talloc_strdup(s, path);
|
2014-05-24 12:06:13 +00:00
|
|
|
s->mode = flags & (STREAM_READ | STREAM_WRITE);
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
s->requested_buffer_size = opts->buffer_size;
|
2014-05-24 12:06:13 +00:00
|
|
|
|
2020-05-10 14:44:35 +00:00
|
|
|
if (flags & STREAM_LESS_NOISE)
|
|
|
|
mp_msg_set_max_level(s->log, MSGL_WARN);
|
|
|
|
|
2019-06-19 14:48:46 +00:00
|
|
|
int opt;
|
2019-09-28 22:45:41 +00:00
|
|
|
mp_read_option_raw(s->global, "access-references", &m_option_type_flag, &opt);
|
2019-06-19 14:48:46 +00:00
|
|
|
s->access_references = opt;
|
2016-12-04 22:15:31 +00:00
|
|
|
|
2015-09-30 20:51:37 +00:00
|
|
|
MP_VERBOSE(s, "Opening %s\n", url);
|
|
|
|
|
2019-06-19 14:48:46 +00:00
|
|
|
if (strlen(url) > INT_MAX / 8) {
|
|
|
|
MP_ERR(s, "URL too large.\n");
|
|
|
|
talloc_free(s);
|
|
|
|
return STREAM_ERROR;
|
|
|
|
}
|
|
|
|
|
2014-05-24 12:06:13 +00:00
|
|
|
if ((s->mode & STREAM_WRITE) && !sinfo->can_write) {
|
2017-09-28 09:53:57 +00:00
|
|
|
MP_DBG(s, "No write access implemented.\n");
|
2014-05-24 12:06:13 +00:00
|
|
|
talloc_free(s);
|
2014-05-27 20:05:22 +00:00
|
|
|
return STREAM_NO_MATCH;
|
2014-05-24 12:06:13 +00:00
|
|
|
}
|
2013-01-24 16:43:07 +00:00
|
|
|
|
stream, demux: redo origin policy thing
mpv has a very weak and very annoying policy that determines whether a
playlist should be used or not. For example, if you play a remote
playlist, you usually don't want it to be able to read local filesystem
entries. (Although for a media player the impact is small I guess.)
It's weak and annoying as in that it does not prevent certain cases
which could be interpreted as bad in some cases, such as allowing
playlists on the local filesystem to reference remote URLs. It probably
barely makes sense, but we just want to exclude some other "definitely
not a good idea" things, all while playlists generally just work, so
whatever.
The policy is:
- from the command line anything is played
- local playlists can reference anything except "unsafe" streams
("unsafe" means special stream inputs like libavfilter graphs)
- remote playlists can reference only remote URLs
- things like "memory://" and archives are "transparent" to this
This commit does... something. It replaces the weird stream flags with a
slightly clearer "origin" value, which is now consequently passed down
and used everywhere. It fixes some deviations from the described policy.
I wanted to force archives to reference only content within them, but
this would probably have been more complicated (or required different
abstractions), and I'm too lazy to figure it out, so archives are now
"transparent" (playlists within archives behave the same outside).
There may be a lot of bugs in this.
This is unfortunately a very noisy commit because:
- every stream open call now needs to pass the origin
- so does every demuxer open call (=> params param. gets mandatory)
- most stream were changed to provide the "origin" value
- the origin value needed to be passed along in a lot of places
- I was too lazy to split the commit
Fixes: #7274
2019-12-20 08:41:42 +00:00
|
|
|
s->stream_origin = flags & STREAM_ORIGIN_MASK; // pass through by default
|
|
|
|
if (opts->load_unsafe_playlists) {
|
|
|
|
s->stream_origin = STREAM_ORIGIN_DIRECT;
|
|
|
|
} else if (sinfo->stream_origin) {
|
|
|
|
s->stream_origin = check_origin(s->stream_origin, sinfo->stream_origin);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!s->stream_origin) {
|
|
|
|
talloc_free(s);
|
|
|
|
return STREAM_UNSAFE;
|
|
|
|
}
|
|
|
|
|
2019-06-19 14:48:46 +00:00
|
|
|
int r = STREAM_UNSUPPORTED;
|
|
|
|
if (sinfo->open2) {
|
2019-09-28 22:45:41 +00:00
|
|
|
r = sinfo->open2(s, args);
|
|
|
|
} else if (!args->special_arg) {
|
2019-06-19 14:48:46 +00:00
|
|
|
r = (sinfo->open)(s);
|
|
|
|
}
|
2013-08-25 20:50:16 +00:00
|
|
|
if (r != STREAM_OK) {
|
2013-01-24 16:43:07 +00:00
|
|
|
talloc_free(s);
|
2013-08-25 20:50:16 +00:00
|
|
|
return r;
|
2013-01-24 16:43:07 +00:00
|
|
|
}
|
2012-11-17 17:12:13 +00:00
|
|
|
|
2020-04-10 10:29:03 +00:00
|
|
|
if (!stream_resize_buffer(s, 0, 0)) {
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
free_stream(s);
|
|
|
|
return STREAM_ERROR;
|
|
|
|
}
|
2018-10-02 17:57:01 +00:00
|
|
|
|
2014-05-24 12:04:09 +00:00
|
|
|
assert(s->seekable == !!s->seek);
|
2013-08-22 16:21:32 +00:00
|
|
|
|
2013-01-24 16:43:07 +00:00
|
|
|
if (s->mime_type)
|
2013-12-21 19:36:45 +00:00
|
|
|
MP_VERBOSE(s, "Mime-type: '%s'\n", s->mime_type);
|
2012-12-10 00:28:20 +00:00
|
|
|
|
2017-09-28 09:53:57 +00:00
|
|
|
MP_DBG(s, "Stream opened successfully.\n");
|
2015-09-30 20:51:37 +00:00
|
|
|
|
2013-08-25 20:50:16 +00:00
|
|
|
*ret = s;
|
|
|
|
return STREAM_OK;
|
2013-08-02 15:02:34 +00:00
|
|
|
}
|
2003-04-02 16:25:07 +00:00
|
|
|
|
2019-09-28 22:45:41 +00:00
|
|
|
int stream_create_with_args(struct stream_open_args *args, struct stream **ret)
|
|
|
|
|
2008-04-23 03:35:36 +00:00
|
|
|
{
|
2019-09-28 22:45:41 +00:00
|
|
|
assert(args->url);
|
|
|
|
|
|
|
|
int r = STREAM_NO_MATCH;
|
|
|
|
*ret = NULL;
|
2013-01-24 16:43:07 +00:00
|
|
|
|
2013-08-25 20:50:16 +00:00
|
|
|
// Open stream proper
|
2019-09-28 22:45:41 +00:00
|
|
|
if (args->sinfo) {
|
|
|
|
r = stream_create_instance(args->sinfo, args, ret);
|
|
|
|
} else {
|
|
|
|
for (int i = 0; stream_list[i]; i++) {
|
|
|
|
r = stream_create_instance(stream_list[i], args, ret);
|
|
|
|
if (r == STREAM_OK)
|
|
|
|
break;
|
|
|
|
if (r == STREAM_NO_MATCH || r == STREAM_UNSUPPORTED)
|
|
|
|
continue;
|
|
|
|
if (r == STREAM_UNSAFE)
|
|
|
|
continue;
|
2013-08-25 20:50:16 +00:00
|
|
|
break;
|
2013-01-24 16:43:07 +00:00
|
|
|
}
|
2013-08-25 20:50:16 +00:00
|
|
|
}
|
|
|
|
|
2019-09-28 22:45:41 +00:00
|
|
|
if (!*ret && !(args->flags & STREAM_SILENT) && !mp_cancel_test(args->cancel))
|
|
|
|
{
|
|
|
|
struct mp_log *log = mp_log_new(NULL, args->global->log, "!stream");
|
|
|
|
|
|
|
|
if (r == STREAM_UNSAFE) {
|
|
|
|
mp_err(log, "\nRefusing to load potentially unsafe URL from a playlist.\n"
|
2020-11-16 03:06:59 +00:00
|
|
|
"Use the --load-unsafe-playlists option to load it anyway.\n\n");
|
2019-09-28 22:45:41 +00:00
|
|
|
} else if (r == STREAM_NO_MATCH || r == STREAM_UNSUPPORTED) {
|
|
|
|
mp_err(log, "No protocol handler found to open URL %s\n", args->url);
|
|
|
|
mp_err(log, "The protocol is either unsupported, or was disabled "
|
|
|
|
"at compile-time.\n");
|
|
|
|
} else {
|
|
|
|
mp_err(log, "Failed to open %s.\n", args->url);
|
|
|
|
}
|
2014-08-31 17:49:39 +00:00
|
|
|
|
2019-09-28 22:45:41 +00:00
|
|
|
talloc_free(log);
|
2013-08-25 20:50:16 +00:00
|
|
|
}
|
|
|
|
|
2019-09-28 22:45:41 +00:00
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct stream *stream_create(const char *url, int flags,
|
|
|
|
struct mp_cancel *c, struct mpv_global *global)
|
|
|
|
{
|
|
|
|
struct stream_open_args args = {
|
|
|
|
.global = global,
|
|
|
|
.cancel = c,
|
|
|
|
.flags = flags,
|
|
|
|
.url = url,
|
|
|
|
};
|
|
|
|
struct stream *s;
|
|
|
|
stream_create_with_args(&args, &s);
|
2013-08-25 20:50:16 +00:00
|
|
|
return s;
|
2003-04-02 16:25:07 +00:00
|
|
|
}
|
|
|
|
|
2013-12-21 19:36:45 +00:00
|
|
|
stream_t *open_output_stream(const char *filename, struct mpv_global *global)
|
2008-04-23 03:35:36 +00:00
|
|
|
{
|
stream, demux: redo origin policy thing
mpv has a very weak and very annoying policy that determines whether a
playlist should be used or not. For example, if you play a remote
playlist, you usually don't want it to be able to read local filesystem
entries. (Although for a media player the impact is small I guess.)
It's weak and annoying as in that it does not prevent certain cases
which could be interpreted as bad in some cases, such as allowing
playlists on the local filesystem to reference remote URLs. It probably
barely makes sense, but we just want to exclude some other "definitely
not a good idea" things, all while playlists generally just work, so
whatever.
The policy is:
- from the command line anything is played
- local playlists can reference anything except "unsafe" streams
("unsafe" means special stream inputs like libavfilter graphs)
- remote playlists can reference only remote URLs
- things like "memory://" and archives are "transparent" to this
This commit does... something. It replaces the weird stream flags with a
slightly clearer "origin" value, which is now consequently passed down
and used everywhere. It fixes some deviations from the described policy.
I wanted to force archives to reference only content within them, but
this would probably have been more complicated (or required different
abstractions), and I'm too lazy to figure it out, so archives are now
"transparent" (playlists within archives behave the same outside).
There may be a lot of bugs in this.
This is unfortunately a very noisy commit because:
- every stream open call now needs to pass the origin
- so does every demuxer open call (=> params param. gets mandatory)
- most stream were changed to provide the "origin" value
- the origin value needed to be passed along in a lot of places
- I was too lazy to split the commit
Fixes: #7274
2019-12-20 08:41:42 +00:00
|
|
|
return stream_create(filename, STREAM_ORIGIN_DIRECT | STREAM_WRITE,
|
|
|
|
NULL, global);
|
2006-12-18 20:56:24 +00:00
|
|
|
}
|
|
|
|
|
cache: make the stream cache a proper stream that wraps other streams
Before this commit, the cache was franken-hacked on top of the stream
API. You had to use special functions (like cache_stream_fill_buffer()
instead of stream_fill_buffer()), which would access the stream in a
cached manner.
The whole idea about the previous design was that the cache runs in a
thread or in a forked process, while the cache awa functions made sure
the stream instance looked consistent to the user. If you used the
normal functions instead of the special ones while the cache was
running, you were out of luck.
Make it a bit more reasonable by turning the cache into a stream on its
own. This makes it behave exactly like a normal stream. The stream
callbacks call into the original (uncached) stream to do work. No
special cache functions or redirections are needed. The only different
thing about cache streams is that they are created by special functions,
instead of being part of the auto_open_streams[] array.
To make things simpler, remove the threading implementation, which was
messed into the code. The threading code could perhaps be kept, but I
don't really want to have to worry about this special case. A proper
threaded implementation will be added later.
Remove the cache enabling code from stream_radio.c. Since enabling the
cache involves replacing the old stream with a new one, the code as-is
can't be kept. It would be easily possible to enable the cache by
requesting a cache size (which is also much simpler). But nobody uses
stream_radio.c and I can't even test this thing, and the cache is
probably not really important for it either.
2013-05-24 16:49:09 +00:00
|
|
|
// Read function bypassing the local stream buffer. This will not write into
|
|
|
|
// s->buffer, but into buf[0..len] instead.
|
2015-02-06 20:15:21 +00:00
|
|
|
// Returns 0 on error or EOF, and length of bytes read on success.
|
cache: make the stream cache a proper stream that wraps other streams
Before this commit, the cache was franken-hacked on top of the stream
API. You had to use special functions (like cache_stream_fill_buffer()
instead of stream_fill_buffer()), which would access the stream in a
cached manner.
The whole idea about the previous design was that the cache runs in a
thread or in a forked process, while the cache awa functions made sure
the stream instance looked consistent to the user. If you used the
normal functions instead of the special ones while the cache was
running, you were out of luck.
Make it a bit more reasonable by turning the cache into a stream on its
own. This makes it behave exactly like a normal stream. The stream
callbacks call into the original (uncached) stream to do work. No
special cache functions or redirections are needed. The only different
thing about cache streams is that they are created by special functions,
instead of being part of the auto_open_streams[] array.
To make things simpler, remove the threading implementation, which was
messed into the code. The threading code could perhaps be kept, but I
don't really want to have to worry about this special case. A proper
threaded implementation will be added later.
Remove the cache enabling code from stream_radio.c. Since enabling the
cache involves replacing the old stream with a new one, the code as-is
can't be kept. It would be easily possible to enable the cache by
requesting a cache size (which is also much simpler). But nobody uses
stream_radio.c and I can't even test this thing, and the cache is
probably not really important for it either.
2013-05-24 16:49:09 +00:00
|
|
|
// Partial reads are possible, even if EOF is not reached.
|
2013-05-25 13:03:30 +00:00
|
|
|
static int stream_read_unbuffered(stream_t *s, void *buf, int len)
|
2010-10-27 19:04:04 +00:00
|
|
|
{
|
2018-10-02 17:57:01 +00:00
|
|
|
assert(len >= 0);
|
|
|
|
if (len <= 0)
|
|
|
|
return 0;
|
|
|
|
|
2017-01-27 08:03:14 +00:00
|
|
|
int res = 0;
|
2013-01-24 16:43:07 +00:00
|
|
|
// we will retry even if we already reached EOF previously.
|
2017-01-27 08:03:14 +00:00
|
|
|
if (s->fill_buffer && !mp_cancel_test(s->cancel))
|
|
|
|
res = s->fill_buffer(s, buf, len);
|
|
|
|
if (res <= 0) {
|
2013-01-24 16:43:07 +00:00
|
|
|
s->eof = 1;
|
|
|
|
return 0;
|
|
|
|
}
|
2020-04-10 10:23:10 +00:00
|
|
|
assert(res <= len);
|
2013-01-24 16:43:07 +00:00
|
|
|
// When reading succeeded we are obviously not at eof.
|
|
|
|
s->eof = 0;
|
2017-01-27 08:03:14 +00:00
|
|
|
s->pos += res;
|
2018-09-01 11:04:45 +00:00
|
|
|
s->total_unbuffered_read_bytes += res;
|
2017-01-27 08:03:14 +00:00
|
|
|
return res;
|
2010-10-27 19:04:04 +00:00
|
|
|
}
|
|
|
|
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
// Ask for having at most "forward" bytes ready to read in the buffer.
|
2018-10-02 17:57:01 +00:00
|
|
|
// To read everything, you may have to call this in a loop.
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
// forward: desired amount of bytes in buffer after s->cur_pos
|
2019-11-07 13:53:19 +00:00
|
|
|
// returns: progress (false on EOF or on OOM or if enough data was available)
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
static bool stream_read_more(struct stream *s, int forward)
|
2013-01-24 16:43:07 +00:00
|
|
|
{
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
assert(forward >= 0);
|
|
|
|
|
|
|
|
int forward_avail = s->buf_end - s->buf_cur;
|
|
|
|
if (forward_avail >= forward)
|
2019-11-07 13:53:19 +00:00
|
|
|
return false;
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
|
|
|
|
// Avoid that many small reads will lead to many low-level read calls.
|
|
|
|
forward = MPMAX(forward, s->requested_buffer_size / 2);
|
2020-04-10 10:23:10 +00:00
|
|
|
assert(forward_avail < forward);
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
|
|
|
|
// Keep guaranteed seek-back.
|
|
|
|
int buf_old = MPMIN(s->buf_cur - s->buf_start, s->requested_buffer_size / 2);
|
|
|
|
|
2020-04-10 10:29:03 +00:00
|
|
|
if (!stream_resize_buffer(s, buf_old + forward_avail, buf_old + forward))
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
int buf_alloc = s->buffer_mask + 1;
|
|
|
|
|
|
|
|
assert(s->buf_start <= s->buf_cur);
|
|
|
|
assert(s->buf_cur <= s->buf_end);
|
|
|
|
assert(s->buf_cur < buf_alloc * 2);
|
|
|
|
assert(s->buf_end < buf_alloc * 2);
|
|
|
|
assert(s->buf_start < buf_alloc);
|
|
|
|
|
|
|
|
// Note: read as much as possible, even if forward is much smaller. Do
|
|
|
|
// this because the stream buffer is supposed to set an approx. minimum
|
|
|
|
// read size on it.
|
2020-04-10 10:23:10 +00:00
|
|
|
int read = buf_alloc - (buf_old + forward_avail); // free buffer past end
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
|
|
|
|
int pos = s->buf_end & s->buffer_mask;
|
|
|
|
read = MPMIN(read, buf_alloc - pos);
|
|
|
|
|
|
|
|
// Note: if wrap-around happens, we need to make two calls. This may
|
|
|
|
// affect latency (e.g. waiting for new data on a socket), so do only
|
|
|
|
// 1 read call always.
|
|
|
|
read = stream_read_unbuffered(s, &s->buffer[pos], read);
|
|
|
|
|
|
|
|
s->buf_end += read;
|
|
|
|
|
|
|
|
// May have overwritten old data.
|
|
|
|
if (s->buf_end - s->buf_start >= buf_alloc) {
|
|
|
|
assert(s->buf_end >= buf_alloc);
|
|
|
|
|
|
|
|
s->buf_start = s->buf_end - buf_alloc;
|
|
|
|
|
|
|
|
assert(s->buf_start <= s->buf_cur);
|
|
|
|
assert(s->buf_cur <= s->buf_end);
|
2018-10-02 17:57:01 +00:00
|
|
|
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
if (s->buf_start >= buf_alloc) {
|
|
|
|
s->buf_start -= buf_alloc;
|
|
|
|
s->buf_cur -= buf_alloc;
|
|
|
|
s->buf_end -= buf_alloc;
|
|
|
|
}
|
2018-10-02 17:57:01 +00:00
|
|
|
}
|
|
|
|
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
// Must not have overwritten guaranteed old data.
|
|
|
|
assert(s->buf_cur - s->buf_start >= buf_old);
|
2001-02-24 20:28:24 +00:00
|
|
|
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
if (s->buf_cur < s->buf_end)
|
|
|
|
s->eof = 0;
|
|
|
|
|
|
|
|
return !!read;
|
2013-08-22 16:27:31 +00:00
|
|
|
}
|
|
|
|
|
2013-05-27 19:53:40 +00:00
|
|
|
// Read between 1..buf_size bytes of data, return how much data has been read.
|
2015-12-21 21:19:44 +00:00
|
|
|
// Return 0 on EOF, error, or if buf_size was 0.
|
2019-11-07 14:28:50 +00:00
|
|
|
int stream_read_partial(stream_t *s, void *buf, int buf_size)
|
2013-05-27 19:53:40 +00:00
|
|
|
{
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
assert(s->buf_cur <= s->buf_end);
|
2013-05-27 19:53:40 +00:00
|
|
|
assert(buf_size >= 0);
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
if (s->buf_cur == s->buf_end && buf_size > 0) {
|
|
|
|
if (buf_size > (s->buffer_mask + 1) / 2) {
|
|
|
|
// Direct read if the buffer is too small anyway.
|
|
|
|
stream_drop_buffers(s);
|
2013-05-27 19:53:40 +00:00
|
|
|
return stream_read_unbuffered(s, buf, buf_size);
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
}
|
|
|
|
stream_read_more(s, 1);
|
2013-05-27 19:53:40 +00:00
|
|
|
}
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
int res = ring_copy(s, buf, buf_size, s->buf_cur);
|
|
|
|
s->buf_cur += res;
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Slow version of stream_read_char(); called by it if the buffer is empty.
|
|
|
|
int stream_read_char_fallback(stream_t *s)
|
|
|
|
{
|
|
|
|
uint8_t c;
|
|
|
|
return stream_read_partial(s, &c, 1) ? c : -256;
|
2013-05-27 19:53:40 +00:00
|
|
|
}
|
|
|
|
|
2019-11-07 14:28:50 +00:00
|
|
|
int stream_read(stream_t *s, void *mem, int total)
|
2013-05-24 09:56:49 +00:00
|
|
|
{
|
|
|
|
int len = total;
|
|
|
|
while (len > 0) {
|
2013-05-27 19:53:40 +00:00
|
|
|
int read = stream_read_partial(s, mem, len);
|
|
|
|
if (read <= 0)
|
|
|
|
break; // EOF
|
2019-11-07 14:28:50 +00:00
|
|
|
mem = (char *)mem + read;
|
2013-05-27 19:53:40 +00:00
|
|
|
len -= read;
|
2013-05-24 09:56:49 +00:00
|
|
|
}
|
2013-07-04 15:58:48 +00:00
|
|
|
total -= len;
|
|
|
|
return total;
|
2013-05-24 09:56:49 +00:00
|
|
|
}
|
|
|
|
|
2020-07-09 10:29:22 +00:00
|
|
|
// Read ahead so that at least forward_size bytes are readable ahead. Returns
|
|
|
|
// the actual forward amount available (restricted by EOF or buffer limits).
|
|
|
|
int stream_peek(stream_t *s, int forward_size)
|
|
|
|
{
|
|
|
|
while (stream_read_more(s, forward_size)) {}
|
|
|
|
return s->buf_end - s->buf_cur;
|
|
|
|
}
|
|
|
|
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
// Like stream_read(), but do not advance the current position. This may resize
|
|
|
|
// the buffer to satisfy the read request.
|
2019-11-07 14:28:50 +00:00
|
|
|
int stream_read_peek(stream_t *s, void *buf, int buf_size)
|
2019-10-26 14:41:46 +00:00
|
|
|
{
|
2020-07-09 10:29:22 +00:00
|
|
|
stream_peek(s, buf_size);
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
return ring_copy(s, buf, buf_size, s->buf_cur);
|
2019-10-26 14:41:46 +00:00
|
|
|
}
|
|
|
|
|
2019-11-07 14:28:50 +00:00
|
|
|
int stream_write_buffer(stream_t *s, void *buf, int len)
|
2013-01-24 16:43:07 +00:00
|
|
|
{
|
|
|
|
if (!s->write_buffer)
|
|
|
|
return -1;
|
2019-09-14 10:55:06 +00:00
|
|
|
int orig_len = len;
|
|
|
|
while (len) {
|
|
|
|
int w = s->write_buffer(s, buf, len);
|
|
|
|
if (w <= 0)
|
|
|
|
return -1;
|
|
|
|
s->pos += w;
|
2019-11-07 14:28:50 +00:00
|
|
|
buf = (char *)buf + w;
|
2019-09-14 10:55:06 +00:00
|
|
|
len -= w;
|
|
|
|
}
|
|
|
|
return orig_len;
|
2006-12-18 20:56:24 +00:00
|
|
|
}
|
|
|
|
|
stream: change license to LGPL
All relevant authors have agreed.
There are two exceptions, patches by authors who could not be reached.
This commit tries to remove their copyright.
a0f08fbe: messes with the seeking code corner cases. The EOF flag logic
was changed at some point, and always had a flaky history (see e.g.
347cf972 50274ca3 70411f27 5999efb9 0d5e6084 ff08d0c3 2e2f77e3 de5566f0
9554a844, all which happened after that patch, MPlayer ones without that
patch). I claim that all of the copyright the patch might have added is
gone. Except the message in stream_seek(), which this commit removes.
The other code removed/changed in stream_seek() is probably not from
that patch, but it doesn't hurt to be sure, and also makes it more
readable. (It might change the behavior so that sometimes the eof flag
is set after a seek, but it doesn't matter here.)
2aa6acd9: it looks like the seek_forward() modified by this patch was
later moved to stream.c and renamed to stream_skip_read() in a790f2133.
(Looking closer at it, it was actually modified again a bunch of times,
fixing the logic.) I rewrote it in this commit. The code ended up rather
similar, which probably could lead to doubts whether this was done
properly, but I guess the reader of this will just have to believe me. I
knew what stream_skip_read() was supposed to do (which was reinforced
when I tried to replace it on the caller side), without reading the
pre-existing code in detail. I had to "relearn" the logic how buf_pos
and bug_len work - it was actually easy to see from stream_read_char()
how to skip the data, essentially by generalizing its logic from 1 byte
to N bytes. From the old code I only "used" the fact that it's obviously
a while(len>0) look, that has to call stream_fill_buffer repeatedly to
make progress. At first I actually didn't use stream_fill_buffer_by(),
but the variant without _by, but readded it when I checked why the old
code used it (see cd7ec016e7). This has to be good enough. In the end,
it's hard to argue that this could be implemented in a way not using
such a loop.
Other than this, I could add the usual remarks about how this code was
not modularized in the past, and how stream.c contained DVD code, and
how this was later modularized, moving the copyright to other files, and
so on. Also, if someone wrote a stream module, and was not asked about
LGPL relicensing, we don't consider the entry in stream_list[]
copyrightable.
2017-06-19 14:07:42 +00:00
|
|
|
// Drop len bytes form input, possibly reading more until all is skipped. If
|
|
|
|
// EOF or an error was encountered before all could be skipped, return false,
|
|
|
|
// otherwise return true.
|
2015-02-06 20:15:21 +00:00
|
|
|
static bool stream_skip_read(struct stream *s, int64_t len)
|
2013-08-22 16:21:32 +00:00
|
|
|
{
|
|
|
|
while (len > 0) {
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
unsigned int left = s->buf_end - s->buf_cur;
|
stream: change license to LGPL
All relevant authors have agreed.
There are two exceptions, patches by authors who could not be reached.
This commit tries to remove their copyright.
a0f08fbe: messes with the seeking code corner cases. The EOF flag logic
was changed at some point, and always had a flaky history (see e.g.
347cf972 50274ca3 70411f27 5999efb9 0d5e6084 ff08d0c3 2e2f77e3 de5566f0
9554a844, all which happened after that patch, MPlayer ones without that
patch). I claim that all of the copyright the patch might have added is
gone. Except the message in stream_seek(), which this commit removes.
The other code removed/changed in stream_seek() is probably not from
that patch, but it doesn't hurt to be sure, and also makes it more
readable. (It might change the behavior so that sometimes the eof flag
is set after a seek, but it doesn't matter here.)
2aa6acd9: it looks like the seek_forward() modified by this patch was
later moved to stream.c and renamed to stream_skip_read() in a790f2133.
(Looking closer at it, it was actually modified again a bunch of times,
fixing the logic.) I rewrote it in this commit. The code ended up rather
similar, which probably could lead to doubts whether this was done
properly, but I guess the reader of this will just have to believe me. I
knew what stream_skip_read() was supposed to do (which was reinforced
when I tried to replace it on the caller side), without reading the
pre-existing code in detail. I had to "relearn" the logic how buf_pos
and bug_len work - it was actually easy to see from stream_read_char()
how to skip the data, essentially by generalizing its logic from 1 byte
to N bytes. From the old code I only "used" the fact that it's obviously
a while(len>0) look, that has to call stream_fill_buffer repeatedly to
make progress. At first I actually didn't use stream_fill_buffer_by(),
but the variant without _by, but readded it when I checked why the old
code used it (see cd7ec016e7). This has to be good enough. In the end,
it's hard to argue that this could be implemented in a way not using
such a loop.
Other than this, I could add the usual remarks about how this code was
not modularized in the past, and how stream.c contained DVD code, and
how this was later modularized, moving the copyright to other files, and
so on. Also, if someone wrote a stream module, and was not asked about
LGPL relicensing, we don't consider the entry in stream_list[]
copyrightable.
2017-06-19 14:07:42 +00:00
|
|
|
if (!left) {
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
if (!stream_read_more(s, 1))
|
stream: change license to LGPL
All relevant authors have agreed.
There are two exceptions, patches by authors who could not be reached.
This commit tries to remove their copyright.
a0f08fbe: messes with the seeking code corner cases. The EOF flag logic
was changed at some point, and always had a flaky history (see e.g.
347cf972 50274ca3 70411f27 5999efb9 0d5e6084 ff08d0c3 2e2f77e3 de5566f0
9554a844, all which happened after that patch, MPlayer ones without that
patch). I claim that all of the copyright the patch might have added is
gone. Except the message in stream_seek(), which this commit removes.
The other code removed/changed in stream_seek() is probably not from
that patch, but it doesn't hurt to be sure, and also makes it more
readable. (It might change the behavior so that sometimes the eof flag
is set after a seek, but it doesn't matter here.)
2aa6acd9: it looks like the seek_forward() modified by this patch was
later moved to stream.c and renamed to stream_skip_read() in a790f2133.
(Looking closer at it, it was actually modified again a bunch of times,
fixing the logic.) I rewrote it in this commit. The code ended up rather
similar, which probably could lead to doubts whether this was done
properly, but I guess the reader of this will just have to believe me. I
knew what stream_skip_read() was supposed to do (which was reinforced
when I tried to replace it on the caller side), without reading the
pre-existing code in detail. I had to "relearn" the logic how buf_pos
and bug_len work - it was actually easy to see from stream_read_char()
how to skip the data, essentially by generalizing its logic from 1 byte
to N bytes. From the old code I only "used" the fact that it's obviously
a while(len>0) look, that has to call stream_fill_buffer repeatedly to
make progress. At first I actually didn't use stream_fill_buffer_by(),
but the variant without _by, but readded it when I checked why the old
code used it (see cd7ec016e7). This has to be good enough. In the end,
it's hard to argue that this could be implemented in a way not using
such a loop.
Other than this, I could add the usual remarks about how this code was
not modularized in the past, and how stream.c contained DVD code, and
how this was later modularized, moving the copyright to other files, and
so on. Also, if someone wrote a stream module, and was not asked about
LGPL relicensing, we don't consider the entry in stream_list[]
copyrightable.
2017-06-19 14:07:42 +00:00
|
|
|
return false;
|
|
|
|
continue;
|
2013-08-22 16:21:32 +00:00
|
|
|
}
|
stream: change license to LGPL
All relevant authors have agreed.
There are two exceptions, patches by authors who could not be reached.
This commit tries to remove their copyright.
a0f08fbe: messes with the seeking code corner cases. The EOF flag logic
was changed at some point, and always had a flaky history (see e.g.
347cf972 50274ca3 70411f27 5999efb9 0d5e6084 ff08d0c3 2e2f77e3 de5566f0
9554a844, all which happened after that patch, MPlayer ones without that
patch). I claim that all of the copyright the patch might have added is
gone. Except the message in stream_seek(), which this commit removes.
The other code removed/changed in stream_seek() is probably not from
that patch, but it doesn't hurt to be sure, and also makes it more
readable. (It might change the behavior so that sometimes the eof flag
is set after a seek, but it doesn't matter here.)
2aa6acd9: it looks like the seek_forward() modified by this patch was
later moved to stream.c and renamed to stream_skip_read() in a790f2133.
(Looking closer at it, it was actually modified again a bunch of times,
fixing the logic.) I rewrote it in this commit. The code ended up rather
similar, which probably could lead to doubts whether this was done
properly, but I guess the reader of this will just have to believe me. I
knew what stream_skip_read() was supposed to do (which was reinforced
when I tried to replace it on the caller side), without reading the
pre-existing code in detail. I had to "relearn" the logic how buf_pos
and bug_len work - it was actually easy to see from stream_read_char()
how to skip the data, essentially by generalizing its logic from 1 byte
to N bytes. From the old code I only "used" the fact that it's obviously
a while(len>0) look, that has to call stream_fill_buffer repeatedly to
make progress. At first I actually didn't use stream_fill_buffer_by(),
but the variant without _by, but readded it when I checked why the old
code used it (see cd7ec016e7). This has to be good enough. In the end,
it's hard to argue that this could be implemented in a way not using
such a loop.
Other than this, I could add the usual remarks about how this code was
not modularized in the past, and how stream.c contained DVD code, and
how this was later modularized, moving the copyright to other files, and
so on. Also, if someone wrote a stream module, and was not asked about
LGPL relicensing, we don't consider the entry in stream_list[]
copyrightable.
2017-06-19 14:07:42 +00:00
|
|
|
unsigned skip = MPMIN(len, left);
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
s->buf_cur += skip;
|
stream: change license to LGPL
All relevant authors have agreed.
There are two exceptions, patches by authors who could not be reached.
This commit tries to remove their copyright.
a0f08fbe: messes with the seeking code corner cases. The EOF flag logic
was changed at some point, and always had a flaky history (see e.g.
347cf972 50274ca3 70411f27 5999efb9 0d5e6084 ff08d0c3 2e2f77e3 de5566f0
9554a844, all which happened after that patch, MPlayer ones without that
patch). I claim that all of the copyright the patch might have added is
gone. Except the message in stream_seek(), which this commit removes.
The other code removed/changed in stream_seek() is probably not from
that patch, but it doesn't hurt to be sure, and also makes it more
readable. (It might change the behavior so that sometimes the eof flag
is set after a seek, but it doesn't matter here.)
2aa6acd9: it looks like the seek_forward() modified by this patch was
later moved to stream.c and renamed to stream_skip_read() in a790f2133.
(Looking closer at it, it was actually modified again a bunch of times,
fixing the logic.) I rewrote it in this commit. The code ended up rather
similar, which probably could lead to doubts whether this was done
properly, but I guess the reader of this will just have to believe me. I
knew what stream_skip_read() was supposed to do (which was reinforced
when I tried to replace it on the caller side), without reading the
pre-existing code in detail. I had to "relearn" the logic how buf_pos
and bug_len work - it was actually easy to see from stream_read_char()
how to skip the data, essentially by generalizing its logic from 1 byte
to N bytes. From the old code I only "used" the fact that it's obviously
a while(len>0) look, that has to call stream_fill_buffer repeatedly to
make progress. At first I actually didn't use stream_fill_buffer_by(),
but the variant without _by, but readded it when I checked why the old
code used it (see cd7ec016e7). This has to be good enough. In the end,
it's hard to argue that this could be implemented in a way not using
such a loop.
Other than this, I could add the usual remarks about how this code was
not modularized in the past, and how stream.c contained DVD code, and
how this was later modularized, moving the copyright to other files, and
so on. Also, if someone wrote a stream module, and was not asked about
LGPL relicensing, we don't consider the entry in stream_list[]
copyrightable.
2017-06-19 14:07:42 +00:00
|
|
|
len -= skip;
|
2013-08-22 16:21:32 +00:00
|
|
|
}
|
2015-02-06 20:15:21 +00:00
|
|
|
return true;
|
2013-08-22 16:21:32 +00:00
|
|
|
}
|
|
|
|
|
2013-12-13 23:51:00 +00:00
|
|
|
// Drop the internal buffer. Note that this will advance the stream position
|
|
|
|
// (as seen by stream_tell()), because the real stream position is ahead of the
|
|
|
|
// logical stream position by the amount of buffered but not yet read data.
|
|
|
|
void stream_drop_buffers(stream_t *s)
|
|
|
|
{
|
2014-10-07 22:58:21 +00:00
|
|
|
s->pos = stream_tell(s);
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
s->buf_start = s->buf_cur = s->buf_end = 0;
|
2013-12-13 23:51:00 +00:00
|
|
|
s->eof = 0;
|
2020-04-10 10:29:03 +00:00
|
|
|
stream_resize_buffer(s, 0, 0);
|
2013-12-13 23:51:00 +00:00
|
|
|
}
|
|
|
|
|
cache: make the stream cache a proper stream that wraps other streams
Before this commit, the cache was franken-hacked on top of the stream
API. You had to use special functions (like cache_stream_fill_buffer()
instead of stream_fill_buffer()), which would access the stream in a
cached manner.
The whole idea about the previous design was that the cache runs in a
thread or in a forked process, while the cache awa functions made sure
the stream instance looked consistent to the user. If you used the
normal functions instead of the special ones while the cache was
running, you were out of luck.
Make it a bit more reasonable by turning the cache into a stream on its
own. This makes it behave exactly like a normal stream. The stream
callbacks call into the original (uncached) stream to do work. No
special cache functions or redirections are needed. The only different
thing about cache streams is that they are created by special functions,
instead of being part of the auto_open_streams[] array.
To make things simpler, remove the threading implementation, which was
messed into the code. The threading code could perhaps be kept, but I
don't really want to have to worry about this special case. A proper
threaded implementation will be added later.
Remove the cache enabling code from stream_radio.c. Since enabling the
cache involves replacing the old stream with a new one, the code as-is
can't be kept. It would be easily possible to enable the cache by
requesting a cache size (which is also much simpler). But nobody uses
stream_radio.c and I can't even test this thing, and the cache is
probably not really important for it either.
2013-05-24 16:49:09 +00:00
|
|
|
// Seek function bypassing the local stream buffer.
|
2015-02-06 20:15:21 +00:00
|
|
|
static bool stream_seek_unbuffered(stream_t *s, int64_t newpos)
|
2010-10-27 19:04:04 +00:00
|
|
|
{
|
2013-07-07 19:04:19 +00:00
|
|
|
if (newpos != s->pos) {
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
MP_VERBOSE(s, "stream level seek from %" PRId64 " to %" PRId64 "\n",
|
|
|
|
s->pos, newpos);
|
|
|
|
|
2019-11-07 15:05:27 +00:00
|
|
|
s->total_stream_seeks++;
|
|
|
|
|
2014-05-24 12:04:09 +00:00
|
|
|
if (newpos > s->pos && !s->seekable) {
|
|
|
|
MP_ERR(s, "Cannot seek forward in this stream\n");
|
2015-02-06 20:15:21 +00:00
|
|
|
return false;
|
2013-07-07 18:49:15 +00:00
|
|
|
}
|
2014-05-24 12:04:09 +00:00
|
|
|
if (newpos < s->pos && !s->seekable) {
|
2013-12-21 19:36:45 +00:00
|
|
|
MP_ERR(s, "Cannot seek backward in linear streams!\n");
|
2015-02-06 20:15:21 +00:00
|
|
|
return false;
|
2013-07-07 18:49:15 +00:00
|
|
|
}
|
|
|
|
if (s->seek(s, newpos) <= 0) {
|
2018-10-11 04:05:09 +00:00
|
|
|
int level = mp_cancel_test(s->cancel) ? MSGL_V : MSGL_ERR;
|
2019-01-05 13:43:39 +00:00
|
|
|
MP_MSG(s, level, "Seek failed (to %lld, size %lld)\n",
|
|
|
|
(long long)newpos, (long long)stream_get_size(s));
|
2015-02-06 20:15:21 +00:00
|
|
|
return false;
|
2013-01-24 16:43:07 +00:00
|
|
|
}
|
2014-09-29 15:58:20 +00:00
|
|
|
stream_drop_buffers(s);
|
|
|
|
s->pos = newpos;
|
2013-01-24 16:43:07 +00:00
|
|
|
}
|
2015-02-06 20:15:21 +00:00
|
|
|
return true;
|
2010-10-27 19:04:04 +00:00
|
|
|
}
|
|
|
|
|
2015-02-06 20:15:21 +00:00
|
|
|
bool stream_seek(stream_t *s, int64_t pos)
|
2013-01-24 16:43:07 +00:00
|
|
|
{
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
MP_TRACE(s, "seek request from %" PRId64 " to %" PRId64 "\n",
|
|
|
|
stream_tell(s), pos);
|
2013-01-24 16:43:07 +00:00
|
|
|
|
2015-02-06 20:15:21 +00:00
|
|
|
s->eof = 0; // eof should be set only on read; seeking always clears it
|
2013-05-24 09:56:49 +00:00
|
|
|
|
|
|
|
if (pos < 0) {
|
2015-02-06 20:15:21 +00:00
|
|
|
MP_ERR(s, "Invalid seek to negative position %lld!\n", (long long)pos);
|
2013-05-24 09:56:49 +00:00
|
|
|
pos = 0;
|
|
|
|
}
|
2018-10-11 03:43:54 +00:00
|
|
|
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
if (pos <= s->pos) {
|
|
|
|
int64_t x = pos - (s->pos - (int)s->buf_end);
|
|
|
|
if (x >= (int)s->buf_start) {
|
|
|
|
s->buf_cur = x;
|
|
|
|
assert(s->buf_cur >= s->buf_start);
|
|
|
|
assert(s->buf_cur <= s->buf_end);
|
2015-02-06 20:15:21 +00:00
|
|
|
return true;
|
2013-05-24 09:56:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-06 20:15:21 +00:00
|
|
|
if (s->mode == STREAM_WRITE)
|
2015-02-06 20:32:44 +00:00
|
|
|
return s->seekable && s->seek(s, pos);
|
2015-02-06 20:15:21 +00:00
|
|
|
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
// Skip data instead of performing a seek in some cases.
|
|
|
|
if (pos >= s->pos &&
|
|
|
|
((!s->seekable && s->fast_skip) ||
|
|
|
|
pos - s->pos <= s->requested_buffer_size))
|
|
|
|
{
|
|
|
|
return stream_skip_read(s, pos - stream_tell(s));
|
2015-02-06 20:15:21 +00:00
|
|
|
}
|
|
|
|
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
return stream_seek_unbuffered(s, pos);
|
2013-05-24 09:56:49 +00:00
|
|
|
}
|
|
|
|
|
2019-11-14 11:59:14 +00:00
|
|
|
// Like stream_seek(), but strictly prefer skipping data instead of failing, if
|
|
|
|
// it's a forward-seek.
|
|
|
|
bool stream_seek_skip(stream_t *s, int64_t pos)
|
2013-05-24 09:56:49 +00:00
|
|
|
{
|
2020-02-14 15:08:54 +00:00
|
|
|
uint64_t cur_pos = stream_tell(s);
|
|
|
|
|
|
|
|
if (cur_pos == pos)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return !s->seekable && pos > cur_pos
|
|
|
|
? stream_skip_read(s, pos - cur_pos)
|
2019-11-14 11:59:14 +00:00
|
|
|
: stream_seek(s, pos);
|
2013-05-24 09:56:49 +00:00
|
|
|
}
|
2001-02-24 20:28:24 +00:00
|
|
|
|
2013-01-24 16:43:07 +00:00
|
|
|
int stream_control(stream_t *s, int cmd, void *arg)
|
|
|
|
{
|
2015-02-06 20:32:44 +00:00
|
|
|
return s->control ? s->control(s, cmd, arg) : STREAM_UNSUPPORTED;
|
2012-11-18 20:23:17 +00:00
|
|
|
}
|
|
|
|
|
2015-08-17 22:10:54 +00:00
|
|
|
// Return the current size of the stream, or a negative value if unknown.
|
|
|
|
int64_t stream_get_size(stream_t *s)
|
|
|
|
{
|
2019-11-07 14:54:34 +00:00
|
|
|
return s->get_size ? s->get_size(s) : -1;
|
2015-08-17 22:10:54 +00:00
|
|
|
}
|
|
|
|
|
2013-01-24 16:43:07 +00:00
|
|
|
void free_stream(stream_t *s)
|
|
|
|
{
|
2013-07-12 20:06:14 +00:00
|
|
|
if (!s)
|
|
|
|
return;
|
|
|
|
|
2013-01-24 16:43:07 +00:00
|
|
|
if (s->close)
|
|
|
|
s->close(s);
|
|
|
|
talloc_free(s);
|
2001-02-24 20:28:24 +00:00
|
|
|
}
|
|
|
|
|
2014-06-10 21:56:05 +00:00
|
|
|
static const char *const bom[3] = {"\xEF\xBB\xBF", "\xFF\xFE", "\xFE\xFF"};
|
2013-08-25 18:40:21 +00:00
|
|
|
|
|
|
|
// Return utf16 argument for stream_read_line
|
|
|
|
int stream_skip_bom(struct stream *s)
|
|
|
|
{
|
stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
2019-11-06 20:36:02 +00:00
|
|
|
char buf[4];
|
|
|
|
int len = stream_read_peek(s, buf, sizeof(buf));
|
|
|
|
bstr data = {buf, len};
|
2013-08-25 18:40:21 +00:00
|
|
|
for (int n = 0; n < 3; n++) {
|
|
|
|
if (bstr_startswith0(data, bom[n])) {
|
2019-11-14 11:59:14 +00:00
|
|
|
stream_seek_skip(s, stream_tell(s) + strlen(bom[n]));
|
2013-08-25 18:40:21 +00:00
|
|
|
return n;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1; // default to 8 bit codepages
|
|
|
|
}
|
|
|
|
|
2013-06-11 10:16:42 +00:00
|
|
|
// Read the rest of the stream into memory (current pos to EOF), and return it.
|
|
|
|
// talloc_ctx: used as talloc parent for the returned allocation
|
|
|
|
// max_size: must be set to >0. If the file is larger than that, it is treated
|
|
|
|
// as error. This is a minor robustness measure.
|
|
|
|
// returns: stream contents, or .start/.len set to NULL on error
|
|
|
|
// If the file was empty, but no error happened, .start will be non-NULL and
|
|
|
|
// .len will be 0.
|
|
|
|
// For convenience, the returned buffer is padded with a 0 byte. The padding
|
|
|
|
// is not included in the returned length.
|
2011-02-25 16:10:00 +00:00
|
|
|
struct bstr stream_read_complete(struct stream *s, void *talloc_ctx,
|
2013-06-11 10:16:42 +00:00
|
|
|
int max_size)
|
2011-02-25 16:10:00 +00:00
|
|
|
{
|
|
|
|
if (max_size > 1000000000)
|
|
|
|
abort();
|
|
|
|
|
|
|
|
int bufsize;
|
|
|
|
int total_read = 0;
|
2013-06-11 10:16:42 +00:00
|
|
|
int padding = 1;
|
2011-02-25 16:10:00 +00:00
|
|
|
char *buf = NULL;
|
2016-01-12 22:50:17 +00:00
|
|
|
int64_t size = stream_get_size(s) - stream_tell(s);
|
2014-05-24 12:04:09 +00:00
|
|
|
if (size > max_size)
|
2013-06-11 10:16:42 +00:00
|
|
|
return (struct bstr){NULL, 0};
|
2014-05-24 12:04:09 +00:00
|
|
|
if (size > 0)
|
|
|
|
bufsize = size + padding;
|
2011-02-25 16:10:00 +00:00
|
|
|
else
|
|
|
|
bufsize = 1000;
|
|
|
|
while (1) {
|
|
|
|
buf = talloc_realloc_size(talloc_ctx, buf, bufsize);
|
|
|
|
int readsize = stream_read(s, buf + total_read, bufsize - total_read);
|
|
|
|
total_read += readsize;
|
|
|
|
if (total_read < bufsize)
|
|
|
|
break;
|
|
|
|
if (bufsize > max_size) {
|
|
|
|
talloc_free(buf);
|
2013-06-11 10:16:42 +00:00
|
|
|
return (struct bstr){NULL, 0};
|
2011-02-25 16:10:00 +00:00
|
|
|
}
|
2019-10-31 10:24:20 +00:00
|
|
|
bufsize = MPMIN(bufsize + (bufsize >> 1), max_size + padding);
|
2011-02-25 16:10:00 +00:00
|
|
|
}
|
|
|
|
buf = talloc_realloc_size(talloc_ctx, buf, total_read + padding);
|
2013-06-11 10:16:42 +00:00
|
|
|
memset(&buf[total_read], 0, padding);
|
|
|
|
return (struct bstr){buf, total_read};
|
2011-02-25 16:10:00 +00:00
|
|
|
}
|
2013-05-03 17:52:28 +00:00
|
|
|
|
2015-03-27 12:27:40 +00:00
|
|
|
struct bstr stream_read_file(const char *filename, void *talloc_ctx,
|
|
|
|
struct mpv_global *global, int max_size)
|
|
|
|
{
|
|
|
|
struct bstr res = {0};
|
2020-05-10 14:44:35 +00:00
|
|
|
int flags = STREAM_ORIGIN_DIRECT | STREAM_READ | STREAM_LOCAL_FS_ONLY |
|
|
|
|
STREAM_LESS_NOISE;
|
|
|
|
stream_t *s = stream_create(filename, flags, NULL, global);
|
2015-03-27 12:27:40 +00:00
|
|
|
if (s) {
|
|
|
|
res = stream_read_complete(s, talloc_ctx, max_size);
|
|
|
|
free_stream(s);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2015-05-23 13:26:55 +00:00
|
|
|
char **stream_get_proto_list(void)
|
2014-06-30 10:49:01 +00:00
|
|
|
{
|
2015-05-23 13:26:55 +00:00
|
|
|
char **list = NULL;
|
|
|
|
int num = 0;
|
2014-06-30 10:49:01 +00:00
|
|
|
for (int i = 0; stream_list[i]; i++) {
|
|
|
|
const stream_info_t *stream_info = stream_list[i];
|
|
|
|
|
|
|
|
if (!stream_info->protocols)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
for (int j = 0; stream_info->protocols[j]; j++) {
|
|
|
|
if (*stream_info->protocols[j] == '\0')
|
|
|
|
continue;
|
|
|
|
|
2015-05-23 13:26:55 +00:00
|
|
|
MP_TARRAY_APPEND(NULL, list, num,
|
|
|
|
talloc_strdup(NULL, stream_info->protocols[j]));
|
2014-06-30 10:49:01 +00:00
|
|
|
}
|
|
|
|
}
|
2015-05-23 13:26:55 +00:00
|
|
|
MP_TARRAY_APPEND(NULL, list, num, NULL);
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
void stream_print_proto_list(struct mp_log *log)
|
|
|
|
{
|
|
|
|
int count = 0;
|
|
|
|
|
|
|
|
mp_info(log, "Protocols:\n\n");
|
|
|
|
char **list = stream_get_proto_list();
|
|
|
|
for (int i = 0; list[i]; i++) {
|
|
|
|
mp_info(log, " %s://\n", list[i]);
|
|
|
|
count++;
|
|
|
|
talloc_free(list[i]);
|
|
|
|
}
|
|
|
|
talloc_free(list);
|
2014-06-30 10:49:01 +00:00
|
|
|
mp_info(log, "\nTotal: %d protocols\n", count);
|
|
|
|
}
|
2016-08-07 16:10:05 +00:00
|
|
|
|
|
|
|
bool stream_has_proto(const char *proto)
|
|
|
|
{
|
|
|
|
for (int i = 0; stream_list[i]; i++) {
|
|
|
|
const stream_info_t *stream_info = stream_list[i];
|
|
|
|
|
|
|
|
for (int j = 0; stream_info->protocols && stream_info->protocols[j]; j++) {
|
|
|
|
if (strcmp(stream_info->protocols[j], proto) == 0)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|