X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=nageru%2Fultimate.lua;h=586b36d7223cb0b29fc6de1d24dd85aa4d45fa55;hb=3c3a5c028bed3922840a2b5ad7ab861fca092582;hp=c57915b321317f86fd0662df1d841e04f7775348;hpb=3bc06e22646cb85dee409039278c4269040c72ff;p=ultimatescore diff --git a/nageru/ultimate.lua b/nageru/ultimate.lua index c57915b..586b36d 100644 --- a/nageru/ultimate.lua +++ b/nageru/ultimate.lua @@ -1,4 +1,4 @@ --- Nageru theme for TFK mini-tournament 2017, based on the default theme. +-- Nageru theme for ultimate productions, based on the default theme. local transition_start = -2.0 local transition_end = -1.0 @@ -51,6 +51,8 @@ local cef_path = Nageru.THEME_PATH:match("(.*)/nageru/") local cef_input = HTMLInput.new("file://" .. cef_path .. "/score.html") cef_input:execute_javascript_async("play()") +local bg_video = VideoInput.new(cef_path .. "/flow-720.mp4", Nageru.VIDEO_FORMAT_YCBCR) + function reload_cef() cef_input:reload() cef_input:execute_javascript_async("play()") @@ -101,7 +103,7 @@ function make_fade_input(chain, signal, live, deint, scale) input:connect_signal(signal) last = input else - input = chain:add_effect(ImageInput.new("tfk_pause.png")) + input = chain:add_effect(ImageInput.new(cef_path .. "/nageru/dsn-bg.png")) last = input end @@ -183,10 +185,15 @@ local fade_chains = make_cartesian_product({ return make_fade_chain(input0_live, input0_deint, input0_scale, input1_live, input1_deint, input1_scale, has_overlay, hq) end) -function make_sbs_input(chain, signal, deint, hq) +function make_sbs_input(chain, signal, deint, has_overlay, hq) local input = chain:add_live_input(not deint, deint) -- Override bounce only if not deinterlacing. input:connect_signal(signal) + local overlay = nil + if has_overlay then + overlay = make_overlay(chain, input) + end + local resample_effect = nil local resize_effect = nil if (hq) then @@ -203,7 +210,8 @@ function make_sbs_input(chain, signal, deint, hq) wb_effect = wb_effect, resample_effect = resample_effect, resize_effect = resize_effect, - padding_effect = padding_effect + padding_effect = padding_effect, + overlay = overlay } end @@ -211,21 +219,23 @@ end function make_sbs_chain(input0_type, input0_overlay, input1_type, hq) local chain = EffectChain.new(16, 9) - local input0 = make_sbs_input(chain, INPUT0_SIGNAL_NUM, input0_type == "livedeint", hq) - local input1 = make_sbs_input(chain, INPUT1_SIGNAL_NUM, input1_type == "livedeint", hq) + local bg = chain:add_video_input(bg_video, false) - -- FIXME: input0_overlay + local input0 = make_sbs_input(chain, INPUT0_SIGNAL_NUM, input0_type == "livedeint", input0_overlay, hq) + local input1 = make_sbs_input(chain, INPUT4_SIGNAL_NUM, input1_type == "livedeint", false, hq) - input0.padding_effect:set_vec4("border_color", 0.0, 0.0, 0.0, 1.0) + input0.padding_effect:set_vec4("border_color", 0.0, 0.0, 0.0, 0.0) input1.padding_effect:set_vec4("border_color", 0.0, 0.0, 0.0, 0.0) - chain:add_effect(OverlayEffect.new(), input0.padding_effect, input1.padding_effect) + local i0 = chain:add_effect(OverlayEffect.new(), bg, input0.padding_effect) + chain:add_effect(OverlayEffect.new(), i0, input1.padding_effect) chain:finalize(hq) return { chain = chain, input0 = input0, - input1 = input1 + input1 = input1, + overlay = input0.overlay -- May be nil. } end @@ -287,7 +297,7 @@ local static_chains = make_cartesian_product({ {true, false} -- hq }, function(hq) local chain = EffectChain.new(16, 9) - local chain_input = chain:add_effect(ImageInput.new("tfk_pause.png")) + local chain_input = chain:add_effect(ImageInput.new(cef_path .. "/nageru/dsn-bg.png")) chain:finalize(hq) return { @@ -450,6 +460,9 @@ function channel_involved_in(channel, signal_num) if is_plain_signal(signal_num) then return channel == (signal_num + 2) end + if signal_num == SBS_SIGNAL_NUM then + return is_sbs_participating_signal(channel - 2) + end if signal_num == STATIC_SIGNAL_NUM then return (channel == NUM_CAMERAS) end @@ -489,6 +502,15 @@ function in_transition(t) return t >= transition_start and t <= transition_end end +function is_sbs_participating_signal(signal_num) + return signal_num == INPUT0_SIGNAL_NUM or signal_num == INPUT4_SIGNAL_NUM +end + +function simple_signal_has_overlay(signal_num) + -- The commentator output has no overlay on it. + return signal_num ~= INPUT4_SIGNAL_NUM +end + -- API ENTRY POINT -- Called every frame. function get_transitions(t) @@ -521,9 +543,9 @@ function get_transitions(t) end -- Various zooms. - if live_signal_num == SBS_SIGNAL_NUM and is_plain_signal(preview_signal_num) then + if live_signal_num == SBS_SIGNAL_NUM and is_sbs_participating_signal(preview_signal_num) then return {"Cut", "Zoom in"} - elseif is_plain_signal(live_signal_num) and preview_signal_num == SBS_SIGNAL_NUM then + elseif is_sbs_participating_signal(live_signal_num) and preview_signal_num == SBS_SIGNAL_NUM then return {"Cut", "Zoom out"} end @@ -602,8 +624,8 @@ function transition_clicked(num, t) return end - if (live_signal_num == SBS_SIGNAL_NUM and is_plain_signal(preview_signal_num)) or - (preview_signal_num == SBS_SIGNAL_NUM and is_plain_signal(live_signal_num)) then + if (live_signal_num == SBS_SIGNAL_NUM and is_sbs_participating_signal(preview_signal_num)) or + (preview_signal_num == SBS_SIGNAL_NUM and is_sbs_participating_signal(live_signal_num)) then start_transition(ZOOM_TRANSITION, t, 1.0) end elseif num == 2 then @@ -648,7 +670,18 @@ function get_fade_chain(signals, t, width, height, input_resolution) chain.mix_effect:set_float("strength_first", 1.0 - tt) chain.mix_effect:set_float("strength_second", tt) - prepare_overlay_live(chain, t) + + -- The commentator output has no overlay on it. + local extra_alpha_factor = 1.0 + if not simple_signal_has_overlay(transition_src_signal) and + not simple_signal_has_overlay(transition_dst_signal) then + extra_alpha_factor = 0.0 + elseif not simple_signal_has_overlay(transition_src_signal) then + extra_alpha_factor = tt + elseif not simple_signal_has_overlay(transition_dst_signal) then + extra_alpha_factor = 1.0 - tt + end + prepare_overlay_live(chain, t, extra_alpha_factor) end return chain.chain, prepare end @@ -656,10 +689,12 @@ end -- SBS code (live_signal_num == SBS_SIGNAL_NUM, or in a transition to/from it). function get_sbs_chain(signals, t, width, height, input_resolution) local input0_type = get_input_type(signals, INPUT0_SIGNAL_NUM) - local input1_type = get_input_type(signals, INPUT1_SIGNAL_NUM) - return sbs_chains[input0_type][false][input1_type][true] -- FIXME: overlay is always false? + local input1_type = get_input_type(signals, INPUT4_SIGNAL_NUM) + return sbs_chains[input0_type][overlay_enabled][input1_type][true] end +local last_rate = 0.0 + -- API ENTRY POINT -- Called every frame. Get the chain for displaying at input , -- where 0 is live, 1 is preview, 2 is the first channel to display @@ -712,6 +747,21 @@ function get_chain(num, t, width, height, signals) end last_resolution = input_resolution + -- Save some CPU time if we're not having SBS on live. + local new_rate + if live_signal_num == SBS_SIGNAL_NUM or + preview_signal_num == SBS_SIGNAL_NUM or + transition_type == ZOOM_TRANSITION then + new_rate = 1.0 + else + new_rate = 0.0001 + end + if new_rate ~= last_rate then + -- Avoid waking up the video thread (which may be sleeping) if the rate is the same. + bg_video:change_rate(new_rate) + last_rate = new_rate + end + if num == 0 then -- Live. -- See if we're in a transition. finish_transitions(t) @@ -720,6 +770,7 @@ function get_chain(num, t, width, height, signals) local chain = get_sbs_chain(signals, t, width, height, input_resolution) prepare = function() prepare_sbs_chain(chain, calc_zoom_progress(t), transition_type, transition_src_signal, transition_dst_signal, width, height, input_resolution) + prepare_overlay_live(chain, t, 1.0) end return chain.chain, prepare elseif transition_type == NO_TRANSITION and live_signal_num == SBS_SIGNAL_NUM then @@ -727,6 +778,7 @@ function get_chain(num, t, width, height, signals) local chain = get_sbs_chain(signals, t, width, height, input_resolution) prepare = function() prepare_sbs_chain(chain, 0.0, NO_TRANSITION, 0, SBS_SIGNAL_NUM, width, height, input_resolution) + prepare_overlay_live(chain, t, 1.0) end return chain.chain, prepare elseif transition_type == FADE_TRANSITION then @@ -734,18 +786,19 @@ function get_chain(num, t, width, height, signals) elseif is_plain_signal(live_signal_num) then local input_type = get_input_type(signals, live_signal_num) local input_scale = needs_scale(signals, live_signal_num, width, height) - local chain = simple_chains[input_type][input_scale][overlay_enabled][true] + local overlay_really_enabled = overlay_enabled and simple_signal_has_overlay(live_signal_num) + local chain = simple_chains[input_type][input_scale][overlay_really_enabled][true] prepare = function() chain.input:connect_signal(live_signal_num) set_scale_parameters_if_needed(chain, width, height) set_neutral_color_from_signal(chain.wb_effect, live_signal_num) - prepare_overlay_live(chain, t) + prepare_overlay_live(chain, t, 1.0) end return chain.chain, prepare elseif live_signal_num == STATIC_SIGNAL_NUM then -- Static picture. local chain = static_chains[true] prepare = function() - prepare_overlay_live(chain, t) + prepare_overlay_live(chain, t, 1.0) -- FIXME: Should this ever be here? end return chain.chain, prepare else @@ -766,7 +819,7 @@ function get_chain(num, t, width, height, signals) end else num = preview_signal_num + 2 - show_overlay = overlay_enabled + show_overlay = overlay_enabled and simple_signal_has_overlay(preview_signal_num) end end @@ -786,7 +839,7 @@ function get_chain(num, t, width, height, signals) end if num == SBS_SIGNAL_NUM + 2 then local input0_type = get_input_type(signals, INPUT0_SIGNAL_NUM) - local input1_type = get_input_type(signals, INPUT1_SIGNAL_NUM) + local input1_type = get_input_type(signals, INPUT4_SIGNAL_NUM) local chain = sbs_chains[input0_type][show_overlay][input1_type][false] prepare = function() prepare_sbs_chain(chain, 0.0, NO_TRANSITION, 0, SBS_SIGNAL_NUM, width, height, input_resolution) @@ -839,14 +892,13 @@ end function prepare_sbs_chain(chain, t, transition_type, src_signal, dst_signal, screen_width, screen_height, input_resolution) chain.input0.input:connect_signal(0) - chain.input1.input:connect_signal(1) + chain.input1.input:connect_signal(4) set_neutral_color(chain.input0.wb_effect, neutral_colors[1]) - set_neutral_color(chain.input1.wb_effect, neutral_colors[2]) + set_neutral_color(chain.input1.wb_effect, neutral_colors[5]) - -- First input is positioned (16,48) from top-left. - -- Second input is positioned (16,48) from the bottom-right. - local pos0 = pos_from_top_left(16, 48, 848, 477, screen_width, screen_height) - local pos1 = pos_from_top_left(1280 - 384 - 16, 720 - 216 - 48, 384, 216, screen_width, screen_height) + -- Both inputs are the same size (true side-by-side). + local pos0 = pos_from_top_left(1280 - 616 - 16, 186, 616, 347, screen_width, screen_height) + local pos1 = pos_from_top_left(16, 186, 616, 347, screen_width, screen_height) local pos_fs = { x0 = 0, y0 = 0, x1 = screen_width, y1 = screen_height } local affine_param @@ -868,7 +920,7 @@ function prepare_sbs_chain(chain, t, transition_type, src_signal, dst_signal, sc if signal == INPUT0_SIGNAL_NUM then affine_param = find_affine_param(pos0, lerp_pos(pos0, pos_fs, real_t)) - elseif signal == INPUT1_SIGNAL_NUM then + elseif signal == INPUT4_SIGNAL_NUM then affine_param = find_affine_param(pos1, lerp_pos(pos1, pos_fs, real_t)) end end @@ -989,10 +1041,11 @@ function place_rectangle(resample_effect, resize_effect, padding_effect, x0, y0, end end -function prepare_overlay_live(chain, t) +function prepare_overlay_live(chain, t, extra_alpha_factor) if chain.overlay then local tt = calc_fade_progress(t, overlay_transition_start, overlay_transition_end) overlay_alpha = overlay_alpha_src + tt * (overlay_alpha_dst - overlay_alpha_src) + overlay_alpha = overlay_alpha * extra_alpha_factor --print("overlay_alpha=" .. overlay_alpha .. " [" .. overlay_alpha_src .. "," .. overlay_alpha_dst .. "]@" .. tt) if t > overlay_transition_end and overlay_alpha_dst == 0.0 then overlay_enabled = false -- Takes effect next frame.