From fb47f2f9402567eb7ecda7e5ec83e0c1915632c1 Mon Sep 17 00:00:00 2001 From: xylosper Date: Sun, 30 Mar 2014 11:42:49 +0900 Subject: player: rename dvdnav to discnav Now, navigation works both of DVD and non-BD-J Blu-ray. Therefore, rename all 'dvdnav' strings which are not DVD specific to 'discnav' --- player/command.c | 2 +- player/core.h | 2 +- player/discnav.c | 303 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ player/dvdnav.c | 303 ------------------------------------------------------- 4 files changed, 305 insertions(+), 305 deletions(-) create mode 100644 player/discnav.c delete mode 100644 player/dvdnav.c (limited to 'player') diff --git a/player/command.c b/player/command.c index dd9bf9e45d..f3b621152a 100644 --- a/player/command.c +++ b/player/command.c @@ -3333,7 +3333,7 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd) mp_input_disable_section(mpctx->input, cmd->args[0].v.s); break; - case MP_CMD_DVDNAV: + case MP_CMD_DISCNAV: mp_nav_user_input(mpctx, cmd->args[0].v.s); break; diff --git a/player/core.h b/player/core.h index 55c526b4cc..1d16a0e005 100644 --- a/player/core.h +++ b/player/core.h @@ -371,7 +371,7 @@ void mp_write_watch_later_conf(struct MPContext *mpctx); struct playlist_entry *mp_check_playlist_resume(struct MPContext *mpctx, struct playlist *playlist); -// dvdnav.c +// discnav.c void mp_nav_init(struct MPContext *mpctx); void mp_nav_reset(struct MPContext *mpctx); void mp_nav_destroy(struct MPContext *mpctx); diff --git a/player/discnav.c b/player/discnav.c new file mode 100644 index 0000000000..990f882d87 --- /dev/null +++ b/player/discnav.c @@ -0,0 +1,303 @@ +/* + * This file is part of mpv. + * + * mpv is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpv is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with mpv. If not, see . + */ + +#include +#include + +#include "core.h" + +#include "common/msg.h" +#include "common/common.h" +#include "input/input.h" + +#include "stream/discnav.h" + +#include "sub/dec_sub.h" +#include "sub/osd.h" + +#include "video/mp_image.h" +#include "video/decode/dec_video.h" + +struct mp_nav_state { + struct mp_log *log; + + int nav_still_frame; + bool nav_eof; + bool nav_menu; + bool nav_draining; + + // Accessed by OSD (possibly separate thread) + int hi_visible; + int highlight[4]; // x0 y0 x1 y1 + int vidsize[2]; + int subsize[2]; + struct sub_bitmap *hi_elem; + struct sub_bitmap *overlays[2]; + struct sub_bitmap outputs[3]; +}; + +static inline bool is_valid_size(int size[2]) { + return size[0] >= 1 && size[1] >= 1; +} + +static void update_resolution(struct MPContext *mpctx) { + struct mp_nav_state *nav = mpctx->nav_state; + if (!nav) + return; + if (mpctx->d_sub[0]) + sub_control(mpctx->d_sub[0], SD_CTRL_GET_RESOLUTION, nav->vidsize); + if (!is_valid_size(nav->vidsize)) { + struct mp_image_params vid = {0}; + if (mpctx->d_video) + vid = mpctx->d_video->decoder_output; + nav->vidsize[0] = vid.w; + nav->vidsize[1] = vid.h; + } +} + +// Allocate state and enable navigation features. Must happen before +// initializing cache, because the cache would read data. Since stream_dvdnav is +// in a mode which skips all transitions on reading data (before enabling +// navigation), this would skip some menu screens. +void mp_nav_init(struct MPContext *mpctx) +{ + assert(!mpctx->nav_state); + + // dvdnav is interactive + if (mpctx->encode_lavc_ctx) + return; + + struct mp_nav_cmd inp = {MP_NAV_CMD_ENABLE}; + if (stream_control(mpctx->stream, STREAM_CTRL_NAV_CMD, &inp) < 1) + return; + + mpctx->nav_state = talloc_zero(NULL, struct mp_nav_state); + mpctx->nav_state->log = mp_log_new(mpctx->nav_state, mpctx->log, "discnav"); + + MP_VERBOSE(mpctx->nav_state, "enabling\n"); + + mp_input_enable_section(mpctx->input, "discnav", 0); + mp_input_set_section_mouse_area(mpctx->input, "discnav-menu", + INT_MIN, INT_MIN, INT_MAX, INT_MAX); +} + +void mp_nav_reset(struct MPContext *mpctx) +{ + struct mp_nav_state *nav = mpctx->nav_state; + if (!nav) + return; + struct mp_nav_cmd inp = {MP_NAV_CMD_RESUME}; + stream_control(mpctx->stream, STREAM_CTRL_NAV_CMD, &inp); + osd_set_nav_highlight(mpctx->osd, NULL); + nav->hi_visible = 0; + nav->nav_menu = false; + nav->nav_draining = false; + nav->nav_still_frame = 0; + mp_input_disable_section(mpctx->input, "discnav-menu"); + // Prevent demuxer init code to seek to the "start" + mpctx->stream->start_pos = stream_tell(mpctx->stream); + stream_control(mpctx->stream, STREAM_CTRL_RESUME_CACHE, NULL); +} + +void mp_nav_destroy(struct MPContext *mpctx) +{ + osd_set_nav_highlight(mpctx->osd, NULL); + if (!mpctx->nav_state) + return; + mp_input_disable_section(mpctx->input, "discnav"); + mp_input_disable_section(mpctx->input, "discnav-menu"); + talloc_free(mpctx->nav_state); + mpctx->nav_state = NULL; +} + +void mp_nav_user_input(struct MPContext *mpctx, char *command) +{ + struct mp_nav_state *nav = mpctx->nav_state; + if (!nav) + return; + if (strcmp(command, "mouse_move") == 0) { + struct mp_image_params vid = {0}; + if (mpctx->d_video) + vid = mpctx->d_video->decoder_output; + struct mp_nav_cmd inp = {MP_NAV_CMD_MOUSE_POS}; + int x, y; + mp_input_get_mouse_pos(mpctx->input, &x, &y); + osd_coords_to_video(mpctx->osd, vid.w, vid.h, &x, &y); + inp.u.mouse_pos.x = x; + inp.u.mouse_pos.y = y; + stream_control(mpctx->stream, STREAM_CTRL_NAV_CMD, &inp); + } else { + struct mp_nav_cmd inp = {MP_NAV_CMD_MENU}; + inp.u.menu.action = command; + stream_control(mpctx->stream, STREAM_CTRL_NAV_CMD, &inp); + } +} + +void mp_handle_nav(struct MPContext *mpctx) +{ + struct mp_nav_state *nav = mpctx->nav_state; + if (!nav) + return; + while (1) { + struct mp_nav_event *ev = NULL; + stream_control(mpctx->stream, STREAM_CTRL_GET_NAV_EVENT, &ev); + if (!ev) + break; + switch (ev->event) { + case MP_NAV_EVENT_DRAIN: { + nav->nav_draining = true; + MP_VERBOSE(nav, "drain requested\n"); + break; + } + case MP_NAV_EVENT_RESET_ALL: { + mpctx->stop_play = PT_RELOAD_DEMUXER; + MP_VERBOSE(nav, "reload\n"); + // return immediately. + // other events should be handled after reloaded. + talloc_free(ev); + return; + } + 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) { + mp_input_enable_section(mpctx->input, "discnav-menu", + MP_INPUT_ON_TOP); + } else { + mp_input_disable_section(mpctx->input, "discnav-menu"); + } + break; + case MP_NAV_EVENT_HIGHLIGHT: { + MP_VERBOSE(nav, "highlight: %d %d %d - %d %d\n", + ev->u.highlight.display, + ev->u.highlight.sx, ev->u.highlight.sy, + ev->u.highlight.ex, ev->u.highlight.ey); + osd_set_nav_highlight(mpctx->osd, NULL); + nav->highlight[0] = ev->u.highlight.sx; + nav->highlight[1] = ev->u.highlight.sy; + nav->highlight[2] = ev->u.highlight.ex; + nav->highlight[3] = ev->u.highlight.ey; + nav->hi_visible = ev->u.highlight.display; + update_resolution(mpctx); + osd_set_nav_highlight(mpctx->osd, mpctx); + break; + } + case MP_NAV_EVENT_OVERLAY: { + osd_set_nav_highlight(mpctx->osd, NULL); + for (int i = 0; i < 2; i++) { + if (nav->overlays[i]) + talloc_free(nav->overlays[i]); + nav->overlays[i] = talloc_steal(nav, ev->u.overlay.images[i]); + } + update_resolution(mpctx); + osd_set_nav_highlight(mpctx->osd, mpctx); + break; + } + default: ; // ignore + } + 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}; + stream_control(mpctx->stream, STREAM_CTRL_NAV_CMD, &inp); + nav->nav_draining = false; + stream_control(mpctx->stream, STREAM_CTRL_RESUME_CACHE, NULL); + } + // E.g. keep displaying still frames + if (mpctx->stop_play == AT_END_OF_FILE && !nav->nav_eof) + mpctx->stop_play = KEEP_PLAYING; +} + +// Render "fake" highlights, because using actual dvd sub highlight elements +// is too hard, and would require extra libavcodec to begin with. +// Note: a proper solution would introduce something like +// SD_CTRL_APPLY_DVDNAV, which would crop the vobsub frame, +// and apply the current CLUT. +void mp_nav_get_highlight(void *priv, struct mp_osd_res res, + struct sub_bitmaps *out_imgs) +{ + struct MPContext *mpctx = priv; + struct mp_nav_state *nav = mpctx ? mpctx->nav_state : NULL; + if (!nav) + return; + struct sub_bitmap *sub = nav->hi_elem; + if (!sub) + sub = talloc_zero(nav, struct sub_bitmap); + + nav->hi_elem = sub; + if (!is_valid_size(nav->vidsize)) { + update_resolution(mpctx); + if (!is_valid_size(nav->vidsize)) + return; + } + int sizes[2] = {nav->vidsize[0], nav->vidsize[1]}; + if (sizes[0] != nav->subsize[0] || sizes[1] != nav->subsize[1]) { + talloc_free(sub->bitmap); + sub->bitmap = talloc_array(sub, uint32_t, sizes[0] * sizes[1]); + memset(sub->bitmap, 0x80, talloc_get_size(sub->bitmap)); + nav->subsize[0] = sizes[0]; + nav->subsize[1] = sizes[1]; + } + + out_imgs->num_parts = 0; + + if (nav->hi_visible) { + sub->x = nav->highlight[0]; + sub->y = nav->highlight[1]; + sub->w = MPCLAMP(nav->highlight[2] - sub->x, 0, sizes[0]); + sub->h = MPCLAMP(nav->highlight[3] - sub->y, 0, sizes[1]); + sub->stride = sub->w * 4; + if (sub->w > 0 && sub->h > 0) + nav->outputs[out_imgs->num_parts++] = *sub; + } + + if (nav->overlays[0]) + nav->outputs[out_imgs->num_parts++] = *nav->overlays[0]; + if (nav->overlays[1]) + nav->outputs[out_imgs->num_parts++] = *nav->overlays[1]; + + if (out_imgs->num_parts) { + out_imgs->parts = nav->outputs; + out_imgs->format = SUBBITMAP_RGBA; + osd_rescale_bitmaps(out_imgs, sizes[0], sizes[1], res, -1); + } +} diff --git a/player/dvdnav.c b/player/dvdnav.c deleted file mode 100644 index ecd141ceef..0000000000 --- a/player/dvdnav.c +++ /dev/null @@ -1,303 +0,0 @@ -/* - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * mpv is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with mpv. If not, see . - */ - -#include -#include - -#include "core.h" - -#include "common/msg.h" -#include "common/common.h" -#include "input/input.h" - -#include "stream/stream_dvdnav.h" - -#include "sub/dec_sub.h" -#include "sub/osd.h" - -#include "video/mp_image.h" -#include "video/decode/dec_video.h" - -struct mp_nav_state { - struct mp_log *log; - - int nav_still_frame; - bool nav_eof; - bool nav_menu; - bool nav_draining; - - // Accessed by OSD (possibly separate thread) - int hi_visible; - int highlight[4]; // x0 y0 x1 y1 - int vidsize[2]; - int subsize[2]; - struct sub_bitmap *hi_elem; - struct sub_bitmap *overlays[2]; - struct sub_bitmap outputs[3]; -}; - -static inline bool is_valid_size(int size[2]) { - return size[0] >= 1 && size[1] >= 1; -} - -static void update_resolution(struct MPContext *mpctx) { - struct mp_nav_state *nav = mpctx->nav_state; - if (!nav) - return; - if (mpctx->d_sub[0]) - sub_control(mpctx->d_sub[0], SD_CTRL_GET_RESOLUTION, nav->vidsize); - if (!is_valid_size(nav->vidsize)) { - struct mp_image_params vid = {0}; - if (mpctx->d_video) - vid = mpctx->d_video->decoder_output; - nav->vidsize[0] = vid.w; - nav->vidsize[1] = vid.h; - } -} - -// Allocate state and enable navigation features. Must happen before -// initializing cache, because the cache would read data. Since stream_dvdnav is -// in a mode which skips all transitions on reading data (before enabling -// navigation), this would skip some menu screens. -void mp_nav_init(struct MPContext *mpctx) -{ - assert(!mpctx->nav_state); - - // dvdnav is interactive - if (mpctx->encode_lavc_ctx) - return; - - struct mp_nav_cmd inp = {MP_NAV_CMD_ENABLE}; - if (stream_control(mpctx->stream, STREAM_CTRL_NAV_CMD, &inp) < 1) - return; - - mpctx->nav_state = talloc_zero(NULL, struct mp_nav_state); - mpctx->nav_state->log = mp_log_new(mpctx->nav_state, mpctx->log, "dvdnav"); - - MP_VERBOSE(mpctx->nav_state, "enabling\n"); - - mp_input_enable_section(mpctx->input, "dvdnav", 0); - mp_input_set_section_mouse_area(mpctx->input, "dvdnav-menu", - INT_MIN, INT_MIN, INT_MAX, INT_MAX); -} - -void mp_nav_reset(struct MPContext *mpctx) -{ - struct mp_nav_state *nav = mpctx->nav_state; - if (!nav) - return; - struct mp_nav_cmd inp = {MP_NAV_CMD_RESUME}; - stream_control(mpctx->stream, STREAM_CTRL_NAV_CMD, &inp); - osd_set_nav_highlight(mpctx->osd, NULL); - 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); - stream_control(mpctx->stream, STREAM_CTRL_RESUME_CACHE, NULL); -} - -void mp_nav_destroy(struct MPContext *mpctx) -{ - osd_set_nav_highlight(mpctx->osd, NULL); - if (!mpctx->nav_state) - return; - mp_input_disable_section(mpctx->input, "dvdnav"); - mp_input_disable_section(mpctx->input, "dvdnav-menu"); - talloc_free(mpctx->nav_state); - mpctx->nav_state = NULL; -} - -void mp_nav_user_input(struct MPContext *mpctx, char *command) -{ - struct mp_nav_state *nav = mpctx->nav_state; - if (!nav) - return; - if (strcmp(command, "mouse_move") == 0) { - struct mp_image_params vid = {0}; - if (mpctx->d_video) - vid = mpctx->d_video->decoder_output; - struct mp_nav_cmd inp = {MP_NAV_CMD_MOUSE_POS}; - int x, y; - mp_input_get_mouse_pos(mpctx->input, &x, &y); - osd_coords_to_video(mpctx->osd, vid.w, vid.h, &x, &y); - inp.u.mouse_pos.x = x; - inp.u.mouse_pos.y = y; - stream_control(mpctx->stream, STREAM_CTRL_NAV_CMD, &inp); - } else { - struct mp_nav_cmd inp = {MP_NAV_CMD_MENU}; - inp.u.menu.action = command; - stream_control(mpctx->stream, STREAM_CTRL_NAV_CMD, &inp); - } -} - -void mp_handle_nav(struct MPContext *mpctx) -{ - struct mp_nav_state *nav = mpctx->nav_state; - if (!nav) - return; - while (1) { - struct mp_nav_event *ev = NULL; - stream_control(mpctx->stream, STREAM_CTRL_GET_NAV_EVENT, &ev); - if (!ev) - break; - switch (ev->event) { - case MP_NAV_EVENT_DRAIN: { - nav->nav_draining = true; - MP_VERBOSE(nav, "drain requested\n"); - break; - } - case MP_NAV_EVENT_RESET_ALL: { - mpctx->stop_play = PT_RELOAD_DEMUXER; - MP_VERBOSE(nav, "reload\n"); - // return immediately. - // other events should be handled after reloaded. - talloc_free(ev); - return; - } - 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) { - mp_input_enable_section(mpctx->input, "dvdnav-menu", - MP_INPUT_ON_TOP); - } else { - mp_input_disable_section(mpctx->input, "dvdnav-menu"); - } - break; - case MP_NAV_EVENT_HIGHLIGHT: { - MP_VERBOSE(nav, "highlight: %d %d %d - %d %d\n", - ev->u.highlight.display, - ev->u.highlight.sx, ev->u.highlight.sy, - ev->u.highlight.ex, ev->u.highlight.ey); - osd_set_nav_highlight(mpctx->osd, NULL); - nav->highlight[0] = ev->u.highlight.sx; - nav->highlight[1] = ev->u.highlight.sy; - nav->highlight[2] = ev->u.highlight.ex; - nav->highlight[3] = ev->u.highlight.ey; - nav->hi_visible = ev->u.highlight.display; - update_resolution(mpctx); - osd_set_nav_highlight(mpctx->osd, mpctx); - break; - } - case MP_NAV_EVENT_OVERLAY: { - osd_set_nav_highlight(mpctx->osd, NULL); - for (int i = 0; i < 2; i++) { - if (nav->overlays[i]) - talloc_free(nav->overlays[i]); - nav->overlays[i] = talloc_steal(nav, ev->u.overlay.images[i]); - } - update_resolution(mpctx); - osd_set_nav_highlight(mpctx->osd, mpctx); - break; - } - default: ; // ignore - } - 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}; - stream_control(mpctx->stream, STREAM_CTRL_NAV_CMD, &inp); - nav->nav_draining = false; - stream_control(mpctx->stream, STREAM_CTRL_RESUME_CACHE, NULL); - } - // E.g. keep displaying still frames - if (mpctx->stop_play == AT_END_OF_FILE && !nav->nav_eof) - mpctx->stop_play = KEEP_PLAYING; -} - -// Render "fake" highlights, because using actual dvd sub highlight elements -// is too hard, and would require extra libavcodec to begin with. -// Note: a proper solution would introduce something like -// SD_CTRL_APPLY_DVDNAV, which would crop the vobsub frame, -// and apply the current CLUT. -void mp_nav_get_highlight(void *priv, struct mp_osd_res res, - struct sub_bitmaps *out_imgs) -{ - struct MPContext *mpctx = priv; - struct mp_nav_state *nav = mpctx ? mpctx->nav_state : NULL; - if (!nav) - return; - struct sub_bitmap *sub = nav->hi_elem; - if (!sub) - sub = talloc_zero(nav, struct sub_bitmap); - - nav->hi_elem = sub; - if (!is_valid_size(nav->vidsize)) { - update_resolution(mpctx); - if (!is_valid_size(nav->vidsize)) - return; - } - int sizes[2] = {nav->vidsize[0], nav->vidsize[1]}; - if (sizes[0] != nav->subsize[0] || sizes[1] != nav->subsize[1]) { - talloc_free(sub->bitmap); - sub->bitmap = talloc_array(sub, uint32_t, sizes[0] * sizes[1]); - memset(sub->bitmap, 0x80, talloc_get_size(sub->bitmap)); - nav->subsize[0] = sizes[0]; - nav->subsize[1] = sizes[1]; - } - - out_imgs->num_parts = 0; - - if (nav->hi_visible) { - sub->x = nav->highlight[0]; - sub->y = nav->highlight[1]; - sub->w = MPCLAMP(nav->highlight[2] - sub->x, 0, sizes[0]); - sub->h = MPCLAMP(nav->highlight[3] - sub->y, 0, sizes[1]); - sub->stride = sub->w * 4; - if (sub->w > 0 && sub->h > 0) - nav->outputs[out_imgs->num_parts++] = *sub; - } - - if (nav->overlays[0]) - nav->outputs[out_imgs->num_parts++] = *nav->overlays[0]; - if (nav->overlays[1]) - nav->outputs[out_imgs->num_parts++] = *nav->overlays[1]; - - if (out_imgs->num_parts) { - out_imgs->parts = nav->outputs; - out_imgs->format = SUBBITMAP_RGBA; - osd_rescale_bitmaps(out_imgs, sizes[0], sizes[1], res, -1); - } -} -- cgit v1.2.3