summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorxylosper <darklin20@gmail.com>2014-03-25 22:41:28 +0900
committerwm4 <wm4@nowhere>2014-03-30 17:53:05 +0200
commitfc510f0da889f392c1e6985eab9a40e37986cba8 (patch)
treee9c1ae551fe04a654c4173b02b5b64776a65ab74
parent8d5775a8d2ae7e5ebf031da8b6ab51ec2e7ff3fb (diff)
downloadmpv-fc510f0da889f392c1e6985eab9a40e37986cba8.tar.bz2
mpv-fc510f0da889f392c1e6985eab9a40e37986cba8.tar.xz
dvdnav: make MP_NAV_EVENT_RESET_ALL handled properly
dvdnav.c did not handle event in regular sequence. Usually this does not make any trouble except around MP_NAV_EVENT_RESET_ALL. Those events should be handled in regular sequence. If they're mixed, it can make wrong result. For instance, MP_NAV_EVENT_HIGHLIGHT right after MP_NAV_EVENT_RESET_ALL should not be ignored but it might be because MP_NAV_EVENT_RESET_ALL makes the demuxer reloaded and osd hidden.
-rw-r--r--player/dvdnav.c4
-rw-r--r--stream/stream_dvdnav.c67
2 files changed, 40 insertions, 31 deletions
diff --git a/player/dvdnav.c b/player/dvdnav.c
index 6c5fed2ed6..3f711b4834 100644
--- a/player/dvdnav.c
+++ b/player/dvdnav.c
@@ -140,7 +140,9 @@ void mp_handle_nav(struct MPContext *mpctx)
case MP_NAV_EVENT_RESET_ALL: {
mpctx->stop_play = PT_RELOAD_DEMUXER;
MP_VERBOSE(nav, "reload\n");
- break;
+ // return immediately.
+ // other events should be handled after reloaded.
+ return;
}
case MP_NAV_EVENT_RESET: {
nav->nav_still_frame = 0;
diff --git a/stream/stream_dvdnav.c b/stream/stream_dvdnav.c
index ca17846921..1046608558 100644
--- a/stream/stream_dvdnav.c
+++ b/stream/stream_dvdnav.c
@@ -298,42 +298,47 @@ static void handle_cmd(stream_t *s, struct mp_nav_cmd *ev)
}
+static inline bool set_event_type(struct priv *priv, int type,
+ struct mp_nav_event *event)
+{
+ if (!(priv->next_event & (1 << type)))
+ return false;
+ priv->next_event &= ~(1 << type);
+ event->event = type;
+ return true;
+}
+
static void fill_next_event(stream_t *s, struct mp_nav_event **ret)
{
struct priv *priv = s->priv;
struct mp_nav_event e = {0};
- for (int n = 0; n < 30; n++) {
- if (priv->next_event & (1 << n)) {
- priv->next_event &= ~(1 << n);
- e.event = n;
- switch (e.event) {
- case MP_NAV_EVENT_HIGHLIGHT: {
- dvdnav_highlight_event_t hlev = priv->hlev;
- e.u.highlight.display = hlev.display;
- e.u.highlight.sx = hlev.sx;
- e.u.highlight.sy = hlev.sy;
- e.u.highlight.ex = hlev.ex;
- e.u.highlight.ey = hlev.ey;
- e.u.highlight.palette = hlev.palette;
- break;
- }
- case MP_NAV_EVENT_MENU_MODE:
- e.u.menu_mode.enable = !dvdnav_is_domain_vts(priv->dvdnav);
- break;
- case MP_NAV_EVENT_STILL_FRAME:
- e.u.still_frame.seconds = priv->still_length;
- break;
- }
- break;
- }
+ if (!set_event_type(priv, MP_NAV_EVENT_RESET_ALL, &e))
+ for (int n = 0; n < 30 && !set_event_type(priv, n, &e); n++) ;
+ switch (e.event) {
+ case MP_NAV_EVENT_NONE:
+ return;
+ case MP_NAV_EVENT_HIGHLIGHT: {
+ dvdnav_highlight_event_t hlev = priv->hlev;
+ e.u.highlight.display = hlev.display;
+ e.u.highlight.sx = hlev.sx;
+ e.u.highlight.sy = hlev.sy;
+ e.u.highlight.ex = hlev.ex;
+ e.u.highlight.ey = hlev.ey;
+ e.u.highlight.palette = hlev.palette;
+ break;
}
- if (e.event) {
- *ret = talloc(NULL, struct mp_nav_event);
- **ret = e;
-
- MP_VERBOSE(s, "DVDNAV: player event '%s'\n",
- LOOKUP_NAME(mp_nav_event_types, e.event));
+ case MP_NAV_EVENT_MENU_MODE:
+ e.u.menu_mode.enable = !dvdnav_is_domain_vts(priv->dvdnav);
+ break;
+ case MP_NAV_EVENT_STILL_FRAME:
+ e.u.still_frame.seconds = priv->still_length;
+ break;
}
+ *ret = talloc(NULL, struct mp_nav_event);
+ **ret = e;
+
+ MP_VERBOSE(s, "DVDNAV: player event '%s'\n",
+ LOOKUP_NAME(mp_nav_event_types, e.event));
}
static int fill_buffer(stream_t *s, char *buf, int max_len)
@@ -414,6 +419,8 @@ static int fill_buffer(stream_t *s, char *buf, int max_len)
priv->had_initial_vts = true;
break;
}
+ // clear all previous events
+ priv->next_event = 0;
priv->next_event |= 1 << MP_NAV_EVENT_RESET;
priv->next_event |= 1 << MP_NAV_EVENT_RESET_ALL;
if (dvdnav_current_title_info(dvdnav, &tit, &part) == DVDNAV_STATUS_OK)