mirror of https://github.com/mpv-player/mpv
dvdnav: crappy hack to respect timed still frames
Before this, they were displayed forever. Since some dvd screens seem not to allow escaping from the still frame using the menu, this could get you stuck forever.
This commit is contained in:
parent
653980ac3a
commit
9bd7601c6d
|
@ -35,7 +35,7 @@
|
||||||
struct mp_nav_state {
|
struct mp_nav_state {
|
||||||
struct mp_log *log;
|
struct mp_log *log;
|
||||||
|
|
||||||
bool nav_still_frame;
|
int nav_still_frame;
|
||||||
bool nav_eof;
|
bool nav_eof;
|
||||||
bool nav_menu;
|
bool nav_menu;
|
||||||
bool nav_draining;
|
bool nav_draining;
|
||||||
|
@ -81,6 +81,7 @@ void mp_nav_reset(struct MPContext *mpctx)
|
||||||
nav->hi_visible = 0;
|
nav->hi_visible = 0;
|
||||||
nav->nav_menu = false;
|
nav->nav_menu = false;
|
||||||
nav->nav_draining = false;
|
nav->nav_draining = false;
|
||||||
|
nav->nav_still_frame = 0;
|
||||||
mp_input_disable_section(mpctx->input, "dvdnav-menu");
|
mp_input_disable_section(mpctx->input, "dvdnav-menu");
|
||||||
// Prevent demuxer init code to seek to the "start"
|
// Prevent demuxer init code to seek to the "start"
|
||||||
mpctx->stream->start_pos = stream_tell(mpctx->stream);
|
mpctx->stream->start_pos = stream_tell(mpctx->stream);
|
||||||
|
@ -141,9 +142,20 @@ void mp_handle_nav(struct MPContext *mpctx)
|
||||||
MP_VERBOSE(nav, "reload\n");
|
MP_VERBOSE(nav, "reload\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case MP_NAV_EVENT_RESET: {
|
||||||
|
nav->nav_still_frame = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case MP_NAV_EVENT_EOF:
|
case MP_NAV_EVENT_EOF:
|
||||||
nav->nav_eof = true;
|
nav->nav_eof = true;
|
||||||
break;
|
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:
|
case MP_NAV_EVENT_MENU_MODE:
|
||||||
nav->nav_menu = ev->u.menu_mode.enable;
|
nav->nav_menu = ev->u.menu_mode.enable;
|
||||||
if (nav->nav_menu) {
|
if (nav->nav_menu) {
|
||||||
|
@ -169,6 +181,17 @@ void mp_handle_nav(struct MPContext *mpctx)
|
||||||
}
|
}
|
||||||
talloc_free(ev);
|
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) {
|
if (nav->nav_draining && mpctx->stop_play == AT_END_OF_FILE) {
|
||||||
MP_VERBOSE(nav, "execute drain\n");
|
MP_VERBOSE(nav, "execute drain\n");
|
||||||
struct mp_nav_cmd inp = {MP_NAV_CMD_DRAIN_OK};
|
struct mp_nav_cmd inp = {MP_NAV_CMD_DRAIN_OK};
|
||||||
|
|
|
@ -87,6 +87,7 @@ static char *mp_nav_cmd_types[] = {
|
||||||
DNE(MP_NAV_CMD_ENABLE),
|
DNE(MP_NAV_CMD_ENABLE),
|
||||||
DNE(MP_NAV_CMD_DRAIN_OK),
|
DNE(MP_NAV_CMD_DRAIN_OK),
|
||||||
DNE(MP_NAV_CMD_RESUME),
|
DNE(MP_NAV_CMD_RESUME),
|
||||||
|
DNE(MP_NAV_CMD_SKIP_STILL),
|
||||||
DNE(MP_NAV_CMD_MENU),
|
DNE(MP_NAV_CMD_MENU),
|
||||||
DNE(MP_NAV_CMD_MOUSE_POS),
|
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)
|
static void handle_menu_input(stream_t *stream, const char *cmd)
|
||||||
{
|
{
|
||||||
struct priv *priv = stream->priv;
|
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:
|
case MP_NAV_CMD_RESUME:
|
||||||
priv->suspended_read = false;
|
priv->suspended_read = false;
|
||||||
break;
|
break;
|
||||||
|
case MP_NAV_CMD_SKIP_STILL:
|
||||||
|
dvdnav_still_skip(priv->dvdnav);
|
||||||
|
break;
|
||||||
case MP_NAV_CMD_MENU:
|
case MP_NAV_CMD_MENU:
|
||||||
handle_menu_input(s, ev->u.menu.action);
|
handle_menu_input(s, ev->u.menu.action);
|
||||||
break;
|
break;
|
||||||
|
@ -319,6 +318,9 @@ static void fill_next_event(stream_t *s, struct mp_nav_event **ret)
|
||||||
case MP_NAV_EVENT_MENU_MODE:
|
case MP_NAV_EVENT_MENU_MODE:
|
||||||
e.u.menu_mode.enable = !dvdnav_is_domain_vts(priv->dvdnav);
|
e.u.menu_mode.enable = !dvdnav_is_domain_vts(priv->dvdnav);
|
||||||
break;
|
break;
|
||||||
|
case MP_NAV_EVENT_STILL_FRAME:
|
||||||
|
e.u.still_frame.seconds = priv->still_length;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -353,7 +355,7 @@ static int fill_buffer(stream_t *s, char *buf, int max_len)
|
||||||
event, dvdnav_err_to_string(dvdnav));
|
event, dvdnav_err_to_string(dvdnav));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (1||event != DVDNAV_BLOCK_OK) {
|
if (event != DVDNAV_BLOCK_OK) {
|
||||||
const char *name = LOOKUP_NAME(mp_dvdnav_events, event);
|
const char *name = LOOKUP_NAME(mp_dvdnav_events, event);
|
||||||
mp_msg(MSGT_CPLAYER, MSGL_V, "DVDNAV: event %s (%d).\n", name, event);
|
mp_msg(MSGT_CPLAYER, MSGL_V, "DVDNAV: event %s (%d).\n", name, event);
|
||||||
dvdnav_get_highlight(priv, 1);
|
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: {
|
case DVDNAV_STILL_FRAME: {
|
||||||
dvdnav_still_event_t *still_event = (dvdnav_still_event_t *) buf;
|
dvdnav_still_event_t *still_event = (dvdnav_still_event_t *) buf;
|
||||||
priv->still_length = still_event->length;
|
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);
|
mp_msg(MSGT_CPLAYER, MSGL_V, "len=%d\n", priv->still_length);
|
||||||
/* set still frame duration */
|
/* set still frame duration */
|
||||||
priv->duration = dvdnav_get_duration(priv->still_length);
|
|
||||||
if (priv->still_length <= 1) {
|
if (priv->still_length <= 1) {
|
||||||
pci_t *pnavpci = dvdnav_get_current_nav_pci(dvdnav);
|
pci_t *pnavpci = dvdnav_get_current_nav_pci(dvdnav);
|
||||||
priv->duration = mp_dvdtimetomsec(&pnavpci->pci_gi.e_eltm);
|
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: {
|
case DVDNAV_CELL_CHANGE: {
|
||||||
dvdnav_cell_change_event_t *ev = (dvdnav_cell_change_event_t *)buf;
|
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_RESET;
|
||||||
priv->next_event |= 1 << MP_NAV_EVENT_MENU_MODE;
|
priv->next_event |= 1 << MP_NAV_EVENT_MENU_MODE;
|
||||||
if (ev->pgc_length)
|
if (ev->pgc_length)
|
||||||
priv->duration = ev->pgc_length / 90;
|
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);
|
dvdnav_get_highlight(priv, 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,11 +40,9 @@ enum mp_nav_event_type {
|
||||||
struct mp_nav_event {
|
struct mp_nav_event {
|
||||||
enum mp_nav_event_type event;
|
enum mp_nav_event_type event;
|
||||||
union {
|
union {
|
||||||
/*
|
|
||||||
struct {
|
struct {
|
||||||
int seconds;
|
int seconds; // -1: infinite
|
||||||
} still_frame;
|
} still_frame;
|
||||||
*/
|
|
||||||
struct {
|
struct {
|
||||||
int display;
|
int display;
|
||||||
int sx, sy, ex, ey;
|
int sx, sy, ex, ey;
|
||||||
|
@ -62,6 +60,7 @@ enum mp_nav_cmd_type {
|
||||||
MP_NAV_CMD_ENABLE, // enable interactive navigation
|
MP_NAV_CMD_ENABLE, // enable interactive navigation
|
||||||
MP_NAV_CMD_DRAIN_OK, // acknowledge EVENT_DRAIN
|
MP_NAV_CMD_DRAIN_OK, // acknowledge EVENT_DRAIN
|
||||||
MP_NAV_CMD_RESUME,
|
MP_NAV_CMD_RESUME,
|
||||||
|
MP_NAV_CMD_SKIP_STILL, // after showing the frame in EVENT_STILL_FRAME
|
||||||
MP_NAV_CMD_MENU,
|
MP_NAV_CMD_MENU,
|
||||||
MP_NAV_CMD_MOUSE_POS,
|
MP_NAV_CMD_MOUSE_POS,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue