mirror of https://github.com/mpv-player/mpv
cache: use threads instead of fork()
Basically rewrite all the code supporting the cache (i.e. anything other than the ringbuffer logic). The underlying design is untouched. Note that the old cache2.c (on which this code is based) already had a threading implementation. This was mostly unused on Linux, and had some problems, such as using shared volatile variables for communication and uninterruptible timeouts, instead of using locks for synchronization. This commit does use proper locking, while still retaining the way the old cache worked. It's basically a big refactor. Simplify the code too. Since we don't need to copy stream ctrl args anymore (we're always guaranteed a shared address space now), lots of annoying code just goes away. Likewise, we don't need to care about sector sizes. The cache uses the high-level stream API to read from other streams, and sector sizes are handled transparently.
This commit is contained in:
parent
4abec2f7b2
commit
236577af09
|
@ -287,12 +287,15 @@
|
|||
Adjust the brightness of the video signal (default: 0). Not supported by
|
||||
all video output drivers.
|
||||
|
||||
--cache=<kBytes>
|
||||
Enable caching of the input stream (if not already enabled) and set the
|
||||
size of the cache in kilobytes. Caching is enabled by default (with a
|
||||
default cache size) for network streams. May be useful when playing files
|
||||
from slow media, but can also have negative effects, especially with file
|
||||
formats that require a lot of seeking, such as mp4. See also ``--no-cache``.
|
||||
--cache=<kBytes|no|auto>
|
||||
Set the size of the cache in kilobytes, disable it with ``no``, or
|
||||
automatically enable it if needed with ``auto`` (default: ``auto``).
|
||||
With ``auto``, the cache will usually be enabled for network streams,
|
||||
using a default size.
|
||||
|
||||
May be useful when playing files from slow media, but can also have
|
||||
negative effects, especially with file formats that require a lot of
|
||||
seeking, such as mp4.
|
||||
|
||||
Note that half the cache size will be used to allow fast seeking back. This
|
||||
is also the reason why a full cache is usually reported as 50% full. The
|
||||
|
@ -319,6 +322,12 @@
|
|||
filled to this position rather than performing a stream seek (default:
|
||||
50).
|
||||
|
||||
This matters for small forward seeks. With slow streams (especially http
|
||||
streams) there is a tradeoff between skipping the data between current
|
||||
position and seek destination, or performing an actual seek. Depending
|
||||
on the situation, either of these might be slower than the other method.
|
||||
This option allows control over this.
|
||||
|
||||
--cdda=<option1:option2>
|
||||
This option can be used to tune the CD Audio reading feature of mpv.
|
||||
|
||||
|
|
|
@ -493,7 +493,6 @@ libavdevice=auto
|
|||
_stream_cache=yes
|
||||
_priority=no
|
||||
def_dos_paths="#define HAVE_DOS_PATHS 0"
|
||||
def_stream_cache="#define CONFIG_STREAM_CACHE 1"
|
||||
def_priority="#undef CONFIG_PRIORITY"
|
||||
need_shmem=yes
|
||||
_build_man=auto
|
||||
|
@ -1452,9 +1451,11 @@ else
|
|||
fi
|
||||
echores "$_pthreads"
|
||||
|
||||
if cygwin || mingw32 ; then
|
||||
_stream_cache=no
|
||||
def_stream_cache="#undef CONFIG_STREAM_CACHE"
|
||||
_stream_cache="$_pthreads"
|
||||
if test "$_stream_cache" = yes ; then
|
||||
def_stream_cache='#define CONFIG_STREAM_CACHE'
|
||||
else
|
||||
def_stream_cache='#undef CONFIG_STREAM_CACHE'
|
||||
fi
|
||||
|
||||
echocheck "rpath"
|
||||
|
|
|
@ -324,7 +324,8 @@ const m_option_t mp_opts[] = {
|
|||
|
||||
#ifdef CONFIG_STREAM_CACHE
|
||||
OPT_CHOICE_OR_INT("cache", stream_cache_size, 0, 32, 0x7fffffff,
|
||||
({"no", -1}),
|
||||
({"no", 0},
|
||||
{"auto", -1}),
|
||||
OPTDEF_INT(-1)),
|
||||
OPT_FLOATRANGE("cache-min", stream_cache_min_percent, 0, 0, 99),
|
||||
OPT_FLOATRANGE("cache-seek-min", stream_cache_seek_min_percent, 0, 0, 99),
|
||||
|
|
947
stream/cache.c
947
stream/cache.c
File diff suppressed because it is too large
Load Diff
|
@ -138,6 +138,7 @@ static const stream_info_t *const auto_open_streams[] = {
|
|||
};
|
||||
|
||||
static stream_t *new_stream(void);
|
||||
static int stream_seek_unbuffered(stream_t *s, int64_t newpos);
|
||||
|
||||
static stream_t *open_stream_plugin(const stream_info_t *sinfo,
|
||||
const char *filename,
|
||||
|
@ -187,6 +188,9 @@ static stream_t *open_stream_plugin(const stream_info_t *sinfo,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (!s->read_chunk)
|
||||
s->read_chunk = 4 * (s->sector_size ? s->sector_size : STREAM_BUFFER_SIZE);
|
||||
|
||||
if (s->streaming && !s->cache_size) {
|
||||
// Set default cache size to use if user does not specify it.
|
||||
s->cache_size = 320;
|
||||
|
@ -337,10 +341,10 @@ void stream_set_capture_file(stream_t *s, const char *filename)
|
|||
}
|
||||
}
|
||||
|
||||
void stream_capture_write(stream_t *s)
|
||||
static void stream_capture_write(stream_t *s, void *buf, size_t len)
|
||||
{
|
||||
if (s->capture_file) {
|
||||
if (fwrite(s->buffer, s->buf_len, 1, s->capture_file) < 1) {
|
||||
if (s->capture_file && len > 0) {
|
||||
if (fwrite(buf, len, 1, s->capture_file) < 1) {
|
||||
mp_tmsg(MSGT_GLOBAL, MSGL_ERR, "Error writing capture file: %s\n",
|
||||
strerror(errno));
|
||||
stream_set_capture_file(s, NULL);
|
||||
|
@ -352,7 +356,7 @@ void stream_capture_write(stream_t *s)
|
|||
// s->buffer, but into buf[0..len] instead.
|
||||
// Returns < 0 on error, 0 on EOF, and length of bytes read on success.
|
||||
// Partial reads are possible, even if EOF is not reached.
|
||||
int stream_read_unbuffered(stream_t *s, void *buf, int len)
|
||||
static int stream_read_unbuffered(stream_t *s, void *buf, int len)
|
||||
{
|
||||
int orig_len = len;
|
||||
s->buf_pos = s->buf_len = 0;
|
||||
|
@ -397,6 +401,7 @@ eof_out:
|
|||
// This e.g. avoids issues with eof getting stuck when lavf seeks in MPEG-TS
|
||||
s->eof = 0;
|
||||
s->pos += len;
|
||||
stream_capture_write(s, buf, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
@ -427,8 +432,6 @@ int stream_fill_buffer(stream_t *s)
|
|||
return 0;
|
||||
s->buf_pos = 0;
|
||||
s->buf_len = len;
|
||||
// printf("[%d]",len);fflush(stdout);
|
||||
stream_capture_write(s);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
@ -480,7 +483,7 @@ int stream_write_buffer(stream_t *s, unsigned char *buf, int len)
|
|||
}
|
||||
|
||||
// Seek function bypassing the local stream buffer.
|
||||
int stream_seek_unbuffered(stream_t *s, int64_t newpos)
|
||||
static int stream_seek_unbuffered(stream_t *s, int64_t newpos)
|
||||
{
|
||||
if (newpos == 0 || newpos != s->pos) {
|
||||
switch (s->type) {
|
||||
|
@ -720,10 +723,16 @@ int stream_enable_cache_percent(stream_t **stream, int64_t stream_cache_size,
|
|||
float stream_cache_min_percent,
|
||||
float stream_cache_seek_min_percent)
|
||||
{
|
||||
return stream_enable_cache(stream, stream_cache_size * 1024,
|
||||
stream_cache_size * 1024 *
|
||||
|
||||
if (stream_cache_size == -1)
|
||||
stream_cache_size = (*stream)->cache_size;
|
||||
|
||||
stream_cache_size = stream_cache_size * 1024; // input is in KiB
|
||||
|
||||
return stream_enable_cache(stream, stream_cache_size,
|
||||
stream_cache_size *
|
||||
(stream_cache_min_percent / 100.0),
|
||||
stream_cache_size * 1024 *
|
||||
stream_cache_size *
|
||||
(stream_cache_seek_min_percent / 100.0));
|
||||
}
|
||||
|
||||
|
@ -756,7 +765,6 @@ int stream_enable_cache(stream_t **stream, int64_t size, int64_t min,
|
|||
cache->opts = orig->opts;
|
||||
cache->sector_size = orig->sector_size;
|
||||
cache->read_chunk = orig->read_chunk;
|
||||
cache->cache_size = orig->cache_size;
|
||||
cache->start_pos = orig->start_pos;
|
||||
cache->end_pos = orig->end_pos;
|
||||
|
||||
|
|
|
@ -174,7 +174,7 @@ typedef struct stream {
|
|||
int uncached_type; // like (uncached_stream ? uncached_stream->type : type)
|
||||
int flags; // MP_STREAM_SEEK_* or'ed flags
|
||||
int sector_size; // sector size (seek will be aligned on this size if non 0)
|
||||
int read_chunk; // maximum amount of data to read at once to limit latency (0 for default)
|
||||
int read_chunk; // maximum amount of data to read at once to limit latency
|
||||
unsigned int buf_pos, buf_len;
|
||||
int64_t pos, start_pos, end_pos;
|
||||
int eof;
|
||||
|
@ -205,7 +205,6 @@ int stream_fill_buffer(stream_t *s);
|
|||
void stream_unread_buffer(stream_t *s, void *buffer, size_t buffer_size);
|
||||
|
||||
void stream_set_capture_file(stream_t *s, const char *filename);
|
||||
void stream_capture_write(stream_t *s);
|
||||
|
||||
int stream_enable_cache_percent(stream_t **stream, int64_t stream_cache_size,
|
||||
float stream_cache_min_percent,
|
||||
|
@ -330,9 +329,6 @@ void stream_set_interrupt_callback(int (*cb)(struct input_ctx *, int),
|
|||
/// wait for time milliseconds
|
||||
int stream_check_interrupt(int time);
|
||||
|
||||
int stream_read_unbuffered(stream_t *s, void *buf, int len);
|
||||
int stream_seek_unbuffered(stream_t *s, int64_t newpos);
|
||||
|
||||
bool stream_manages_timeline(stream_t *s);
|
||||
|
||||
extern int dvd_title;
|
||||
|
|
Loading…
Reference in New Issue