summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2012-12-02 00:22:54 +0100
committerwm4 <wm4@nowhere>2012-12-03 21:08:52 +0100
commit3486f59fe28efa81ce6951208b94cec91ad6cdb8 (patch)
treee85c775c112ce3465ccf6f367f08821828626313 /core
parentc02f2529385ab2ddd9605c5ebe5d2a68be200ec4 (diff)
downloadmpv-3486f59fe28efa81ce6951208b94cec91ad6cdb8.tar.bz2
mpv-3486f59fe28efa81ce6951208b94cec91ad6cdb8.tar.xz
core: automatically pause on low cache
When the cache fill status goes below a certain threshold, automatically pause the player. When the cache is filled again, unpause again. This is intended to help with streaming from http. It's better to pause a while, rather than exposing extremely crappy behavior when packet reads during decoding block the entire player. In theory, we should try to increase the cache if underruns happen too often. Unfortunately, changing the cache implementation would be very hard, because it's insane code (forks, uses shared memory and "volatile" etc.). So for now, this just reduces the frequency of the stuttering if the network is absolutely too slow to play the stream in realtime.
Diffstat (limited to 'core')
-rw-r--r--core/cfg-mplayer.h2
-rw-r--r--core/defaultopts.c1
-rw-r--r--core/mp_core.h2
-rw-r--r--core/mplayer.c44
-rw-r--r--core/options.h1
5 files changed, 47 insertions, 3 deletions
diff --git a/core/cfg-mplayer.h b/core/cfg-mplayer.h
index b1c693a5a9..03432c8e04 100644
--- a/core/cfg-mplayer.h
+++ b/core/cfg-mplayer.h
@@ -329,6 +329,8 @@ const m_option_t common_opts[] = {
OPT_FLOATRANGE("cache-min", stream_cache_min_percent, 0, 0, 99),
OPT_FLOATRANGE("cache-seek-min", stream_cache_seek_min_percent, 0, 0, 99),
+ OPT_CHOICE_OR_INT("cache-pause", stream_cache_pause, 0,
+ 0, 40, ({"no", -1})),
#endif /* CONFIG_STREAM_CACHE */
{"cdrom-device", &cdrom_device, CONF_TYPE_STRING, 0, 0, 0, NULL},
#ifdef CONFIG_DVDREAD
diff --git a/core/defaultopts.c b/core/defaultopts.c
index 1c179a74a1..9f746b3dc1 100644
--- a/core/defaultopts.c
+++ b/core/defaultopts.c
@@ -32,6 +32,7 @@ void set_default_mplayer_options(struct MPOpts *opts)
.chapter_merge_threshold = 100,
.stream_cache_min_percent = 20.0,
.stream_cache_seek_min_percent = 50.0,
+ .stream_cache_pause = 10.0,
.chapterrange = {-1, -1},
.edition_id = -1,
.user_correct_pts = -1,
diff --git a/core/mp_core.h b/core/mp_core.h
index dac4dd26d0..f633f3481f 100644
--- a/core/mp_core.h
+++ b/core/mp_core.h
@@ -257,6 +257,8 @@ typedef struct MPContext {
// step this many frames, then pause
int step_frames;
+ bool paused_for_cache;
+
// Set after showing warning about decoding being too slow for realtime
// playback rate. Used to avoid showing it multiple times.
bool drop_message_shown;
diff --git a/core/mplayer.c b/core/mplayer.c
index e60c7e173c..04ea0e2597 100644
--- a/core/mplayer.c
+++ b/core/mplayer.c
@@ -1051,6 +1051,14 @@ static int get_cache_percent(struct MPContext *mpctx)
return -1;
}
+static bool get_cache_idle(struct MPContext *mpctx)
+{
+ int idle = 0;
+ if (mpctx->stream)
+ stream_control(mpctx->stream, STREAM_CTRL_GET_CACHE_IDLE, &idle);
+ return idle;
+}
+
/**
* \brief append a formatted string
* \param buf buffer to print into
@@ -1131,8 +1139,12 @@ static void print_status(struct MPContext *mpctx)
line[0] = '\0';
// Playback status
- if (mpctx->paused)
+ if (mpctx->paused_for_cache) {
+ saddf(line, width, "(Buffering) ");
+ } else if (mpctx->paused) {
saddf(line, width, "(Paused) ");
+ }
+
if (mpctx->sh_audio)
saddf(line, width, "A");
if (mpctx->sh_video)
@@ -1458,8 +1470,15 @@ static void sadd_osd_status(char *buffer, int len, struct MPContext *mpctx,
{
bool fractions = mpctx->opts.osd_fractions;
int sym = mpctx->osd_function;
- if (!sym)
- sym = mpctx->paused || mpctx->step_frames ? OSD_PAUSE : OSD_PLAY;
+ if (!sym) {
+ if (mpctx->paused_for_cache) {
+ sym = OSD_CLOCK;
+ } else if (mpctx->paused || mpctx->step_frames) {
+ sym = OSD_PAUSE;
+ } else {
+ sym = OSD_PLAY;
+ }
+ }
saddf_osd_function_sym(buffer, len, sym);
sadd_hhmmssff(buffer, len, get_current_time(mpctx), fractions);
if (full) {
@@ -2579,6 +2598,7 @@ void unpause_player(struct MPContext *mpctx)
return;
mpctx->paused = 0;
mpctx->osd_function = 0;
+ mpctx->paused_for_cache = false;
if (mpctx->ao && mpctx->sh_audio)
ao_resume(mpctx->ao);
@@ -3070,6 +3090,22 @@ static void update_avsync(struct MPContext *mpctx)
}
}
+static void handle_pause_on_low_cache(struct MPContext *mpctx)
+{
+ struct MPOpts *opts = &mpctx->opts;
+ int cache = get_cache_percent(mpctx);
+ bool idle = get_cache_idle(mpctx);
+ if (mpctx->paused && mpctx->paused_for_cache) {
+ if (cache < 0 || cache >= opts->stream_cache_min_percent || idle)
+ unpause_player(mpctx);
+ } else if (!mpctx->paused) {
+ if (cache >= 0 && cache <= opts->stream_cache_pause && !idle) {
+ pause_player(mpctx);
+ mpctx->paused_for_cache = true;
+ }
+ }
+}
+
static void run_playloop(struct MPContext *mpctx)
{
struct MPOpts *opts = &mpctx->opts;
@@ -3390,6 +3426,8 @@ static void run_playloop(struct MPContext *mpctx)
//================= Keyboard events, SEEKing ====================
+ handle_pause_on_low_cache(mpctx);
+
mp_cmd_t *cmd;
while ((cmd = mp_input_get_cmd(mpctx->input, 0, 1)) != NULL) {
/* Allow running consecutive seek commands to combine them,
diff --git a/core/options.h b/core/options.h
index 47f4593b9b..2847637bcc 100644
--- a/core/options.h
+++ b/core/options.h
@@ -55,6 +55,7 @@ typedef struct MPOpts {
int stream_cache_size;
float stream_cache_min_percent;
float stream_cache_seek_min_percent;
+ int stream_cache_pause;
int chapterrange[2];
int edition_id;
int correct_pts;