summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/interface-changes.rst4
-rw-r--r--DOCS/man/options.rst17
-rw-r--r--options/options.c4
-rw-r--r--options/options.h1
-rw-r--r--player/video.c34
5 files changed, 48 insertions, 12 deletions
diff --git a/DOCS/interface-changes.rst b/DOCS/interface-changes.rst
index d7db0106b4..f02f6588ff 100644
--- a/DOCS/interface-changes.rst
+++ b/DOCS/interface-changes.rst
@@ -19,6 +19,10 @@ Interface changes
::
+ --- mpv 0.20.0 ---
+ - add --image-display-duration option - this also means that image duration
+ is not influenced by --mf-fps anymore in the general case (this is an
+ incompatible change)
--- mpv 0.19.0 ---
- deprecate "balance" option/property (no replacement)
--- mpv 0.18.1 ---
diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst
index 39416d2a64..0301e6971d 100644
--- a/DOCS/man/options.rst
+++ b/DOCS/man/options.rst
@@ -1873,6 +1873,23 @@ Window
file.mkv normally, then fail to open ``/dev/null``, then exit). (In
mpv 0.8.0, ``always`` was introduced, which restores the old behavior.)
+``--image-display-duration=<seconds|inf>``
+ If the current file is an image, play the image for the given amount of
+ seconds (default: 1). ``inf`` means the file is kept open forever (until
+ the user stops playback manually).
+
+ Unlike ``--keep-open``, the player is not paused, but simply continues
+ playback until the time has elapsed. (It should not use any resources
+ during "playback".)
+
+ This affects image files, which are defined as having only 1 video frame
+ and no audio. The player may recognize certain non-images as images, for
+ example if ``--length`` is used to reduce the length to 1 frame, or if
+ you seek to the last frame.
+
+ This option does not affect the framerate used for ``mf://`` or
+ ``--merge-files``. For that, use ``--mf-fps`` instead.
+
``--force-window=<yes|no|immediate>``
Create a video output window even if there is no video. This can be useful
when pretending that mpv is a GUI application. Currently, the window
diff --git a/options/options.c b/options/options.c
index 9e3e70385e..1a8ecaca2f 100644
--- a/options/options.c
+++ b/options/options.c
@@ -25,6 +25,7 @@
#include <stddef.h>
#include <sys/types.h>
#include <limits.h>
+#include <math.h>
#include "config.h"
@@ -214,6 +215,8 @@ const m_option_t mp_opts[] = {
({"no", 0},
{"yes", 1},
{"always", 2})),
+ OPT_DOUBLE("image-display-duration", image_display_duration,
+ M_OPT_RANGE, 0, INFINITY),
OPT_CHOICE("index", index_mode, 0, ({"default", 1}, {"recreate", 0})),
@@ -796,6 +799,7 @@ const struct MPOpts mp_default_opts = {
.play_frames = -1,
.rebase_start_time = 1,
.keep_open = 0,
+ .image_display_duration = 1.0,
.stream_id = { { [STREAM_AUDIO] = -1,
[STREAM_VIDEO] = -1,
[STREAM_SUB] = -1, },
diff --git a/options/options.h b/options/options.h
index 4de4a831bb..263caaa8de 100644
--- a/options/options.h
+++ b/options/options.h
@@ -190,6 +190,7 @@ typedef struct MPOpts {
int ignore_path_in_watch_later_config;
int pause;
int keep_open;
+ double image_display_duration;
char *lavfi_complex;
int stream_id[2][STREAM_TYPE_COUNT];
int stream_id_ff[STREAM_TYPE_COUNT];
diff --git a/player/video.c b/player/video.c
index e18f8cba70..23f8eefa33 100644
--- a/player/video.c
+++ b/player/video.c
@@ -1283,10 +1283,6 @@ static void calculate_frame_duration(struct MPContext *mpctx)
double pts1 = mpctx->next_frames[1]->pts;
if (pts0 != MP_NOPTS_VALUE && pts1 != MP_NOPTS_VALUE && pts1 >= pts0)
duration = pts1 - pts0;
- } else {
- // E.g. last frame on EOF. Only use it if it's significant.
- if (demux_duration >= 0.1)
- duration = demux_duration;
}
// The following code tries to compensate for rounded Matroska timestamps
@@ -1350,17 +1346,31 @@ void write_video(struct MPContext *mpctx)
return;
if (r == VD_EOF) {
- int prev_state = mpctx->video_status;
- mpctx->video_status = STATUS_EOF;
- if (mpctx->num_past_frames > 0 && mpctx->past_frames[0].duration > 0) {
- if (vo_still_displaying(vo))
- mpctx->video_status = STATUS_DRAINING;
- }
mpctx->delay = 0;
mpctx->last_av_difference = 0;
+
+ if (mpctx->video_status <= STATUS_PLAYING) {
+ mpctx->video_status = STATUS_DRAINING;
+ get_relative_time(mpctx);
+ if (mpctx->num_past_frames == 1 && mpctx->past_frames[0].pts == 0 &&
+ !mpctx->ao_chain)
+ {
+ mpctx->time_frame += opts->image_display_duration;
+ } else {
+ mpctx->time_frame = 0;
+ }
+ }
+
+ if (mpctx->video_status == STATUS_DRAINING) {
+ mpctx->time_frame -= get_relative_time(mpctx);
+ mpctx->sleeptime = MPMIN(mpctx->sleeptime, mpctx->time_frame);
+ if (mpctx->time_frame <= 0) {
+ MP_VERBOSE(mpctx, "video EOF reached\n");
+ mpctx->video_status = STATUS_EOF;
+ }
+ }
+
MP_DBG(mpctx, "video EOF (status=%d)\n", mpctx->video_status);
- if (prev_state != mpctx->video_status)
- mpctx->sleeptime = 0;
return;
}