mirror of
https://github.com/mpv-player/mpv
synced 2025-03-20 02:09:52 +00:00
stats: change the way toggling/oneshot works internally
Previously multiple timers were used to realize oneshot, toggling (redrawing) and page keybindings. The oneshot case in particular also relied on mp.osd_message to display text only for a given duration. This was changed to only use one timer in total now. Because now each case has a defined "start" and "end" point (including oneshot) mp.set_osd_ass() can be used to print stats as well. This is currently optional and has to be activated using the config option persistent_overlay=true. One shortcoming: oneshot and toggling are mutual exclusive right now. Previously you could enter toggling while oneshot stats were shown, this is not possible anymore to reduce the number of cases to be considered. This can be added later on if desired.
This commit is contained in:
parent
eadec19d22
commit
c38ad6ae6f
@ -21,6 +21,7 @@ local o = {
|
|||||||
duration = 4,
|
duration = 4,
|
||||||
redraw_delay = 1, -- acts as duration in the toggling case
|
redraw_delay = 1, -- acts as duration in the toggling case
|
||||||
ass_formatting = true,
|
ass_formatting = true,
|
||||||
|
persistent_overlay = false, -- whether the stats can be overwritten by other output
|
||||||
print_perfdata_passes = false, -- when true, print the full information about all passes
|
print_perfdata_passes = false, -- when true, print the full information about all passes
|
||||||
filter_params_max_length = 100, -- a filter list longer than this many characters will be shown one filter per line instead
|
filter_params_max_length = 100, -- a filter list longer than this many characters will be shown one filter per line instead
|
||||||
debug = false,
|
debug = false,
|
||||||
@ -79,18 +80,14 @@ local min = math.min
|
|||||||
|
|
||||||
-- Function used to record performance data
|
-- Function used to record performance data
|
||||||
local recorder = nil
|
local recorder = nil
|
||||||
-- Timer used for toggling
|
-- Timer used for redrawing (toggling) and clearing the screen (oneshot)
|
||||||
local toggle_timer = nil
|
local display_timer = nil
|
||||||
-- Timer used to remove forced keybindings
|
|
||||||
local binding_timer = nil
|
|
||||||
-- Current page and <page key>:<page function> mappings
|
-- Current page and <page key>:<page function> mappings
|
||||||
local curr_page = o.key_page_1
|
local curr_page = o.key_page_1
|
||||||
local pages = {}
|
local pages = {}
|
||||||
|
|
||||||
-- Save these sequences locally as we'll need them a lot
|
-- Save these sequences locally as we'll need them a lot
|
||||||
local ass_start = mp.get_property_osd("osd-ass-cc/0")
|
local ass_start = mp.get_property_osd("osd-ass-cc/0")
|
||||||
local ass_stop = mp.get_property_osd("osd-ass-cc/1")
|
local ass_stop = mp.get_property_osd("osd-ass-cc/1")
|
||||||
|
|
||||||
-- Ring buffers for the values used to construct a graph.
|
-- Ring buffers for the values used to construct a graph.
|
||||||
-- .pos denotes the current position, .len the buffer length
|
-- .pos denotes the current position, .len the buffer length
|
||||||
-- .max is the max value in the corresponding buffer
|
-- .max is the max value in the corresponding buffer
|
||||||
@ -99,7 +96,6 @@ local function init_buffers()
|
|||||||
vsratio_buf = {0, pos = 1, len = 50, max = 0}
|
vsratio_buf = {0, pos = 1, len = 50, max = 0}
|
||||||
vsjitter_buf = {0, pos = 1, len = 50, max = 0}
|
vsjitter_buf = {0, pos = 1, len = 50, max = 0}
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Save all properties known to this version of mpv
|
-- Save all properties known to this version of mpv
|
||||||
local property_list = {}
|
local property_list = {}
|
||||||
for p in string.gmatch(mp.get_property("property-list"), "([^,]+)") do property_list[p] = true end
|
for p in string.gmatch(mp.get_property("property-list"), "([^,]+)") do property_list[p] = true end
|
||||||
@ -121,7 +117,7 @@ end
|
|||||||
|
|
||||||
|
|
||||||
local function set_ASS(b)
|
local function set_ASS(b)
|
||||||
if not o.use_ass then
|
if not o.use_ass or o.persistent_overlay then
|
||||||
return ""
|
return ""
|
||||||
end
|
end
|
||||||
return b and ass_start or ass_stop
|
return b and ass_start or ass_stop
|
||||||
@ -150,7 +146,8 @@ local function text_style()
|
|||||||
if o.custom_header and o.custom_header ~= "" then
|
if o.custom_header and o.custom_header ~= "" then
|
||||||
return set_ASS(true) .. o.custom_header
|
return set_ASS(true) .. o.custom_header
|
||||||
else
|
else
|
||||||
return format("%s{\\r}{\\an7}{\\fs%d}{\\fn%s}{\\bord%f}{\\3c&H%s&}{\\1c&H%s&}{\\alpha&H%s&}{\\xshad%f}{\\yshad%f}{\\4c&H%s&}",
|
return format("%s{\\r}{\\an7}{\\fs%d}{\\fn%s}{\\bord%f}{\\3c&H%s&}" ..
|
||||||
|
"{\\1c&H%s&}{\\alpha&H%s&}{\\xshad%f}{\\yshad%f}{\\4c&H%s&}",
|
||||||
set_ASS(true), o.font_size, o.font, o.border_size,
|
set_ASS(true), o.font_size, o.font, o.border_size,
|
||||||
o.border_color, o.font_color, o.alpha, o.shadow_x_offset,
|
o.border_color, o.font_color, o.alpha, o.shadow_x_offset,
|
||||||
o.shadow_y_offset, o.shadow_color)
|
o.shadow_y_offset, o.shadow_color)
|
||||||
@ -176,7 +173,9 @@ end
|
|||||||
|
|
||||||
|
|
||||||
local function has_ansi()
|
local function has_ansi()
|
||||||
local is_windows = type(package) == 'table' and type(package.config) == 'string' and package.config:sub(1,1) == '\\'
|
local is_windows = type(package) == 'table'
|
||||||
|
and type(package.config) == 'string'
|
||||||
|
and package.config:sub(1, 1) == '\\'
|
||||||
if is_windows then
|
if is_windows then
|
||||||
return os.getenv("ANSICON")
|
return os.getenv("ANSICON")
|
||||||
end
|
end
|
||||||
@ -309,7 +308,8 @@ local function append_perfdata(s, dedicated_page)
|
|||||||
return format("{\\b%d}%02d%%{\\b0}", w, i * 100)
|
return format("{\\b%d}%02d%%{\\b0}", w, i * 100)
|
||||||
end
|
end
|
||||||
|
|
||||||
s[#s+1] = format("%s%s%s%s{\\fs%s}%s{\\fs%s}", dedicated_page and "" or o.nl, dedicated_page and "" or o.indent,
|
s[#s+1] = format("%s%s%s%s{\\fs%s}%s{\\fs%s}",
|
||||||
|
dedicated_page and "" or o.nl, dedicated_page and "" or o.indent,
|
||||||
b("Frame Timings:"), o.prefix_sep, o.font_size * 0.66,
|
b("Frame Timings:"), o.prefix_sep, o.font_size * 0.66,
|
||||||
"(last/average/peak μs)", o.font_size)
|
"(last/average/peak μs)", o.font_size)
|
||||||
|
|
||||||
@ -368,7 +368,7 @@ local function append_display_sync(s)
|
|||||||
append_property(s, "vo-delayed-frame-count", {prefix="Delayed:", nl=""})
|
append_property(s, "vo-delayed-frame-count", {prefix="Delayed:", nl=""})
|
||||||
|
|
||||||
-- As we need to plot some graphs we print jitter and ratio on their own lines
|
-- As we need to plot some graphs we print jitter and ratio on their own lines
|
||||||
if toggle_timer:is_enabled() and (o.plot_vsync_ratio or o.plot_vsync_jitter) and o.use_ass then
|
if not display_timer.oneshot and (o.plot_vsync_ratio or o.plot_vsync_jitter) and o.use_ass then
|
||||||
local ratio_graph = ""
|
local ratio_graph = ""
|
||||||
local jitter_graph = ""
|
local jitter_graph = ""
|
||||||
if o.plot_vsync_ratio then
|
if o.plot_vsync_ratio then
|
||||||
@ -459,13 +459,12 @@ local function add_video(s)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if append_property(s, "video-codec", {prefix=o.nl .. o.nl .. "Video:", nl="", indent=""}) then
|
if append_property(s, "video-codec", {prefix=o.nl .. o.nl .. "Video:", nl="", indent=""}) then
|
||||||
append_property(s, "hwdec-current",
|
append_property(s, "hwdec-current", {prefix="(hwdec:", nl="", indent=" ",
|
||||||
{prefix="(hwdec:", nl="", indent=" ",
|
no_prefix_markup=true, suffix=")"}, {no=true, [""]=true})
|
||||||
no_prefix_markup=true, suffix=")"},
|
|
||||||
{no=true, [""]=true})
|
|
||||||
end
|
end
|
||||||
append_property(s, "avsync", {prefix="A-V:"})
|
append_property(s, "avsync", {prefix="A-V:"})
|
||||||
if append_property(s, compat("decoder-frame-drop-count"), {prefix="Dropped Frames:", suffix=" (decoder)"}) then
|
if append_property(s, compat("decoder-frame-drop-count"),
|
||||||
|
{prefix="Dropped Frames:", suffix=" (decoder)"}) then
|
||||||
append_property(s, compat("frame-drop-count"), {suffix=" (output)", nl="", indent=""})
|
append_property(s, compat("frame-drop-count"), {suffix=" (output)", nl="", indent=""})
|
||||||
end
|
end
|
||||||
if append_property(s, "display-fps", {prefix="Display FPS:", suffix=" (specified)"}) then
|
if append_property(s, "display-fps", {prefix="Display FPS:", suffix=" (specified)"}) then
|
||||||
@ -526,7 +525,7 @@ local function add_audio(s)
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Determine whether ASS formatting shall/can be used
|
-- Determine whether ASS formatting shall/can be used and set formatting sequences
|
||||||
local function eval_ass_formatting()
|
local function eval_ass_formatting()
|
||||||
o.use_ass = o.ass_formatting and has_vo_window()
|
o.use_ass = o.ass_formatting and has_vo_window()
|
||||||
if o.use_ass then
|
if o.use_ass then
|
||||||
@ -584,38 +583,13 @@ local function filter_stats()
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Call the function for `page` and print it to OSD
|
-- Current page and <page key>:<page function> mapping
|
||||||
local function print_page(page, duration)
|
curr_page = o.key_page_1
|
||||||
mp.osd_message(pages[page].f(), duration or o.duration)
|
pages = {
|
||||||
end
|
[o.key_page_1] = { f = default_stats, desc = "Default" },
|
||||||
|
[o.key_page_2] = { f = vo_stats, desc = "Extended Frame Timings" },
|
||||||
|
[o.key_page_3] = { f = filter_stats, desc = "Dummy" },
|
||||||
-- Add keybindings for every page
|
}
|
||||||
local function add_page_bindings()
|
|
||||||
local function a(k)
|
|
||||||
return function()
|
|
||||||
-- In single invocation case we need to reset the timer because
|
|
||||||
-- stats are printed again for o.duration
|
|
||||||
if not toggle_timer:is_enabled() then
|
|
||||||
binding_timer:kill()
|
|
||||||
binding_timer:resume()
|
|
||||||
end
|
|
||||||
curr_page = k
|
|
||||||
print_page(k, toggle_timer:is_enabled() and o.redraw_delay + 1 or nil)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
for k, _ in pairs(pages) do
|
|
||||||
mp.add_forced_key_binding(k, k, a(k), {repeatable=true})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function remove_page_bindings()
|
|
||||||
for k, _ in pairs(pages) do
|
|
||||||
mp.remove_key_binding(k)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
-- Returns a function to record vsratio/jitter with the specified `skip` value
|
-- Returns a function to record vsratio/jitter with the specified `skip` value
|
||||||
@ -652,80 +626,109 @@ local function record_data(skip)
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local function toggle_stats()
|
-- Call the function for `page` and print it to OSD
|
||||||
-- Disable
|
local function print_page(page)
|
||||||
if toggle_timer:is_enabled() then
|
if o.persistent_overlay then
|
||||||
|
mp.set_osd_ass(0, 0, pages[page].f())
|
||||||
|
else
|
||||||
|
mp.osd_message(pages[page].f(), display_timer.oneshot and o.duration or o.redraw_delay + 1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function clear_screen()
|
||||||
|
if o.persistent_overlay then mp.set_osd_ass(0, 0, "") else mp.osd_message("", 0) end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Add keybindings for every page
|
||||||
|
local function add_page_bindings()
|
||||||
|
local function a(k)
|
||||||
|
return function()
|
||||||
|
curr_page = k
|
||||||
|
print_page(k)
|
||||||
|
if display_timer.oneshot then display_timer:kill() ; display_timer:resume() end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for k, _ in pairs(pages) do
|
||||||
|
mp.add_forced_key_binding(k, k, a(k), {repeatable=true})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Remove keybindings for every page
|
||||||
|
local function remove_page_bindings()
|
||||||
|
for k, _ in pairs(pages) do
|
||||||
|
mp.remove_key_binding(k)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function process_key_binding(oneshot)
|
||||||
|
-- Stats are already being displayed
|
||||||
|
if display_timer:is_enabled() then
|
||||||
|
-- Previous and current keys were oneshot -> restart timer
|
||||||
|
if display_timer.oneshot and oneshot then
|
||||||
|
display_timer:kill()
|
||||||
|
print_page(curr_page)
|
||||||
|
display_timer:resume()
|
||||||
|
-- Previous and current keys were toggling -> end toggling
|
||||||
|
elseif not display_timer.oneshot and not oneshot then
|
||||||
|
display_timer:kill()
|
||||||
|
clear_screen()
|
||||||
|
remove_page_bindings()
|
||||||
if recorder then
|
if recorder then
|
||||||
mp.unregister_event(recorder)
|
mp.unregister_event(recorder)
|
||||||
recorder = nil
|
recorder = nil
|
||||||
end
|
end
|
||||||
toggle_timer:kill()
|
end
|
||||||
mp.osd_message("", 0) -- clear the screen
|
-- No stats are being displayed yet
|
||||||
remove_page_bindings()
|
|
||||||
-- Enable
|
|
||||||
else
|
else
|
||||||
if o.plot_vsync_jitter or o.plot_vsync_ratio then
|
if not oneshot and (o.plot_vsync_jitter or o.plot_vsync_ratio) then
|
||||||
recorder = record_data(o.skip_frames)
|
recorder = record_data(o.skip_frames)
|
||||||
mp.register_event("tick", recorder)
|
mp.register_event("tick", recorder)
|
||||||
end
|
end
|
||||||
|
display_timer:kill()
|
||||||
|
display_timer.oneshot = oneshot
|
||||||
|
display_timer.timeout = oneshot and o.duration or o.redraw_delay
|
||||||
add_page_bindings()
|
add_page_bindings()
|
||||||
toggle_timer:resume()
|
print_page(curr_page)
|
||||||
print_page(curr_page, o.redraw_delay + 1)
|
display_timer:resume()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local function oneshot_stats(page)
|
-- Create the timer used for redrawing (toggling) or clearing the screen (oneshot)
|
||||||
-- Ignore single invocations while stats are toggled
|
-- The duration here is not important and always set in process_key_binding()
|
||||||
if toggle_timer:is_enabled() then
|
display_timer = mp.add_periodic_timer(o.duration,
|
||||||
return
|
|
||||||
end
|
|
||||||
binding_timer:kill()
|
|
||||||
binding_timer:resume()
|
|
||||||
add_page_bindings()
|
|
||||||
print_page(page or curr_page)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
-- Current page and <page key>:<page function> mapping
|
|
||||||
curr_page = o.key_page_1
|
|
||||||
pages = {
|
|
||||||
[o.key_page_1] = { f = default_stats, desc = "Default" },
|
|
||||||
[o.key_page_2] = { f = vo_stats, desc = "Extended Frame Timings" },
|
|
||||||
[o.key_page_3] = { f = filter_stats, desc = "Dummy" },
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
-- Create timer used for toggling, pause it immediately
|
|
||||||
toggle_timer = mp.add_periodic_timer(o.redraw_delay, function() print_page(curr_page, o.redraw_delay + 1) end)
|
|
||||||
toggle_timer:kill()
|
|
||||||
|
|
||||||
-- Create timer used to remove forced key bindings, only in the "single invocation" case
|
|
||||||
binding_timer = mp.add_periodic_timer(o.duration,
|
|
||||||
function()
|
function()
|
||||||
if not toggle_timer:is_enabled() then
|
if display_timer.oneshot then
|
||||||
remove_page_bindings()
|
display_timer:kill() ; clear_screen() ; remove_page_bindings()
|
||||||
|
else
|
||||||
|
print_page(curr_page)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
binding_timer.oneshot = true
|
display_timer:kill()
|
||||||
binding_timer:kill()
|
|
||||||
|
|
||||||
-- Single invocation key binding
|
-- Single invocation key binding
|
||||||
mp.add_key_binding(o.key_oneshot, "display-stats", oneshot_stats, {repeatable=true})
|
mp.add_key_binding(o.key_oneshot, "display-stats", function() process_key_binding(true) end,
|
||||||
|
{repeatable=true})
|
||||||
|
|
||||||
|
-- Toggling key binding
|
||||||
|
mp.add_key_binding(o.key_toggle, "display-stats-toggle", function() process_key_binding(false) end,
|
||||||
|
{repeatable=false})
|
||||||
|
|
||||||
-- Single invocation bindings without key, can be used in input.conf to create
|
-- Single invocation bindings without key, can be used in input.conf to create
|
||||||
-- bindings for a specific page: "e script-binding stats/display-page-2"
|
-- bindings for a specific page: "e script-binding stats/display-page-2"
|
||||||
for k, _ in pairs(pages) do
|
for k, _ in pairs(pages) do
|
||||||
mp.add_key_binding(nil, "display-page-" .. k, function() oneshot_stats(k) end, {repeatable=true})
|
mp.add_key_binding(nil, "display-page-" .. k, function() process_key_binding(true) end,
|
||||||
|
{repeatable=true})
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Toggling key binding
|
|
||||||
mp.add_key_binding(o.key_toggle, "display-stats-toggle", toggle_stats, {repeatable=false})
|
|
||||||
|
|
||||||
-- Reprint stats immediately when VO was reconfigured, only when toggled
|
-- Reprint stats immediately when VO was reconfigured, only when toggled
|
||||||
mp.register_event("video-reconfig",
|
mp.register_event("video-reconfig",
|
||||||
function()
|
function()
|
||||||
if toggle_timer:is_enabled() then
|
if display_timer:is_enabled() then
|
||||||
print_page(curr_page, o.redraw_delay + 1)
|
print_page(curr_page)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
Loading…
Reference in New Issue
Block a user