From e68cc34c990907fb8c5fe2a3c690671bac38e618 Mon Sep 17 00:00:00 2001 From: Kevin Mitchell Date: Sun, 19 Oct 2014 23:05:12 -0700 Subject: 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. --- TOOLS/lua/autodeint.lua | 164 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 TOOLS/lua/autodeint.lua diff --git a/TOOLS/lua/autodeint.lua b/TOOLS/lua/autodeint.lua new file mode 100644 index 0000000000..d834f96a91 --- /dev/null +++ b/TOOLS/lua/autodeint.lua @@ -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= +-- +-- 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) -- cgit v1.2.3