summaryrefslogtreecommitdiffstats
path: root/player
diff options
context:
space:
mode:
Diffstat (limited to 'player')
-rw-r--r--player/client.c15
-rw-r--r--player/command.c184
-rw-r--r--player/command.h3
-rw-r--r--player/configfiles.c14
-rw-r--r--player/core.h2
-rw-r--r--player/discnav.c23
-rw-r--r--player/lua.c21
-rw-r--r--player/lua/osc.lua12
-rw-r--r--player/playloop.c4
-rw-r--r--player/screenshot.c22
-rw-r--r--player/screenshot.h3
-rw-r--r--player/video.c30
12 files changed, 197 insertions, 136 deletions
diff --git a/player/client.c b/player/client.c
index 614d64205f..43c7c07c60 100644
--- a/player/client.c
+++ b/player/client.c
@@ -954,6 +954,7 @@ static int run_async(mpv_handle *ctx, void (*fn)(void *fn_data), void *fn_data)
struct cmd_request {
struct MPContext *mpctx;
struct mp_cmd *cmd;
+ struct mpv_node *res;
int status;
struct mpv_handle *reply_ctx;
uint64_t userdata;
@@ -962,7 +963,7 @@ struct cmd_request {
static void cmd_fn(void *data)
{
struct cmd_request *req = data;
- int r = run_command(req->mpctx, req->cmd);
+ int r = run_command(req->mpctx, req->cmd, req->res);
req->status = r >= 0 ? 0 : MPV_ERROR_COMMAND;
talloc_free(req->cmd);
if (req->reply_ctx) {
@@ -971,7 +972,7 @@ static void cmd_fn(void *data)
}
}
-static int run_client_command(mpv_handle *ctx, struct mp_cmd *cmd)
+static int run_client_command(mpv_handle *ctx, struct mp_cmd *cmd, mpv_node *res)
{
if (!ctx->mpctx->initialized)
return MPV_ERROR_UNINITIALIZED;
@@ -986,6 +987,7 @@ static int run_client_command(mpv_handle *ctx, struct mp_cmd *cmd)
struct cmd_request req = {
.mpctx = ctx->mpctx,
.cmd = cmd,
+ .res = res,
};
run_locked(ctx, cmd_fn, &req);
return req.status;
@@ -993,21 +995,22 @@ static int run_client_command(mpv_handle *ctx, struct mp_cmd *cmd)
int mpv_command(mpv_handle *ctx, const char **args)
{
- return run_client_command(ctx, mp_input_parse_cmd_strv(ctx->log, args));
+ return run_client_command(ctx, mp_input_parse_cmd_strv(ctx->log, args), NULL);
}
int mpv_command_node(mpv_handle *ctx, mpv_node *args, mpv_node *result)
{
- int r = run_client_command(ctx, mp_input_parse_cmd_node(ctx->log, args));
+ struct mpv_node rn = {.format = MPV_FORMAT_NONE};
+ int r = run_client_command(ctx, mp_input_parse_cmd_node(ctx->log, args), &rn);
if (result && r >= 0)
- *result = (mpv_node){.format = MPV_FORMAT_NONE};
+ *result = rn;
return r;
}
int mpv_command_string(mpv_handle *ctx, const char *args)
{
return run_client_command(ctx,
- mp_input_parse_cmd(ctx->mpctx->input, bstr0((char*)args), ctx->name));
+ mp_input_parse_cmd(ctx->mpctx->input, bstr0((char*)args), ctx->name), NULL);
}
static int run_cmd_async(mpv_handle *ctx, uint64_t ud, struct mp_cmd *cmd)
diff --git a/player/command.c b/player/command.c
index 88b3164436..3556986473 100644
--- a/player/command.c
+++ b/player/command.c
@@ -216,14 +216,6 @@ static void mark_seek(struct MPContext *mpctx)
cmd->last_seek_time = now;
}
-static char *format_bitrate(int rate)
-{
- if (rate < 1024 * 1024)
- return talloc_asprintf(NULL, "%.3f kbps", rate / 1000.0);
-
- return talloc_asprintf(NULL, "%.3f mbps", rate / 1000000.0);
-}
-
static char *format_file_size(int64_t size)
{
double s = size;
@@ -702,6 +694,14 @@ static int mp_property_disc_menu(void *ctx, struct m_property *prop,
return m_property_flag_ro(action, arg, !!state);
}
+static int mp_property_mouse_on_button(void *ctx, struct m_property *prop,
+ int action, void *arg)
+{
+ MPContext *mpctx = ctx;
+ bool on = mp_nav_mouse_on_button(mpctx);
+ return m_property_flag_ro(action, arg, on);
+}
+
/// Current chapter (RW)
static int mp_property_chapter(void *ctx, struct m_property *prop,
int action, void *arg)
@@ -1383,6 +1383,24 @@ static int mp_property_demuxer_cache_duration(void *ctx, struct m_property *prop
return m_property_double_ro(action, arg, s.ts_duration);
}
+static int mp_property_demuxer_cache_time(void *ctx, struct m_property *prop,
+ int action, void *arg)
+{
+ MPContext *mpctx = ctx;
+ if (!mpctx->demuxer)
+ return M_PROPERTY_UNAVAILABLE;
+
+ struct demux_ctrl_reader_state s;
+ if (demux_control(mpctx->demuxer, DEMUXER_CTRL_GET_READER_STATE, &s) < 1)
+ return M_PROPERTY_UNAVAILABLE;
+
+ double ts = s.ts_range[1];
+ if (ts == MP_NOPTS_VALUE)
+ return M_PROPERTY_UNAVAILABLE;
+
+ return m_property_double_ro(action, arg, ts);
+}
+
static int mp_property_demuxer_cache_idle(void *ctx, struct m_property *prop,
int action, void *arg)
{
@@ -1636,20 +1654,6 @@ static int mp_property_audio_codec(void *ctx, struct m_property *prop,
return m_property_strdup_ro(action, arg, c);
}
-/// Audio bitrate (RO)
-static int mp_property_audio_bitrate(void *ctx, struct m_property *prop,
- int action, void *arg)
-{
- MPContext *mpctx = ctx;
- if (!mpctx->d_audio)
- return M_PROPERTY_UNAVAILABLE;
- if (action == M_PROPERTY_PRINT) {
- *(char **)arg = format_bitrate(mpctx->d_audio->bitrate);
- return M_PROPERTY_OK;
- }
- return m_property_int_ro(action, arg, mpctx->d_audio->bitrate);
-}
-
/// Samplerate (RO)
static int mp_property_samplerate(void *ctx, struct m_property *prop,
int action, void *arg)
@@ -2329,21 +2333,6 @@ static int mp_property_video_codec(void *ctx, struct m_property *prop,
return m_property_strdup_ro(action, arg, c);
}
-
-/// Video bitrate (RO)
-static int mp_property_video_bitrate(void *ctx, struct m_property *prop,
- int action, void *arg)
-{
- MPContext *mpctx = ctx;
- if (!mpctx->d_video)
- return M_PROPERTY_UNAVAILABLE;
- if (action == M_PROPERTY_PRINT) {
- *(char **)arg = format_bitrate(mpctx->d_video->bitrate);
- return M_PROPERTY_OK;
- }
- return m_property_int_ro(action, arg, mpctx->d_video->bitrate);
-}
-
static int property_imgparams(struct mp_image_params p, int action, void *arg)
{
if (!p.imgfmt)
@@ -3022,7 +3011,8 @@ static int mp_property_packet_bitrate(void *ctx, struct m_property *prop,
int action, void *arg)
{
MPContext *mpctx = ctx;
- int type = (intptr_t)prop->priv;
+ int type = (uintptr_t)prop->priv & ~0x100;
+ bool old = (uintptr_t)prop->priv & 0x100;
if (!mpctx->demuxer)
return M_PROPERTY_UNAVAILABLE;
@@ -3031,8 +3021,23 @@ static int mp_property_packet_bitrate(void *ctx, struct m_property *prop,
if (demux_control(mpctx->demuxer, DEMUXER_CTRL_GET_BITRATE_STATS, &r) < 1)
return M_PROPERTY_UNAVAILABLE;
- // r[type] is in bytes/second -> kilobits
- return m_property_int64_ro(action, arg, r[type] * 8 / 1000.0 + 0.5);
+ // r[type] is in bytes/second -> bits
+ double rate = r[type] * 8;
+
+ // Same story, but used kilobits for some reason.
+ if (old)
+ return m_property_int64_ro(action, arg, rate / 1000.0 + 0.5);
+
+ if (action == M_PROPERTY_PRINT) {
+ rate /= 1000;
+ if (rate < 1000) {
+ *(char **)arg = talloc_asprintf(NULL, "%d kbps", (int)rate);
+ } else {
+ *(char **)arg = talloc_asprintf(NULL, "%.3f mbps", rate / 1000.0);
+ }
+ return M_PROPERTY_OK;
+ }
+ return m_property_int64_ro(action, arg, rate);
}
static int mp_property_cwd(void *ctx, struct m_property *prop,
@@ -3262,6 +3267,7 @@ static const struct m_property mp_properties[] = {
{"playback-time", mp_property_playback_time},
{"disc-title", mp_property_disc_title},
{"disc-menu-active", mp_property_disc_menu},
+ {"disc-mouse-on-button", mp_property_mouse_on_button},
{"chapter", mp_property_chapter},
{"edition", mp_property_edition},
{"disc-titles", mp_property_disc_titles},
@@ -3283,6 +3289,7 @@ static const struct m_property mp_properties[] = {
{"cache-size", mp_property_cache_size},
{"cache-idle", mp_property_cache_idle},
{"demuxer-cache-duration", mp_property_demuxer_cache_duration},
+ {"demuxer-cache-time", mp_property_demuxer_cache_time},
{"demuxer-cache-idle", mp_property_demuxer_cache_idle},
{"cache-buffering-state", mp_property_cache_buffering},
{"paused-for-cache", mp_property_paused_for_cache},
@@ -3308,7 +3315,6 @@ static const struct m_property mp_properties[] = {
{"audio-delay", mp_property_audio_delay},
{"audio-format", mp_property_audio_format},
{"audio-codec", mp_property_audio_codec},
- {"audio-bitrate", mp_property_audio_bitrate},
{"audio-samplerate", mp_property_samplerate},
{"audio-channels", mp_property_channels},
{"aid", mp_property_audio},
@@ -3343,7 +3349,6 @@ static const struct m_property mp_properties[] = {
{"video-params", mp_property_vd_imgparams},
{"video-format", mp_property_video_format},
{"video-codec", mp_property_video_codec},
- {"video-bitrate", mp_property_video_bitrate},
M_PROPERTY_ALIAS("dwidth", "video-out-params/dw"),
M_PROPERTY_ALIAS("dheight", "video-out-params/dh"),
M_PROPERTY_ALIAS("width", "video-params/w"),
@@ -3390,11 +3395,15 @@ static const struct m_property mp_properties[] = {
{"ab-loop-a", mp_property_ab_loop},
{"ab-loop-b", mp_property_ab_loop},
-#define PROPERTY_BITRATE(name, type) \
- {name, mp_property_packet_bitrate, (void *)(intptr_t)type}
- PROPERTY_BITRATE("packet-video-bitrate", STREAM_VIDEO),
- PROPERTY_BITRATE("packet-audio-bitrate", STREAM_AUDIO),
- PROPERTY_BITRATE("packet-sub-bitrate", STREAM_SUB),
+#define PROPERTY_BITRATE(name, old, type) \
+ {name, mp_property_packet_bitrate, (void *)(uintptr_t)((type)|(old?0x100:0))}
+ PROPERTY_BITRATE("packet-video-bitrate", true, STREAM_VIDEO),
+ PROPERTY_BITRATE("packet-audio-bitrate", true, STREAM_AUDIO),
+ PROPERTY_BITRATE("packet-sub-bitrate", true, STREAM_SUB),
+
+ PROPERTY_BITRATE("video-bitrate", false, STREAM_VIDEO),
+ PROPERTY_BITRATE("audio-bitrate", false, STREAM_AUDIO),
+ PROPERTY_BITRATE("sub-bitrate", false, STREAM_SUB),
#define PROPERTY_TV_COLOR(name, type) \
{name, mp_property_tv_color, (void *)(intptr_t)type}
@@ -3473,7 +3482,8 @@ static const char *const *const mp_event_property_change[] = {
E(MPV_EVENT_METADATA_UPDATE, "metadata", "filtered-metadata", "media-title"),
E(MPV_EVENT_CHAPTER_CHANGE, "chapter", "chapter-metadata"),
E(MP_EVENT_CACHE_UPDATE, "cache", "cache-free", "cache-used", "cache-idle",
- "demuxer-cache-duration", "demuxer-cache-idle", "paused-for-cache"),
+ "demuxer-cache-duration", "demuxer-cache-idle", "paused-for-cache",
+ "demuxer-cache-time"),
E(MP_EVENT_WIN_RESIZE, "window-scale"),
E(MP_EVENT_WIN_STATE, "window-minimized", "display-names", "display-fps"),
E(MP_EVENT_AUDIO_DEVICES, "audio-device-list"),
@@ -3960,39 +3970,6 @@ static void overlay_uninit(struct MPContext *mpctx)
osd_set_external2(mpctx->osd, NULL);
}
-struct subprocess_args {
- struct mp_log *log;
- char **args;
-};
-
-static void *run_subprocess(void *ptr)
-{
- struct subprocess_args *p = ptr;
- pthread_detach(pthread_self());
-
- mp_msg_flush_status_line(p->log);
-
- char *err = NULL;
- if (mp_subprocess(p->args, NULL, NULL, NULL, NULL, &err) < 0)
- mp_err(p->log, "Running subprocess failed: %s\n", err);
-
- talloc_free(p);
- return NULL;
-}
-
-static void subprocess_detached(struct mp_log *log, char **args)
-{
- struct subprocess_args *p = talloc_zero(NULL, struct subprocess_args);
- p->log = mp_log_new(p, log, NULL);
- int num_args = 0;
- for (int n = 0; args[n]; n++)
- MP_TARRAY_APPEND(p, p->args, num_args, talloc_strdup(p, args[n]));
- MP_TARRAY_APPEND(p, p->args, num_args, NULL);
- pthread_t thread;
- if (pthread_create(&thread, NULL, run_subprocess, p))
- talloc_free(p);
-}
-
struct cycle_counter {
char **args;
int counter;
@@ -4083,7 +4060,23 @@ static bool check_property_autorepeat(char *property, struct MPContext *mpctx)
return true;
}
-int run_command(MPContext *mpctx, mp_cmd_t *cmd)
+static struct mpv_node *add_map_entry(struct mpv_node *dst, const char *key)
+{
+ struct mpv_node_list *list = dst->u.list;
+ assert(dst->format == MPV_FORMAT_NODE_MAP && dst->u.list);
+ MP_TARRAY_GROW(list, list->values, list->num);
+ MP_TARRAY_GROW(list, list->keys, list->num);
+ list->keys[list->num] = talloc_strdup(list, key);
+ return &list->values[list->num++];
+}
+
+#define ADD_MAP_INT(dst, name, i) (*add_map_entry(dst, name) = \
+ (struct mpv_node){ .format = MPV_FORMAT_INT64, .u.int64 = (i) });
+
+#define ADD_MAP_CSTR(dst, name, s) (*add_map_entry(dst, name) = \
+ (struct mpv_node){ .format = MPV_FORMAT_STRING, .u.string = (s) });
+
+int run_command(struct MPContext *mpctx, struct mp_cmd *cmd, struct mpv_node *res)
{
struct command_ctx *cmdctx = mpctx->command_ctx;
struct MPOpts *opts = mpctx->opts;
@@ -4595,11 +4588,34 @@ int run_command(MPContext *mpctx, mp_cmd_t *cmd)
screenshot_to_file(mpctx, cmd->args[0].v.s, cmd->args[1].v.i, msg_osd);
break;
+ case MP_CMD_SCREENSHOT_RAW: {
+ if (!res)
+ return -1;
+ struct mp_image *img = screenshot_get_rgb(mpctx, cmd->args[0].v.i);
+ if (!img)
+ return -1;
+ struct mpv_node_list *info = talloc_zero(NULL, struct mpv_node_list);
+ talloc_steal(info, img);
+ *res = (mpv_node){ .format = MPV_FORMAT_NODE_MAP, .u.list = info };
+ ADD_MAP_INT(res, "w", img->w);
+ ADD_MAP_INT(res, "h", img->h);
+ ADD_MAP_INT(res, "stride", img->stride[0]);
+ ADD_MAP_CSTR(res, "format", "bgr0");
+ struct mpv_byte_array *ba = talloc_ptrtype(info, ba);
+ *ba = (struct mpv_byte_array){
+ .data = img->planes[0],
+ .size = img->stride[0] * img->h,
+ };
+ *add_map_entry(res, "data") =
+ (struct mpv_node){.format = MPV_FORMAT_BYTE_ARRAY, .u.ba = ba,};
+ break;
+ }
+
case MP_CMD_RUN: {
char *args[MP_CMD_MAX_ARGS + 1] = {0};
for (int n = 0; n < cmd->nargs; n++)
args[n] = cmd->args[n].v.s;
- subprocess_detached(mpctx->log, args);
+ mp_subprocess_detached(mpctx->log, args);
break;
}
@@ -4735,7 +4751,7 @@ int run_command(MPContext *mpctx, mp_cmd_t *cmd)
case MP_CMD_COMMAND_LIST: {
for (struct mp_cmd *sub = cmd->args[0].v.p; sub; sub = sub->queue_next)
- run_command(mpctx, sub);
+ run_command(mpctx, sub, NULL);
break;
}
diff --git a/player/command.h b/player/command.h
index 1a36c79570..447e01c011 100644
--- a/player/command.h
+++ b/player/command.h
@@ -21,11 +21,12 @@
struct MPContext;
struct mp_cmd;
struct mp_log;
+struct mpv_node;
void command_init(struct MPContext *mpctx);
void command_uninit(struct MPContext *mpctx);
-int run_command(struct MPContext *mpctx, struct mp_cmd *cmd);
+int run_command(struct MPContext *mpctx, struct mp_cmd *cmd, struct mpv_node *res);
char *mp_property_expand_string(struct MPContext *mpctx, const char *str);
char *mp_property_expand_escaped_string(struct MPContext *mpctx, const char *str);
void property_print_help(struct mp_log *log);
diff --git a/player/configfiles.c b/player/configfiles.c
index e056b43e8e..b7d3795f60 100644
--- a/player/configfiles.c
+++ b/player/configfiles.c
@@ -72,16 +72,14 @@ void mp_parse_cfgfiles(struct MPContext *mpctx)
// So we "divert" normal options into a separate section, and the diverted
// section is never used - unless maybe it's explicitly referenced from an
// encoding profile.
- if (encoding)
+ if (encoding) {
section = "playback-default";
- // The #if is a stupid hack to avoid errors if libavfilter is not available.
-#if HAVE_LIBAVFILTER && HAVE_ENCODING
- char *cf = mp_find_config_file(NULL, mpctx->global, "encoding-profiles.conf");
- if (cf)
- m_config_parse_config_file(mpctx->mconfig, cf, SECT_ENCODE, 0);
- talloc_free(cf);
-#endif
+ char *cf = mp_find_config_file(NULL, mpctx->global, "encoding-profiles.conf");
+ if (cf)
+ m_config_parse_config_file(mpctx->mconfig, cf, SECT_ENCODE, 0);
+ talloc_free(cf);
+ }
load_all_cfgfiles(mpctx, section, "mpv.conf|config");
diff --git a/player/core.h b/player/core.h
index 23547ac630..714fd5d4bd 100644
--- a/player/core.h
+++ b/player/core.h
@@ -373,6 +373,7 @@ void mp_nav_destroy(struct MPContext *mpctx);
void mp_nav_user_input(struct MPContext *mpctx, char *command);
void mp_handle_nav(struct MPContext *mpctx);
int mp_nav_in_menu(struct MPContext *mpctx);
+bool mp_nav_mouse_on_button(struct MPContext *mpctx);
// loadfile.c
void uninit_player(struct MPContext *mpctx, unsigned int mask);
@@ -490,7 +491,6 @@ int reinit_video_chain(struct MPContext *mpctx);
int reinit_video_filters(struct MPContext *mpctx);
void write_video(struct MPContext *mpctx, double endpts);
void mp_force_video_refresh(struct MPContext *mpctx);
-void update_fps(struct MPContext *mpctx);
void uninit_video_out(struct MPContext *mpctx);
void uninit_video_chain(struct MPContext *mpctx);
diff --git a/player/discnav.c b/player/discnav.c
index d66b569d4b..719e88ac8f 100644
--- a/player/discnav.c
+++ b/player/discnav.c
@@ -42,6 +42,7 @@ struct mp_nav_state {
bool nav_eof;
bool nav_menu;
bool nav_draining;
+ bool nav_mouse_on_button;
// Accessed by OSD (possibly separate thread)
// Protected by the given lock
@@ -91,6 +92,25 @@ int mp_nav_in_menu(struct MPContext *mpctx)
return mpctx->nav_state ? mpctx->nav_state->nav_menu : -1;
}
+static void update_mouse_on_button(struct MPContext *mpctx)
+{
+ mp_notify_property(mpctx, "disc-mouse-on-button");
+}
+
+static void set_mouse_on_button(struct MPContext *mpctx, bool in)
+{
+ struct mp_nav_state *nav = mpctx->nav_state;
+ if (nav->nav_mouse_on_button != in) {
+ nav->nav_mouse_on_button = in;
+ update_mouse_on_button(mpctx);
+ }
+}
+
+bool mp_nav_mouse_on_button(struct MPContext *mpctx)
+{
+ return mpctx->nav_state ? mpctx->nav_state->nav_mouse_on_button : false;
+}
+
// If a demuxer is accessing the stream, we have to use demux_stream_control()
// to avoid synchronization issues; otherwise access it directly.
static int run_stream_control(struct MPContext *mpctx, int cmd, void *arg)
@@ -129,6 +149,7 @@ void mp_nav_init(struct MPContext *mpctx)
MP_INPUT_ALLOW_VO_DRAGGING | MP_INPUT_ALLOW_HIDE_CURSOR);
update_state(mpctx);
+ update_mouse_on_button(mpctx);
}
void mp_nav_reset(struct MPContext *mpctx)
@@ -159,6 +180,7 @@ void mp_nav_destroy(struct MPContext *mpctx)
talloc_free(mpctx->nav_state);
mpctx->nav_state = NULL;
update_state(mpctx);
+ update_mouse_on_button(mpctx);
}
void mp_nav_user_input(struct MPContext *mpctx, char *command)
@@ -182,6 +204,7 @@ void mp_nav_user_input(struct MPContext *mpctx, char *command)
inp.u.mouse_pos.x = x;
inp.u.mouse_pos.y = y;
run_stream_control(mpctx, STREAM_CTRL_NAV_CMD, &inp);
+ set_mouse_on_button(mpctx, inp.mouse_on_button);
} else {
struct mp_nav_cmd inp = {MP_NAV_CMD_MENU};
inp.u.menu.action = command;
diff --git a/player/lua.c b/player/lua.c
index 43f549b4ed..4ef772fd84 100644
--- a/player/lua.c
+++ b/player/lua.c
@@ -860,6 +860,9 @@ static void pushnode(lua_State *L, mpv_node *node)
lua_rawset(L, -3);
}
break;
+ case MPV_FORMAT_BYTE_ARRAY:
+ lua_pushlstring(L, node->u.ba->data, node->u.ba->size);
+ break;
default:
// unknown value - what do we do?
// for now, set a unique dummy value
@@ -1252,6 +1255,23 @@ static int script_parse_json(lua_State *L)
return 3;
}
+static int script_format_json(lua_State *L)
+{
+ void *tmp = mp_lua_PITA(L);
+ struct mpv_node node;
+ makenode(tmp, &node, L, 1);
+ char *dst = talloc_strdup(tmp, "");
+ if (json_write(&dst, &node) >= 0) {
+ lua_pushstring(L, dst);
+ lua_pushnil(L);
+ } else {
+ lua_pushnil(L);
+ lua_pushstring(L, "error");
+ }
+ talloc_free_children(tmp);
+ return 2;
+}
+
#define FN_ENTRY(name) {#name, script_ ## name}
struct fn_entry {
const char *name;
@@ -1300,6 +1320,7 @@ static const struct fn_entry utils_fns[] = {
FN_ENTRY(join_path),
FN_ENTRY(subprocess),
FN_ENTRY(parse_json),
+ FN_ENTRY(format_json),
{0}
};
diff --git a/player/lua/osc.lua b/player/lua/osc.lua
index 26e2f89c5f..7f602b8689 100644
--- a/player/lua/osc.lua
+++ b/player/lua/osc.lua
@@ -266,11 +266,13 @@ end
-- get the currently selected track of <type>, OSC-style counted
function get_track(type)
local track = mp.get_property(type)
- if (track == "no" or track == nil) then
- return 0
- else
- return tracks_mpv[type][tonumber(track)].osc_id
+ if track ~= "no" and track ~= nil then
+ local tr = tracks_mpv[type][tonumber(track)]
+ if tr then
+ return tr.osc_id
+ end
end
+ return 0
end
@@ -446,7 +448,7 @@ function render_elements(master_ass)
style_ass:append(string.format("{\\1a&H%X&\\2a&H%X&\\3a&H%X&\\4a&H%X&}",
ar[1], ar[2], ar[3], ar[4]))
- if (state.active_element == n) then
+ if element.eventresponder and (state.active_element == n) then
-- run render event functions
if not (element.eventresponder.render == nil) then
diff --git a/player/playloop.c b/player/playloop.c
index 1f480cf3ba..c34ae7e6da 100644
--- a/player/playloop.c
+++ b/player/playloop.c
@@ -67,7 +67,7 @@ void mp_process_input(struct MPContext *mpctx)
mp_cmd_t *cmd = mp_input_read_cmd(mpctx->input);
if (!cmd)
break;
- run_command(mpctx, cmd);
+ run_command(mpctx, cmd, NULL);
mp_cmd_free(cmd);
mp_dispatch_queue_process(mpctx->dispatch, 0);
}
@@ -240,8 +240,6 @@ static int mp_seek(MPContext *mpctx, struct seek_params seek,
}
if (hr_seek)
demuxer_style |= SEEK_HR;
- if (hr_seek || opts->mkv_subtitle_preroll)
- demuxer_style |= SEEK_SUBPREROLL;
if (hr_seek)
demuxer_amount -= hr_seek_offset;
diff --git a/player/screenshot.c b/player/screenshot.c
index ec01adffaa..a47de292d5 100644
--- a/player/screenshot.c
+++ b/player/screenshot.c
@@ -32,7 +32,6 @@
#include "options/path.h"
#include "video/mp_image.h"
#include "video/decode/dec_video.h"
-#include "video/filter/vf.h"
#include "video/out/vo.h"
#include "video/image_writer.h"
#include "sub/osd.h"
@@ -330,11 +329,7 @@ static struct mp_image *screenshot_get(struct MPContext *mpctx, int mode)
if (mode == MODE_SUBTITLES && osd_get_render_subs_in_filter(mpctx->osd))
mode = 0;
- // vf_screenshot
- if (mpctx->d_video && mpctx->d_video->vfilter)
- vf_control_any(mpctx->d_video->vfilter, VFCTRL_SCREENSHOT, &image);
-
- if (!image && mpctx->video_out && mpctx->video_out->config_ok) {
+ if (mpctx->video_out && mpctx->video_out->config_ok) {
vo_wait_frame(mpctx->video_out); // important for each-frame mode
if (mode != MODE_FULL_WINDOW)
@@ -362,6 +357,16 @@ static struct mp_image *screenshot_get(struct MPContext *mpctx, int mode)
return image;
}
+struct mp_image *screenshot_get_rgb(struct MPContext *mpctx, int mode)
+{
+ struct mp_image *mpi = screenshot_get(mpctx, mode);
+ if (!mpi)
+ return NULL;
+ struct mp_image *res = convert_image(mpi, IMGFMT_BGR0, mpctx->log);
+ talloc_free(mpi);
+ return res;
+}
+
void screenshot_to_file(struct MPContext *mpctx, const char *filename, int mode,
bool osd)
{
@@ -370,11 +375,6 @@ void screenshot_to_file(struct MPContext *mpctx, const char *filename, int mode,
bool old_osd = ctx->osd;
ctx->osd = osd;
- if (mp_path_exists(filename)) {
- screenshot_msg(ctx, SMSG_ERR, "Screenshot: file '%s' already exists.",
- filename);
- goto end;
- }
char *ext = mp_splitext(filename, NULL);
if (ext)
opts.format = ext;
diff --git a/player/screenshot.h b/player/screenshot.h
index 84b7ef4f58..9ebe9ef76e 100644
--- a/player/screenshot.h
+++ b/player/screenshot.h
@@ -39,6 +39,9 @@ void screenshot_request(struct MPContext *mpctx, int mode, bool each_frame,
void screenshot_to_file(struct MPContext *mpctx, const char *filename, int mode,
bool osd);
+// mode is the same as in screenshot_request()
+struct mp_image *screenshot_get_rgb(struct MPContext *mpctx, int mode);
+
// Called by the playback core code when a new frame is displayed.
void screenshot_flip(struct MPContext *mpctx);
diff --git a/player/video.c b/player/video.c
index 6c41593c72..d35a9de011 100644
--- a/player/video.c
+++ b/player/video.c
@@ -76,15 +76,6 @@ static const char av_desync_help_text[] =
" with --no-video, --no-audio, or --no-sub.\n"
"If none of this helps you, file a bug report.\n\n";
-void update_fps(struct MPContext *mpctx)
-{
-#if HAVE_ENCODING
- struct dec_video *d_video = mpctx->d_video;
- if (mpctx->encode_lavc_ctx && d_video)
- encode_lavc_set_video_fps(mpctx->encode_lavc_ctx, d_video->fps);
-#endif
-}
-
static void set_allowed_vo_formats(struct vf_chain *c, struct vo *vo)
{
vo_query_formats(vo, c->allowed_output_formats);
@@ -296,12 +287,18 @@ int reinit_video_chain(struct MPContext *mpctx)
d_video->fps = sh->video->fps;
d_video->vo = mpctx->video_out;
+ MP_VERBOSE(d_video, "Container reported FPS: %f\n", sh->video->fps);
+
if (opts->force_fps) {
d_video->fps = opts->force_fps;
MP_INFO(mpctx, "FPS forced to %5.3f.\n", d_video->fps);
MP_INFO(mpctx, "Use --no-correct-pts to force FPS based timing.\n");
}
- update_fps(mpctx);
+
+#if HAVE_ENCODING
+ if (mpctx->encode_lavc_ctx && d_video)
+ encode_lavc_set_video_fps(mpctx->encode_lavc_ctx, d_video->fps);
+#endif
vo_control(mpctx->video_out, VOCTRL_GET_HWDEC_INFO, &d_video->hwdec_info);
@@ -380,7 +377,7 @@ static int decode_image(struct MPContext *mpctx)
if (d_video->header->attached_picture) {
d_video->waiting_decoded_mpi =
video_decode(d_video, d_video->header->attached_picture, 0);
- return VD_EOF;
+ return d_video->waiting_decoded_mpi ? VD_EOF : VD_PROGRESS;
}
struct demux_packet *pkt;
@@ -405,7 +402,8 @@ static int decode_image(struct MPContext *mpctx)
talloc_free(pkt);
if (had_packet && !d_video->waiting_decoded_mpi &&
- mpctx->video_status == STATUS_PLAYING)
+ mpctx->video_status == STATUS_PLAYING &&
+ (mpctx->opts->frame_dropping & 2))
{
mpctx->dropped_frames_total++;
mpctx->dropped_frames++;
@@ -726,9 +724,9 @@ static void update_avsync_after_frame(struct MPContext *mpctx)
mpctx->last_av_difference = a_pos - mpctx->video_pts + opts->audio_delay;
if (mpctx->time_frame > 0)
mpctx->last_av_difference += mpctx->time_frame * opts->playback_speed;
- if (a_pos == MP_NOPTS_VALUE || mpctx->video_pts == MP_NOPTS_VALUE)
+ if (a_pos == MP_NOPTS_VALUE || mpctx->video_pts == MP_NOPTS_VALUE) {
mpctx->last_av_difference = MP_NOPTS_VALUE;
- if (fabs(mpctx->last_av_difference) > 0.5 && !mpctx->drop_message_shown) {
+ } else if (fabs(mpctx->last_av_difference) > 0.5 && !mpctx->drop_message_shown) {
MP_WARN(mpctx, "%s", av_desync_help_text);
mpctx->drop_message_shown = true;
}
@@ -768,8 +766,6 @@ void write_video(struct MPContext *mpctx, double endpts)
if (mpctx->paused && mpctx->video_status >= STATUS_READY)
return;
- update_fps(mpctx);
-
int r = video_output_image(mpctx, endpts);
MP_TRACE(mpctx, "video_output_image: %d\n", r);
@@ -784,7 +780,7 @@ void write_video(struct MPContext *mpctx, double endpts)
vo_still_displaying(vo) ? STATUS_DRAINING : STATUS_EOF;
mpctx->delay = 0;
mpctx->last_av_difference = 0;
- MP_VERBOSE(mpctx, "video EOF (status=%d)\n", mpctx->video_status);
+ MP_DBG(mpctx, "video EOF (status=%d)\n", mpctx->video_status);
return;
}