diff options
Diffstat (limited to 'player')
-rw-r--r-- | player/client.c | 15 | ||||
-rw-r--r-- | player/command.c | 184 | ||||
-rw-r--r-- | player/command.h | 3 | ||||
-rw-r--r-- | player/configfiles.c | 14 | ||||
-rw-r--r-- | player/core.h | 2 | ||||
-rw-r--r-- | player/discnav.c | 23 | ||||
-rw-r--r-- | player/lua.c | 21 | ||||
-rw-r--r-- | player/lua/osc.lua | 12 | ||||
-rw-r--r-- | player/playloop.c | 4 | ||||
-rw-r--r-- | player/screenshot.c | 22 | ||||
-rw-r--r-- | player/screenshot.h | 3 | ||||
-rw-r--r-- | player/video.c | 30 |
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; } |