summaryrefslogtreecommitdiffstats
path: root/player
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-05-08 00:49:21 +0200
committerwm4 <wm4@nowhere>2014-05-08 01:25:48 +0200
commit996ab61a6a3422c84f8924ebb72ffda833545777 (patch)
tree91cffdb8fc8bc25f7d7c954e3812f5c7d86f96da /player
parentc57660fbf77eb29ddd2187f84b7450f601069b05 (diff)
downloadmpv-996ab61a6a3422c84f8924ebb72ffda833545777.tar.bz2
mpv-996ab61a6a3422c84f8924ebb72ffda833545777.tar.xz
command: add property that estimates current video FPS
This is done after filters, so things like framerate-doubling deinterlacing is accounted for. Unfortunately, framedropping can cause inaccuracies (especially after precise seeks), and we can't really know when that happens. Even though we know that the decoder might drop a frame if we request it to do so, we don't know when the dropped frame will start or stop affecting the video filter chain. Video filters can have frames buffered, and we can't tell at which point the dropped frame would have been output. It's not even possible to mark a discontinuity after seek, because again we don't know if the filter chain still has the discontinuity within its buffers. So we have to live with the fact that the output of this property can be completely broken after seek, unless --no-hr-seek-framedrop is used.
Diffstat (limited to 'player')
-rw-r--r--player/command.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/player/command.c b/player/command.c
index b0f74219f7..08f97f4b2e 100644
--- a/player/command.c
+++ b/player/command.c
@@ -1986,6 +1986,32 @@ static int mp_property_fps(m_option_t *prop, int action, void *arg,
return m_property_float_ro(prop, action, arg, mpctx->d_video->fps);
}
+static int mp_property_vf_fps(m_option_t *prop, int action, void *arg,
+ MPContext *mpctx)
+{
+ if (!mpctx->d_video)
+ return M_PROPERTY_UNAVAILABLE;
+ double next_pts = mpctx->vo_pts_history_pts[0];
+ if (mpctx->vo_pts_history_seek[0] != mpctx->vo_pts_history_seek_ts)
+ return M_PROPERTY_UNAVAILABLE;
+ if (next_pts == MP_NOPTS_VALUE)
+ return M_PROPERTY_UNAVAILABLE;
+ int num_samples = 10;
+ assert(num_samples + 1 <= MAX_NUM_VO_PTS);
+ double duration = 0;
+ for (int n = 1; n < 1 + num_samples; n++) {
+ double frame_pts = mpctx->vo_pts_history_pts[n];
+ // Discontinuity -> refuse to return a value.
+ if (mpctx->vo_pts_history_seek[n] != mpctx->vo_pts_history_seek_ts)
+ return M_PROPERTY_UNAVAILABLE;
+ if (frame_pts == MP_NOPTS_VALUE)
+ return M_PROPERTY_UNAVAILABLE;
+ duration += next_pts - frame_pts;
+ next_pts = frame_pts;
+ }
+ return m_property_double_ro(prop, action, arg, num_samples / duration);
+}
+
/// Video aspect (RO)
static int mp_property_aspect(m_option_t *prop, int action, void *arg,
MPContext *mpctx)
@@ -2432,6 +2458,7 @@ static const m_option_t mp_properties[] = {
CONF_RANGE, 0.125, 8 },
{ "fps", mp_property_fps, CONF_TYPE_FLOAT,
0, 0, 0, NULL },
+ { "estimated-vf-fps", mp_property_vf_fps, CONF_TYPE_DOUBLE },
{ "video-aspect", mp_property_aspect, CONF_TYPE_FLOAT,
CONF_RANGE, -1, 10, NULL },
M_OPTION_PROPERTY_CUSTOM("vid", mp_property_video),