summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/man/en/options.rst14
-rw-r--r--mpvcore/mplayer.c91
-rw-r--r--mpvcore/options.c1
-rw-r--r--mpvcore/options.h1
-rw-r--r--mpvcore/screenshot.c6
-rw-r--r--video/decode/vd_lavc.c1
-rw-r--r--video/out/vo.c5
-rw-r--r--video/out/vo.h1
8 files changed, 103 insertions, 17 deletions
diff --git a/DOCS/man/en/options.rst b/DOCS/man/en/options.rst
index 9230529d54..cc0b7a4db2 100644
--- a/DOCS/man/en/options.rst
+++ b/DOCS/man/en/options.rst
@@ -804,6 +804,20 @@
depending on GPU drivers and hardware. For other VOs, this just makes
rendering slower.
+``--force-window``
+ Create a video output window even if there is no video. This can be useful
+ when pretending that mpv is a GUI application. Currently, the window
+ always has the size 640x480, and is subject to ``--geometry``,
+ ``--autofit``, and similar options.
+
+ .. warning::
+
+ The window is created only after initialization (to make sure default
+ window placement still works if the video size is different from the
+ ``--force-window`` default window size). This can be a problem if
+ initialization doesn't work perfectly, such as when opening URLs with
+ bad network connection, or opening broken video files.
+
``--force-window-position``
Forcefully move mpv's video output window to default location whenever
there is a change in video parameters, video stream or file. This used to
diff --git a/mpvcore/mplayer.c b/mpvcore/mplayer.c
index 280cc87f3e..98af9d4e37 100644
--- a/mpvcore/mplayer.c
+++ b/mpvcore/mplayer.c
@@ -1556,7 +1556,7 @@ static void update_osd_msg(struct MPContext *mpctx)
// Look if we have a msg
mp_osd_msg_t *msg = get_osd_msg(mpctx);
if (msg && !msg->show_position) {
- if (mpctx->sh_video && opts->term_osd != 1) {
+ if (mpctx->video_out && opts->term_osd != 1) {
osd_set_text(osd, msg->msg);
} else if (opts->term_osd) {
if (strcmp(mpctx->terminal_osd_text, msg->msg)) {
@@ -1576,7 +1576,7 @@ static void update_osd_msg(struct MPContext *mpctx)
if (msg && msg->show_position)
osd_level = 3;
- if (mpctx->sh_video && opts->term_osd != 1) {
+ if (mpctx->video_out && opts->term_osd != 1) {
// fallback on the timer
char *text = NULL;
@@ -2031,8 +2031,10 @@ void mp_switch_track(struct MPContext *mpctx, enum stream_type type,
return;
if (type == STREAM_VIDEO) {
- uninit_player(mpctx, INITIALIZED_VCODEC |
- (mpctx->opts->fixed_vo && track ? 0 : INITIALIZED_VO));
+ int uninit = INITIALIZED_VCODEC;
+ if (!mpctx->opts->force_vo)
+ uninit |= mpctx->opts->fixed_vo && track ? 0 : INITIALIZED_VO;
+ uninit_player(mpctx, uninit);
} else if (type == STREAM_AUDIO) {
uninit_player(mpctx, INITIALIZED_AO | INITIALIZED_ACODEC);
} else if (type == STREAM_SUB) {
@@ -2380,7 +2382,8 @@ int reinit_video_chain(struct MPContext *mpctx)
init_demux_stream(mpctx, STREAM_VIDEO);
sh_video_t *sh_video = mpctx->sh_video;
if (!sh_video) {
- uninit_player(mpctx, INITIALIZED_VO);
+ if (!opts->force_vo)
+ uninit_player(mpctx, INITIALIZED_VO);
goto no_video;
}
@@ -2453,7 +2456,8 @@ int reinit_video_chain(struct MPContext *mpctx)
return 1;
err_out:
- uninit_player(mpctx, INITIALIZED_VO);
+ if (!opts->force_vo)
+ uninit_player(mpctx, INITIALIZED_VO);
cleanup_demux_stream(mpctx, STREAM_VIDEO);
no_video:
mpctx->current_track[STREAM_VIDEO] = NULL;
@@ -3528,6 +3532,41 @@ static void handle_keep_open(struct MPContext *mpctx)
}
}
+// Execute a forceful refresh of the VO window, if it hasn't had a valid frame
+// for a while. The problem is that a VO with no valid frame (vo->hasframe==0)
+// doesn't redraw video and doesn't OSD interaction. So screw it, hard.
+static void handle_force_window(struct MPContext *mpctx)
+{
+ // Don't interfere with real video playback
+ if (mpctx->sh_video)
+ return;
+
+ struct vo *vo = mpctx->video_out;
+ if (!vo)
+ return;
+
+ if (!vo->config_ok) {
+ MP_INFO(mpctx, "Creating non-video VO window.\n");
+ // Pick whatever works
+ int config_format = 0;
+ for (int fmt = IMGFMT_START; fmt < IMGFMT_END; fmt++) {
+ if (vo->driver->query_format(vo, fmt)) {
+ config_format = fmt;
+ break;
+ }
+ }
+ int w = 640;
+ int h = 480;
+ struct mp_image_params p = {
+ .imgfmt = config_format,
+ .w = w, .h = h,
+ .d_w = w, .d_h = h,
+ };
+ vo_reconfig(vo, &p, 0);
+ redraw_osd(mpctx);
+ }
+}
+
static double get_wakeup_period(struct MPContext *mpctx)
{
/* Even if we can immediately wake up in response to most input events,
@@ -3593,6 +3632,11 @@ static void run_playloop(struct MPContext *mpctx)
audio_left = status > -2;
}
+ if (mpctx->video_out) {
+ vo_check_events(mpctx->video_out);
+ handle_cursor_autohide(mpctx);
+ }
+
double buffered_audio = -1;
while (mpctx->sh_video) { // never loops, for "break;" only
struct vo *vo = mpctx->video_out;
@@ -3606,12 +3650,16 @@ static void run_playloop(struct MPContext *mpctx)
mp_tmsg(MSGT_CPLAYER, MSGL_FATAL,
"\nFATAL: Could not initialize video filters (-vf) "
"or video output (-vo).\n");
- uninit_player(mpctx, INITIALIZED_VCODEC | INITIALIZED_VO);
+ int uninit = INITIALIZED_VCODEC;
+ if (!opts->force_vo)
+ uninit |= INITIALIZED_VO;
+ uninit_player(mpctx, uninit);
cleanup_demux_stream(mpctx, STREAM_VIDEO);
mpctx->current_track[STREAM_VIDEO] = NULL;
if (!mpctx->current_track[STREAM_AUDIO])
mpctx->stop_play = PT_NEXT_ENTRY;
mpctx->error_playing = true;
+ handle_force_window(mpctx);
break;
}
video_left = frame_time >= 0;
@@ -3628,11 +3676,6 @@ static void run_playloop(struct MPContext *mpctx)
if (endpts != MP_NOPTS_VALUE)
video_left &= mpctx->sh_video->pts < endpts;
- // ================================================================
- vo_check_events(vo);
-
- handle_cursor_autohide(mpctx);
-
handle_heartbeat_cmd(mpctx);
if (!video_left || (mpctx->paused && !mpctx->restart_playback))
@@ -3857,7 +3900,7 @@ static void run_playloop(struct MPContext *mpctx)
audio_sleep = 0.020;
}
sleeptime = FFMIN(sleeptime, audio_sleep);
- if (sleeptime > 0 && mpctx->sh_video) {
+ if (sleeptime > 0 && mpctx->video_out && mpctx->video_out->config_ok) {
bool want_redraw = vo_get_want_redraw(mpctx->video_out);
if (mpctx->video_out->driver->draw_osd)
want_redraw |= mpctx->osd->want_redraw;
@@ -3888,6 +3931,8 @@ static void run_playloop(struct MPContext *mpctx)
handle_keep_open(mpctx);
+ handle_force_window(mpctx);
+
execute_queued_seek(mpctx);
}
@@ -4227,7 +4272,11 @@ static void idle_loop(struct MPContext *mpctx)
while (mpctx->opts->player_idle_mode && !mpctx->playlist->current
&& mpctx->stop_play != PT_QUIT)
{
- uninit_player(mpctx, INITIALIZED_AO | INITIALIZED_VO);
+ int uninit = INITIALIZED_AO;
+ if (!mpctx->opts->force_vo)
+ uninit |= INITIALIZED_VO;
+ uninit_player(mpctx, uninit);
+ handle_force_window(mpctx);
mp_cmd_t *cmd;
while (!(cmd = mp_input_get_cmd(mpctx->input,
get_wakeup_period(mpctx) * 1000,
@@ -4925,6 +4974,7 @@ static int mpv_main(int argc, char *argv[])
m_config_set_option0(mpctx->mconfig, "vo", "lavc");
m_config_set_option0(mpctx->mconfig, "ao", "lavc");
m_config_set_option0(mpctx->mconfig, "fixed-vo", "yes");
+ m_config_set_option0(mpctx->mconfig, "force-window", "no");
m_config_set_option0(mpctx->mconfig, "gapless-audio", "yes");
mp_input_enable_section(mpctx->input, "encode", MP_INPUT_EXCLUSIVE);
}
@@ -4936,6 +4986,19 @@ static int mpv_main(int argc, char *argv[])
mpctx->osd = osd_create(opts, mpctx->ass_library);
+ if (opts->force_vo) {
+ opts->fixed_vo = 1;
+ mpctx->video_out = init_best_video_out(mpctx->global, mpctx->input,
+ mpctx->encode_lavc_ctx);
+ if (!mpctx->video_out) {
+ mp_tmsg(MSGT_CPLAYER, MSGL_FATAL, "Error opening/initializing "
+ "the selected video_out (-vo) device.\n");
+ exit_player(mpctx, EXIT_ERROR);
+ }
+ mpctx->mouse_cursor_visible = true;
+ mpctx->initialized_flags |= INITIALIZED_VO;
+ }
+
#ifdef CONFIG_LUA
// Lua user scripts can call arbitrary functions. Load them at a point
// where this is safe.
diff --git a/mpvcore/options.c b/mpvcore/options.c
index 234d8646bd..b0988bd6e2 100644
--- a/mpvcore/options.c
+++ b/mpvcore/options.c
@@ -567,6 +567,7 @@ const m_option_t mp_opts[] = {
OPT_SETTINGSLIST("vo", vo.video_driver_list, 0, &vo_obj_list),
OPT_SETTINGSLIST("ao", audio_driver_list, 0, &ao_obj_list),
OPT_FLAG("fixed-vo", fixed_vo, CONF_GLOBAL),
+ OPT_FLAG("force-window", force_vo, CONF_GLOBAL),
OPT_FLAG("ontop", vo.ontop, 0),
OPT_FLAG("border", vo.border, 0),
diff --git a/mpvcore/options.h b/mpvcore/options.h
index fb88456ac9..0f3fa51549 100644
--- a/mpvcore/options.h
+++ b/mpvcore/options.h
@@ -50,6 +50,7 @@ typedef struct MPOpts {
struct m_obj_settings *audio_driver_list;
int fixed_vo;
+ int force_vo;
int softvol;
float mixer_init_volume;
int mixer_init_mute;
diff --git a/mpvcore/screenshot.c b/mpvcore/screenshot.c
index 161bfac1e5..181292474b 100644
--- a/mpvcore/screenshot.c
+++ b/mpvcore/screenshot.c
@@ -316,8 +316,10 @@ static struct mp_image *screenshot_get(struct MPContext *mpctx, int mode)
struct voctrl_screenshot_args args =
{ .full_window = (mode == MODE_FULL_WINDOW) };
- struct vf_instance *vfilter = mpctx->sh_video->vfilter;
- vfilter->control(vfilter, VFCTRL_SCREENSHOT, &args);
+ if (mpctx->sh_video && mpctx->sh_video->vfilter) {
+ struct vf_instance *vfilter = mpctx->sh_video->vfilter;
+ vfilter->control(vfilter, VFCTRL_SCREENSHOT, &args);
+ }
if (!args.out_image)
vo_control(mpctx->video_out, VOCTRL_SCREENSHOT, &args);
diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c
index 86c1c92541..6f395ea843 100644
--- a/video/decode/vd_lavc.c
+++ b/video/decode/vd_lavc.c
@@ -778,7 +778,6 @@ static struct mp_image *decode_with_fallback(struct sh_video *sh,
// Failed hardware decoding? Try again in software.
if (ctx->software_fallback_decoder) {
uninit_avctx(sh);
- sh->vf_initialized = 0;
mp_tmsg(MSGT_DECVIDEO, MSGL_ERR, "Error using hardware "
"decoding, falling back to software decoding.\n");
const char *decoder = ctx->software_fallback_decoder;
diff --git a/video/out/vo.c b/video/out/vo.c
index a069c442df..0dc60a558d 100644
--- a/video/out/vo.c
+++ b/video/out/vo.c
@@ -406,6 +406,9 @@ int vo_reconfig(struct vo *vo, struct mp_image_params *params, int flags)
vo->dwidth = d_width;
vo->dheight = d_height;
+ talloc_free(vo->params);
+ vo->params = NULL;
+
struct mp_image_params p2 = *params;
int ret;
@@ -419,6 +422,8 @@ int vo_reconfig(struct vo *vo, struct mp_image_params *params, int flags)
}
vo->config_ok = (ret >= 0);
vo->config_count += vo->config_ok;
+ if (vo->config_ok)
+ vo->params = talloc_memdup(vo, &p2, sizeof(p2));
if (vo->registered_fd == -1 && vo->event_fd != -1 && vo->config_ok) {
mp_input_add_key_fd(vo->input_ctx, vo->event_fd, 1, event_fd_callback,
NULL, vo);
diff --git a/video/out/vo.h b/video/out/vo.h
index 50e83d2809..3b6adddb0c 100644
--- a/video/out/vo.h
+++ b/video/out/vo.h
@@ -238,6 +238,7 @@ struct vo {
struct mp_log *log; // Using e.g. "[vo/vdpau]" as prefix
int config_ok; // Last config call was successful?
int config_count; // Total number of successful config calls
+ struct mp_image_params *params; // Configured parameters (as in vo_reconfig)
bool probing;