From ff706ee86d4ca1e31de6c6c322a3bedb819ead05 Mon Sep 17 00:00:00 2001 From: Uoti Urpala Date: Tue, 14 Dec 2010 22:31:39 +0200 Subject: core: avoid using sh_video->pts as "current pts" Add a new field "video_pts" to mpctx. It records the time of the last frame flipped visible on VO. Change various code which used sh_video->pts to use either the new field or get_current_time(mpctx). --- command.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'command.c') diff --git a/command.c b/command.c index 4ffe29a351..489cd2d047 100644 --- a/command.c +++ b/command.c @@ -2689,14 +2689,12 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd) abs = (cmd->nargs > 1) ? cmd->args[1].v.i : 0; if (abs == 2) { /* Absolute seek to a specific timestamp in seconds */ mpctx->abs_seek_pos = SEEK_ABSOLUTE; - if (sh_video) - mpctx->osd_function = - (v > sh_video->pts) ? OSD_FFW : OSD_REW; + mpctx->osd_function = v > get_current_time(mpctx) ? + OSD_FFW : OSD_REW; mpctx->rel_seek_secs = v; } else if (abs) { /* Absolute seek by percentage */ mpctx->abs_seek_pos = SEEK_ABSOLUTE | SEEK_FACTOR; - if (sh_video) - mpctx->osd_function = OSD_FFW; // Direction isn't set correctly + mpctx->osd_function = OSD_FFW; // Direction isn't set correctly mpctx->rel_seek_secs = v / 100.0; } else { mpctx->rel_seek_secs += v; @@ -2905,12 +2903,12 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd) case MP_CMD_SUB_STEP: if (sh_video) { int movement = cmd->args[0].v.i; - step_sub(subdata, sh_video->pts, movement); + step_sub(subdata, mpctx->video_pts, movement); #ifdef CONFIG_ASS if (ass_track) sub_delay += ass_step_sub(ass_track, - (sh_video->pts + + (mpctx->video_pts + sub_delay) * 1000 + .5, movement) / 1000.; #endif set_osd_tmsg(OSD_MSG_SUB_DELAY, 1, osd_duration, -- cgit v1.2.3 From b9a3579ec980dfb01d0b952bf0b859ecdf62d7ea Mon Sep 17 00:00:00 2001 From: Uoti Urpala Date: Sat, 18 Dec 2010 08:02:48 +0200 Subject: commands: add generic option -> property wrapper Add mp_property_generic_option(), a property function that can be used for generic option-based properties that do not require any action beyond manipulating the value of the option variable. Currently it directly implements GET and SET, plus STEP_UP for "choice" options only. Use it to add a property for -pts-association-mode (not particularly useful in normal use, but serves as a test). --- command.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'command.c') diff --git a/command.c b/command.c index 489cd2d047..247af1b9d1 100644 --- a/command.c +++ b/command.c @@ -34,6 +34,7 @@ #include "libvo/sub.h" #include "m_option.h" #include "m_property.h" +#include "m_config.h" #include "metadata.h" #include "libmpcodecs/vf.h" #include "libmpcodecs/vd.h" @@ -226,6 +227,39 @@ static void log_sub(struct MPContext *mpctx) /// \ingroup Properties ///@{ +static int mp_property_generic_option(struct m_option *prop, int action, + void *arg, MPContext *mpctx) +{ + char *optname = prop->priv; + const struct m_option *opt = m_config_get_option(mpctx->mconfig, optname); + void *valptr = m_option_get_ptr(opt, &mpctx->opts); + + switch (action) { + case M_PROPERTY_GET_TYPE: + *(const struct m_option **)arg = opt; + return M_PROPERTY_OK; + case M_PROPERTY_GET: + m_option_copy(opt, arg, valptr); + return M_PROPERTY_OK; + case M_PROPERTY_SET: + m_option_copy(opt, valptr, arg); + return M_PROPERTY_OK; + case M_PROPERTY_STEP_UP: + if (opt->type == &m_option_type_choice) { + int v = *(int *) valptr; + int best = v; + struct m_opt_choice_alternatives *alt; + for (alt = opt->priv; alt->name; alt++) + if ((unsigned) alt->value - v - 1 < (unsigned) best - v - 1) + best = alt->value; + *(int *) valptr = best; + return M_PROPERTY_OK; + } + break; + } + return M_PROPERTY_NOT_IMPLEMENTED; +} + /// OSD level (RW) static int mp_property_osdlevel(m_option_t *prop, int action, void *arg, MPContext *mpctx) @@ -2189,6 +2223,8 @@ static const m_option_t mp_properties[] = { M_OPT_RANGE, 0, 1, NULL }, { "capturing", mp_property_capture, CONF_TYPE_FLAG, M_OPT_RANGE, 0, 1, NULL }, + { "pts_association_mode", mp_property_generic_option, &m_option_type_choice, + 0, 0, 0, "pts-association-mode" }, // Audio { "volume", mp_property_volume, CONF_TYPE_FLOAT, @@ -2362,6 +2398,7 @@ static struct property_osd_display { { "loop", 0, -1, _("Loop: %s") }, { "chapter", -1, -1, NULL }, { "capturing", 0, -1, _("Capturing: %s") }, + { "pts_association_mode", 0, -1, "PTS association mode: %s" }, // audio { "volume", OSD_VOLUME, -1, _("Volume") }, { "mute", 0, -1, _("Mute: %s") }, -- cgit v1.2.3 From 23f598e0ee2151923a44077f510cd484f239480b Mon Sep 17 00:00:00 2001 From: Uoti Urpala Date: Sat, 18 Dec 2010 10:13:45 +0200 Subject: core: add struct for queued seek info To prepare for the addition of exact seek support, add a struct for queued seek state and a helper function to update its state. It would have been cumbersome to update additional state (showing whether the seek is forced to be exact or non-exact) manually at every point that handles seeks. --- command.c | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) (limited to 'command.c') diff --git a/command.c b/command.c index 247af1b9d1..394bf566c4 100644 --- a/command.c +++ b/command.c @@ -454,8 +454,7 @@ static int mp_property_percent_pos(m_option_t *prop, int action, return m_property_int_ro(prop, action, arg, get_percent_pos(mpctx)); } - mpctx->abs_seek_pos = SEEK_ABSOLUTE | SEEK_FACTOR; - mpctx->rel_seek_secs = pos / 100.0; + queue_seek(mpctx, MPSEEK_FACTOR, pos / 100.0, 0); return M_PROPERTY_OK; } @@ -469,13 +468,12 @@ static int mp_property_time_pos(m_option_t *prop, int action, case M_PROPERTY_SET: if(!arg) return M_PROPERTY_ERROR; M_PROPERTY_CLAMP(prop, *(double*)arg); - mpctx->abs_seek_pos = SEEK_ABSOLUTE; - mpctx->rel_seek_secs = *(double*)arg; + queue_seek(mpctx, MPSEEK_ABSOLUTE, *(double*)arg, 0); return M_PROPERTY_OK; case M_PROPERTY_STEP_UP: case M_PROPERTY_STEP_DOWN: - mpctx->rel_seek_secs += (arg ? *(double*)arg : 10.0) * - (action == M_PROPERTY_STEP_UP ? 1.0 : -1.0); + queue_seek(mpctx, MPSEEK_RELATIVE, (arg ? *(double*)arg : 10.0) * + (action == M_PROPERTY_STEP_UP ? 1.0 : -1.0), 0); return M_PROPERTY_OK; } return m_property_time_ro(prop, action, arg, get_current_time(mpctx)); @@ -531,20 +529,16 @@ static int mp_property_chapter(m_option_t *prop, int action, void *arg, } double next_pts = 0; + queue_seek(mpctx, MPSEEK_NONE, 0, 0); chapter = seek_chapter(mpctx, chapter, &next_pts, &chapter_name); - mpctx->rel_seek_secs = 0; - mpctx->abs_seek_pos = 0; if (chapter >= 0) { - if (next_pts > -1.0) { - mpctx->abs_seek_pos = SEEK_ABSOLUTE; - mpctx->rel_seek_secs = next_pts; - } + if (next_pts > -1.0) + queue_seek(mpctx, MPSEEK_ABSOLUTE, next_pts, 0); if (chapter_name) set_osd_tmsg(OSD_MSG_TEXT, 1, opts->osd_duration, "Chapter: (%d) %s", chapter + 1, chapter_name); - } - else if (step_all > 0) - mpctx->rel_seek_secs = 1000000000.; + } else if (step_all > 0) + queue_seek(mpctx, MPSEEK_RELATIVE, 1000000000, 0); else set_osd_tmsg(OSD_MSG_TEXT, 1, opts->osd_duration, "Chapter: (%d) %s", 0, mp_gtext("unknown")); @@ -2725,16 +2719,14 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd) v = cmd->args[0].v.f; abs = (cmd->nargs > 1) ? cmd->args[1].v.i : 0; if (abs == 2) { /* Absolute seek to a specific timestamp in seconds */ - mpctx->abs_seek_pos = SEEK_ABSOLUTE; + queue_seek(mpctx, MPSEEK_ABSOLUTE, v, 0); mpctx->osd_function = v > get_current_time(mpctx) ? OSD_FFW : OSD_REW; - mpctx->rel_seek_secs = v; } else if (abs) { /* Absolute seek by percentage */ - mpctx->abs_seek_pos = SEEK_ABSOLUTE | SEEK_FACTOR; + queue_seek(mpctx, MPSEEK_FACTOR, v / 100.0, 0); mpctx->osd_function = OSD_FFW; // Direction isn't set correctly - mpctx->rel_seek_secs = v / 100.0; } else { - mpctx->rel_seek_secs += v; + queue_seek(mpctx, MPSEEK_RELATIVE, v, 0); mpctx->osd_function = (v > 0) ? OSD_FFW : OSD_REW; } } -- cgit v1.2.3 From f0649f13d698eb6aeffeaacd6801b666c4366caf Mon Sep 17 00:00:00 2001 From: Uoti Urpala Date: Wed, 15 Dec 2010 01:09:47 +0200 Subject: core: add support for precise non-keyframe-limited seeks Add support for seeking to an arbitrary non-keyframe position by decoding video starting from the previous keyframe. Whether to use this functionality when seeking is controlled by the new option -hr-seek and a new third argument to the "seek" command. The default is to use it for absolute seeks (like chapter seeks) but not for relative ones. Because there's currently no support for cutting encoded audio some desync is expected if encoded audio passthrough is used. Currently precise seeks always go to the first frame with timestamp equal to or greater than the target position; there's no support for "matching or earlier" backwards seeks at frame level. --- command.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'command.c') diff --git a/command.c b/command.c index 394bf566c4..c1519d001d 100644 --- a/command.c +++ b/command.c @@ -2219,6 +2219,8 @@ static const m_option_t mp_properties[] = { M_OPT_RANGE, 0, 1, NULL }, { "pts_association_mode", mp_property_generic_option, &m_option_type_choice, 0, 0, 0, "pts-association-mode" }, + { "hr_seek", mp_property_generic_option, &m_option_type_choice, + 0, 0, 0, "hr-seek" }, // Audio { "volume", mp_property_volume, CONF_TYPE_FLOAT, @@ -2393,6 +2395,7 @@ static struct property_osd_display { { "chapter", -1, -1, NULL }, { "capturing", 0, -1, _("Capturing: %s") }, { "pts_association_mode", 0, -1, "PTS association mode: %s" }, + { "hr_seek", 0, -1, "hr-seek: %s" }, // audio { "volume", OSD_VOLUME, -1, _("Volume") }, { "mute", 0, -1, _("Mute: %s") }, @@ -2713,20 +2716,19 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd) if (!set_property_command(mpctx, cmd)) switch (cmd->id) { case MP_CMD_SEEK:{ - float v; - int abs; mpctx->add_osd_seek_info = true; - v = cmd->args[0].v.f; - abs = (cmd->nargs > 1) ? cmd->args[1].v.i : 0; + float v = cmd->args[0].v.f; + int abs = (cmd->nargs > 1) ? cmd->args[1].v.i : 0; + int exact = (cmd->nargs > 2) ? cmd->args[2].v.i : 0; if (abs == 2) { /* Absolute seek to a specific timestamp in seconds */ - queue_seek(mpctx, MPSEEK_ABSOLUTE, v, 0); + queue_seek(mpctx, MPSEEK_ABSOLUTE, v, exact); mpctx->osd_function = v > get_current_time(mpctx) ? OSD_FFW : OSD_REW; } else if (abs) { /* Absolute seek by percentage */ - queue_seek(mpctx, MPSEEK_FACTOR, v / 100.0, 0); + queue_seek(mpctx, MPSEEK_FACTOR, v / 100.0, exact); mpctx->osd_function = OSD_FFW; // Direction isn't set correctly } else { - queue_seek(mpctx, MPSEEK_RELATIVE, v, 0); + queue_seek(mpctx, MPSEEK_RELATIVE, v, exact); mpctx->osd_function = (v > 0) ? OSD_FFW : OSD_REW; } } -- cgit v1.2.3