summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mpvcore/player/dvdnav.c25
-rw-r--r--stream/stream_dvdnav.c28
-rw-r--r--stream/stream_dvdnav.h5
3 files changed, 36 insertions, 22 deletions
diff --git a/mpvcore/player/dvdnav.c b/mpvcore/player/dvdnav.c
index 98afa82138..592c0a4ce2 100644
--- a/mpvcore/player/dvdnav.c
+++ b/mpvcore/player/dvdnav.c
@@ -35,7 +35,7 @@
struct mp_nav_state {
struct mp_log *log;
- bool nav_still_frame;
+ int nav_still_frame;
bool nav_eof;
bool nav_menu;
bool nav_draining;
@@ -81,6 +81,7 @@ void mp_nav_reset(struct MPContext *mpctx)
nav->hi_visible = 0;
nav->nav_menu = false;
nav->nav_draining = false;
+ nav->nav_still_frame = 0;
mp_input_disable_section(mpctx->input, "dvdnav-menu");
// Prevent demuxer init code to seek to the "start"
mpctx->stream->start_pos = stream_tell(mpctx->stream);
@@ -141,9 +142,20 @@ void mp_handle_nav(struct MPContext *mpctx)
MP_VERBOSE(nav, "reload\n");
break;
}
+ case MP_NAV_EVENT_RESET: {
+ nav->nav_still_frame = 0;
+ break;
+ }
case MP_NAV_EVENT_EOF:
nav->nav_eof = true;
break;
+ case MP_NAV_EVENT_STILL_FRAME: {
+ int len = ev->u.still_frame.seconds;
+ MP_VERBOSE(nav, "wait for %d seconds\n", len);
+ if (len > 0 && nav->nav_still_frame == 0)
+ nav->nav_still_frame = len;
+ break;
+ }
case MP_NAV_EVENT_MENU_MODE:
nav->nav_menu = ev->u.menu_mode.enable;
if (nav->nav_menu) {
@@ -169,6 +181,17 @@ void mp_handle_nav(struct MPContext *mpctx)
}
talloc_free(ev);
}
+ if (mpctx->stop_play == AT_END_OF_FILE) {
+ if (nav->nav_still_frame > 0) {
+ // gross hack
+ mpctx->time_frame += nav->nav_still_frame;
+ mpctx->playing_last_frame = true;
+ nav->nav_still_frame = -2;
+ } else if (nav->nav_still_frame == -2) {
+ struct mp_nav_cmd inp = {MP_NAV_CMD_SKIP_STILL};
+ stream_control(mpctx->stream, STREAM_CTRL_NAV_CMD, &inp);
+ }
+ }
if (nav->nav_draining && mpctx->stop_play == AT_END_OF_FILE) {
MP_VERBOSE(nav, "execute drain\n");
struct mp_nav_cmd inp = {MP_NAV_CMD_DRAIN_OK};
diff --git a/stream/stream_dvdnav.c b/stream/stream_dvdnav.c
index f66eeec605..5504d6fb79 100644
--- a/stream/stream_dvdnav.c
+++ b/stream/stream_dvdnav.c
@@ -87,6 +87,7 @@ static char *mp_nav_cmd_types[] = {
DNE(MP_NAV_CMD_ENABLE),
DNE(MP_NAV_CMD_DRAIN_OK),
DNE(MP_NAV_CMD_RESUME),
+ DNE(MP_NAV_CMD_SKIP_STILL),
DNE(MP_NAV_CMD_MENU),
DNE(MP_NAV_CMD_MOUSE_POS),
};
@@ -146,11 +147,6 @@ static void dvdnav_get_highlight(struct priv *priv, int display_mode)
}
}
-static inline int dvdnav_get_duration(int length)
-{
- return (length == 255) ? 0 : length * 1000;
-}
-
static void handle_menu_input(stream_t *stream, const char *cmd)
{
struct priv *priv = stream->priv;
@@ -287,6 +283,9 @@ static void handle_cmd(stream_t *s, struct mp_nav_cmd *ev)
case MP_NAV_CMD_RESUME:
priv->suspended_read = false;
break;
+ case MP_NAV_CMD_SKIP_STILL:
+ dvdnav_still_skip(priv->dvdnav);
+ break;
case MP_NAV_CMD_MENU:
handle_menu_input(s, ev->u.menu.action);
break;
@@ -319,6 +318,9 @@ static void fill_next_event(stream_t *s, struct mp_nav_event **ret)
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;
}
@@ -353,7 +355,7 @@ static int fill_buffer(stream_t *s, char *buf, int max_len)
event, dvdnav_err_to_string(dvdnav));
return 0;
}
- if (1||event != DVDNAV_BLOCK_OK) {
+ if (event != DVDNAV_BLOCK_OK) {
const char *name = LOOKUP_NAME(mp_dvdnav_events, event);
mp_msg(MSGT_CPLAYER, MSGL_V, "DVDNAV: event %s (%d).\n", name, event);
dvdnav_get_highlight(priv, 1);
@@ -370,9 +372,10 @@ static int fill_buffer(stream_t *s, char *buf, int max_len)
case DVDNAV_STILL_FRAME: {
dvdnav_still_event_t *still_event = (dvdnav_still_event_t *) buf;
priv->still_length = still_event->length;
+ if (priv->still_length == 255)
+ priv->still_length = -1;
mp_msg(MSGT_CPLAYER, MSGL_V, "len=%d\n", priv->still_length);
/* set still frame duration */
- priv->duration = dvdnav_get_duration(priv->still_length);
if (priv->still_length <= 1) {
pci_t *pnavpci = dvdnav_get_current_nav_pci(dvdnav);
priv->duration = mp_dvdtimetomsec(&pnavpci->pci_gi.e_eltm);
@@ -428,23 +431,12 @@ static int fill_buffer(stream_t *s, char *buf, int max_len)
}
case DVDNAV_CELL_CHANGE: {
dvdnav_cell_change_event_t *ev = (dvdnav_cell_change_event_t *)buf;
- uint32_t nextstill;
priv->next_event |= 1 << MP_NAV_EVENT_RESET;
priv->next_event |= 1 << MP_NAV_EVENT_MENU_MODE;
if (ev->pgc_length)
priv->duration = ev->pgc_length / 90;
- nextstill = dvdnav_get_next_still_flag(dvdnav);
- if (nextstill) {
- priv->duration = dvdnav_get_duration(nextstill);
- priv->still_length = nextstill;
- if (priv->still_length <= 1) {
- pci_t *pnavpci = dvdnav_get_current_nav_pci(dvdnav);
- priv->duration = mp_dvdtimetomsec(&pnavpci->pci_gi.e_eltm);
- }
- }
-
dvdnav_get_highlight(priv, 1);
break;
}
diff --git a/stream/stream_dvdnav.h b/stream/stream_dvdnav.h
index cc8163e015..e27af6eb1e 100644
--- a/stream/stream_dvdnav.h
+++ b/stream/stream_dvdnav.h
@@ -40,11 +40,9 @@ enum mp_nav_event_type {
struct mp_nav_event {
enum mp_nav_event_type event;
union {
- /*
struct {
- int seconds;
+ int seconds; // -1: infinite
} still_frame;
- */
struct {
int display;
int sx, sy, ex, ey;
@@ -62,6 +60,7 @@ enum mp_nav_cmd_type {
MP_NAV_CMD_ENABLE, // enable interactive navigation
MP_NAV_CMD_DRAIN_OK, // acknowledge EVENT_DRAIN
MP_NAV_CMD_RESUME,
+ MP_NAV_CMD_SKIP_STILL, // after showing the frame in EVENT_STILL_FRAME
MP_NAV_CMD_MENU,
MP_NAV_CMD_MOUSE_POS,
};