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, };