mirror of
https://github.com/mpv-player/mpv
synced 2025-01-15 19:42:53 +00:00
45f822593f
I don't actually deinterlace ever but allegedly this is better than yadif, and there's no real reason to not have this be the fallback deinterlace when we're not using hw frames. Also change various mentions of yadif to bwdif. Ref #12835.
157 lines
5.3 KiB
Lua
157 lines
5.3 KiB
Lua
-- 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 filters
|
|
-- ``vf=idet,lavfi-pullup,idet``. After 4 seconds, it removes these
|
|
-- filters and decides whether the content is progressive, interlaced, or
|
|
-- telecined and the interlacing field dominance.
|
|
--
|
|
-- Based on this information, it may set mpv's ``deinterlace`` property (which
|
|
-- usually inserts the bwdif filter), or insert the ``pullup`` filter if the
|
|
-- content is telecined. It also sets field dominance with lavfi setfield.
|
|
--
|
|
-- OPTIONS:
|
|
-- The default detection time may be overridden by adding
|
|
--
|
|
-- --script-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
|
|
|
|
require "mp.msg"
|
|
|
|
script_name = mp.get_script_name()
|
|
detect_label = string.format("%s-detect", script_name)
|
|
pullup_label = string.format("%s", script_name)
|
|
dominance_label = string.format("%s-dominance", script_name)
|
|
ivtc_detect_label = string.format("%s-ivtc-detect", 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
|
|
|
|
local function add_vf(label, filter)
|
|
return mp.command(('vf add @%s:%s'):format(label, filter))
|
|
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)
|
|
del_filter_if_present(dominance_label)
|
|
|
|
-- insert the detection filters
|
|
if not (add_vf(detect_label, 'idet') and
|
|
add_vf(dominance_label, 'setfield=mode=auto') and
|
|
add_vf(pullup_label, 'lavfi-pullup') and
|
|
add_vf(ivtc_detect_label, 'idet')) then
|
|
mp.msg.error("failed to insert detection filters")
|
|
return
|
|
end
|
|
|
|
-- wait to gather data
|
|
timer = mp.add_timeout(detect_seconds, select_filter)
|
|
end
|
|
|
|
function stop_detect()
|
|
del_filter_if_present(detect_label)
|
|
del_filter_if_present(ivtc_detect_label)
|
|
timer = nil
|
|
end
|
|
|
|
progressive, interlaced_tff, interlaced_bff, interlaced = 0, 1, 2, 3, 4
|
|
|
|
function judge(label)
|
|
-- get the metadata
|
|
local result = mp.get_property_native(string.format("vf-metadata/%s", label))
|
|
local num_tff = tonumber(result["lavfi.idet.multiple.tff"])
|
|
local num_bff = tonumber(result["lavfi.idet.multiple.bff"])
|
|
local num_progressive = tonumber(result["lavfi.idet.multiple.progressive"])
|
|
local num_undetermined = tonumber(result["lavfi.idet.multiple.undetermined"])
|
|
local num_interlaced = num_tff + num_bff
|
|
local num_determined = num_interlaced + num_progressive
|
|
|
|
mp.msg.verbose(label.." progressive = "..num_progressive)
|
|
mp.msg.verbose(label.." interlaced-tff = "..num_tff)
|
|
mp.msg.verbose(label.." interlaced-bff = "..num_bff)
|
|
mp.msg.verbose(label.." 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 select_filter()
|
|
-- handle the first detection filter results
|
|
local verdict = judge(detect_label)
|
|
local ivtc_verdict = judge(ivtc_detect_label)
|
|
local dominance = "auto"
|
|
if verdict == progressive then
|
|
mp.msg.info("progressive: doing nothing")
|
|
stop_detect()
|
|
del_filter_if_present(dominance_label)
|
|
del_filter_if_present(pullup_label)
|
|
return
|
|
else
|
|
if verdict == interlaced_tff then
|
|
dominance = "tff"
|
|
add_vf(dominance_label, 'setfield=mode='..dominance)
|
|
elseif verdict == interlaced_bff then
|
|
dominance = "bff"
|
|
add_vf(dominance_label, 'setfield=mode='..dominance)
|
|
else
|
|
del_filter_if_present(dominance_label)
|
|
end
|
|
end
|
|
|
|
-- handle the ivtc detection filter results
|
|
if ivtc_verdict == progressive then
|
|
mp.msg.info(string.format("telecined with %s field dominance: using pullup", dominance))
|
|
stop_detect()
|
|
else
|
|
mp.msg.info(string.format("interlaced with %s field dominance: setting deinterlace property", dominance))
|
|
del_filter_if_present(pullup_label)
|
|
mp.set_property("deinterlace","yes")
|
|
stop_detect()
|
|
end
|
|
end
|
|
|
|
mp.add_key_binding("ctrl+d", script_name, start_detect)
|