CHECK(init_movit(MOVIT_SHADER_DIR, MOVIT_DEBUG_OFF));
check_error();
+ // Since we allow non-bouncing 4:2:2 YCbCrInputs, effective subpixel precision
+ // will be halved when sampling them, and we need to compensate here.
+ movit_texel_subpixel_precision /= 2.0;
+
resource_pool.reset(new ResourcePool);
theme.reset(new Theme("theme.lua", resource_pool.get()));
output_channel[OUTPUT_LIVE].parent = this;
int EffectChain_add_live_input(lua_State* L)
{
- assert(lua_gettop(L) == 1);
+ assert(lua_gettop(L) == 2);
Theme *theme = get_theme_updata(L);
EffectChain *chain = (EffectChain *)luaL_checkudata(L, 1, "EffectChain");
- return wrap_lua_object<LiveInputWrapper>(L, "LiveInputWrapper", theme, chain);
+ bool override_bounce = checkbool(L, 2);
+ return wrap_lua_object<LiveInputWrapper>(L, "LiveInputWrapper", theme, chain, override_bounce);
}
int EffectChain_add_effect(lua_State* L)
} // namespace
-LiveInputWrapper::LiveInputWrapper(Theme *theme, EffectChain *chain)
+LiveInputWrapper::LiveInputWrapper(Theme *theme, EffectChain *chain, bool override_bounce)
: theme(theme)
{
ImageFormat inout_format;
input_ycbcr_format.luma_coefficients = YCBCR_REC_601;
input_ycbcr_format.full_range = false;
- input = new YCbCrInput(inout_format, input_ycbcr_format, WIDTH, HEIGHT, YCBCR_INPUT_SPLIT_Y_AND_CBCR);
+ if (override_bounce) {
+ input = new NonBouncingYCbCrInput(inout_format, input_ycbcr_format, WIDTH, HEIGHT, YCBCR_INPUT_SPLIT_Y_AND_CBCR);
+ } else {
+ input = new YCbCrInput(inout_format, input_ycbcr_format, WIDTH, HEIGHT, YCBCR_INPUT_SPLIT_Y_AND_CBCR);
+ }
chain->add_input(input);
}
#include <movit/effect_chain.h>
#include <movit/ycbcr_input.h>
+class NonBouncingYCbCrInput : public movit::YCbCrInput {
+public:
+ NonBouncingYCbCrInput(const movit::ImageFormat &image_format,
+ const movit::YCbCrFormat &ycbcr_format,
+ unsigned width, unsigned height,
+ movit::YCbCrInputSplitting ycbcr_input_splitting = movit::YCBCR_INPUT_PLANAR)
+ : movit::YCbCrInput(image_format, ycbcr_format, width, height, ycbcr_input_splitting) {}
+
+ bool override_disable_bounce() const override { return true; }
+};
+
class Theme {
public:
Theme(const char *filename, movit::ResourcePool *resource_pool);
class LiveInputWrapper {
public:
- LiveInputWrapper(Theme *theme, movit::EffectChain *chain);
+ LiveInputWrapper(Theme *theme, movit::EffectChain *chain, bool override_bounce);
void connect_signal(int signal_num);
movit::YCbCrInput *get_input() const
-- The main live chain.
function make_sbs_chain(hq)
local chain = EffectChain.new(16, 9)
- local input0 = chain:add_live_input()
+ local input0 = chain:add_live_input(true)
input0:connect_signal(0)
- local input1 = chain:add_live_input()
+ local input1 = chain:add_live_input(true)
input1:connect_signal(1)
local resample_effect = nil
-- A chain to fade between two inputs (live chain only)
local fade_chain_hq = EffectChain.new(16, 9)
-local fade_chain_hq_input0 = fade_chain_hq:add_live_input()
-local fade_chain_hq_input1 = fade_chain_hq:add_live_input()
+local fade_chain_hq_input0 = fade_chain_hq:add_live_input(true)
+local fade_chain_hq_input1 = fade_chain_hq:add_live_input(true)
fade_chain_hq_input0:connect_signal(0)
fade_chain_hq_input1:connect_signal(1)
local fade_chain_mix_effect = fade_chain_hq:add_effect(MixEffect.new(), fade_chain_hq_input0, fade_chain_hq_input1)
-- A chain to show a single input on screen (HQ version).
local simple_chain_hq = EffectChain.new(16, 9)
-local simple_chain_hq_input = simple_chain_hq:add_live_input()
+local simple_chain_hq_input = simple_chain_hq:add_live_input(true)
simple_chain_hq_input:connect_signal(0) -- First input card. Can be changed whenever you want.
simple_chain_hq:finalize(true)
-- A chain to show a single input on screen (LQ version).
local simple_chain_lq = EffectChain.new(16, 9)
-local simple_chain_lq_input = simple_chain_lq:add_live_input()
+local simple_chain_lq_input = simple_chain_lq:add_live_input(true)
simple_chain_lq_input:connect_signal(0) -- First input card. Can be changed whenever you want.
simple_chain_lq:finalize(false)