mirror of
https://github.com/mpv-player/mpv.git
synced 2025-12-28 05:33:14 +00:00
TOOLS/lua: add autodeint.lua
This isn't quite as robust as idet.sh as the default detection interval is only 4 seconds vs 35 for idet.sh. idet.sh can have such a large sample time since it turns off the vo and uses --untimed, which is currently not possible from lua.
This commit is contained in:
164
TOOLS/lua/autodeint.lua
Normal file
164
TOOLS/lua/autodeint.lua
Normal file
@@ -0,0 +1,164 @@
|
||||
-- This script uses the lavfi idet filter to automatically insert the
|
||||
-- appropriate deinterlacing filter based on a short section of the
|
||||
-- currently playing video.
|
||||
--
|
||||
-- It registers the key-binding ctrl+d, which when pressed, inserts
|
||||
-- the filter vf=lavfi=idet. After 4 second, it examines the results
|
||||
-- to determine whether the content progressive or interlaced and the
|
||||
-- interlacing field dominance. It immediately sets the latter within
|
||||
-- mpv.
|
||||
--
|
||||
-- If the content is judged not to be progressive, it may be either
|
||||
-- interlaced or telecined. To determine which one, the video is
|
||||
-- seeked back to the detection starting point with the "pullup"
|
||||
-- filter inserted. After another four seconds, if idet thinks that
|
||||
-- the pulled up viedo is "progressive", then pullup is the correct
|
||||
-- filter and this script leaves it in places while removing the idet
|
||||
-- filter. Otherwise, the content plain interlaced and mpv's deinterlace
|
||||
-- property is set. This will usually insert the yadif deinterlacing filter.
|
||||
--
|
||||
-- The default detection time may be overridden by adding
|
||||
--
|
||||
-- --lua-opts=autodeint.detect_seconds=<number of seconds>
|
||||
--
|
||||
-- to mpv's arguments. This may be desirable to allow idet more
|
||||
-- time to collect data.
|
||||
--
|
||||
-- To see counts of the various types of frames for each detection phase,
|
||||
-- the verbosity can be increased with
|
||||
--
|
||||
-- --msg-level autodeint=v
|
||||
--
|
||||
-- This script requires a recent version of ffmpeg for which the idet
|
||||
-- filter adds the required metadata.
|
||||
|
||||
require "mp.msg"
|
||||
|
||||
script_name = mp.get_script_name()
|
||||
detect_label = string.format("%s-detect", script_name)
|
||||
pullup_label = string.format("%s", script_name)
|
||||
|
||||
-- number of seconds to gather cropdetect data
|
||||
detect_seconds = tonumber(mp.get_opt(string.format("%s.detect_seconds", script_name)))
|
||||
if not detect_seconds then
|
||||
detect_seconds = 4
|
||||
end
|
||||
|
||||
function del_filter_if_present(label)
|
||||
-- necessary because mp.command('vf del @label:filter') raises an
|
||||
-- error if the filter doesn't exist
|
||||
local vfs = mp.get_property_native("vf")
|
||||
|
||||
for i,vf in pairs(vfs) do
|
||||
if vf["label"] == label then
|
||||
table.remove(vfs, i)
|
||||
mp.set_property_native("vf", vfs)
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function start_detect()
|
||||
-- exit if detection is already in progress
|
||||
if timer then
|
||||
mp.msg.warn("already detecting!")
|
||||
return
|
||||
end
|
||||
|
||||
mp.set_property("deinterlace","no")
|
||||
del_filter_if_present(pullup_label)
|
||||
|
||||
percent_pos = mp.get_property("percent-pos")
|
||||
|
||||
-- insert the detection filter
|
||||
local cmd = string.format('vf add @%s:lavfi=graph="idet"', detect_label)
|
||||
if not mp.command(cmd) then
|
||||
mp.msg.error("failed to insert detection filter")
|
||||
return
|
||||
end
|
||||
|
||||
-- wait to gather data
|
||||
timer = mp.add_timeout(detect_seconds, judge_field_dominance)
|
||||
end
|
||||
|
||||
function stop_detect()
|
||||
del_filter_if_present(detect_label)
|
||||
timer = nil
|
||||
mp.set_property("playback-pos", percent_pos)
|
||||
end
|
||||
|
||||
progressive, interlaced_tff, interlaced_bff, interlaced = 0, 1, 2, 3, 4
|
||||
|
||||
function judge()
|
||||
-- get the metadata
|
||||
local result = mp.get_property_native(string.format("vf-metadata/%s", detect_label))
|
||||
num_tff = tonumber(result["lavfi.idet.multiple.tff"])
|
||||
num_bff = tonumber(result["lavfi.idet.multiple.bff"])
|
||||
num_progressive = tonumber(result["lavfi.idet.multiple.progressive"])
|
||||
num_undetermined = tonumber(result["lavfi.idet.multiple.undetermined"])
|
||||
num_interlaced = num_tff + num_bff
|
||||
num_determined = num_interlaced + num_progressive
|
||||
|
||||
mp.msg.verbose("progressive = "..num_progressive)
|
||||
mp.msg.verbose("interlaced-tff = "..num_tff)
|
||||
mp.msg.verbose("interlaced-bff = "..num_bff)
|
||||
mp.msg.verbose("undetermined = "..num_undetermined)
|
||||
|
||||
if num_determined < num_undetermined then
|
||||
mp.msg.warn("majority undetermined frames")
|
||||
end
|
||||
if num_progressive > 20*num_interlaced then
|
||||
return progressive
|
||||
elseif num_tff > 10*num_bff then
|
||||
return interlaced_tff
|
||||
elseif num_bff > 10*num_tff then
|
||||
return interlaced_bff
|
||||
else
|
||||
return interlaced
|
||||
end
|
||||
end
|
||||
|
||||
function judge_field_dominance()
|
||||
verdict = judge()
|
||||
if verdict == progressive then
|
||||
stop_detect()
|
||||
mp.msg.info("progressive: doing nothing")
|
||||
return
|
||||
elseif verdict == interlaced_tff then
|
||||
mp.set_property("field-dominance", "top")
|
||||
elseif verdict == interlaced_bff then
|
||||
mp.set_property("field-dominance", "bottom")
|
||||
elseif verdict == interlaced then
|
||||
mp.set_property("field-dominance", "auto")
|
||||
end
|
||||
|
||||
local cmd = string.format("vf pre @%s:pullup", pullup_label)
|
||||
if not mp.command(cmd) then
|
||||
mp.msg.error("failed to insert pullup filter")
|
||||
stop_detect()
|
||||
return
|
||||
end
|
||||
|
||||
-- redo the detection with the pullup filter to see if it's telecined
|
||||
mp.set_property("percent-pos", percent_pos)
|
||||
timer = mp.add_timeout(detect_seconds, judge_ivtc)
|
||||
end
|
||||
|
||||
function judge_ivtc()
|
||||
verdict = judge()
|
||||
|
||||
if verdict == progressive then
|
||||
mp.msg.info(string.format("telecinied with %s field dominance: using pullup", mp.get_property("field-dominance")))
|
||||
stop_detect()
|
||||
else
|
||||
mp.msg.info(string.format("interlaced with %s field dominance: setting deinterlace property", mp.get_property("field-dominance")))
|
||||
del_filter_if_present(pullup_label)
|
||||
mp.set_property("deinterlace","yes")
|
||||
stop_detect()
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
mp.add_key_binding("ctrl+d", script_name, start_detect)
|
||||
Reference in New Issue
Block a user