// The theme can't (or at least shouldn't!) call connect_signal() on
// each FFmpeg input, so we'll do it here.
for (const pair<LiveInputWrapper *, FFmpegCapture *> &conn : theme->get_signal_connections()) {
- conn.first->connect_signal_raw(conn.second->get_card_index());
+ conn.first->connect_signal_raw(conn.second->get_card_index(), input_state);
}
// If HDMI/SDI output is active and the user has requested auto mode,
}
signal_num = theme->map_signal(signal_num);
- connect_signal_raw(signal_num);
+ connect_signal_raw(signal_num, *theme->input_state);
}
-void LiveInputWrapper::connect_signal_raw(int signal_num)
+void LiveInputWrapper::connect_signal_raw(int signal_num, const InputState &input_state)
{
- BufferedFrame first_frame = theme->input_state->buffered_frames[signal_num][0];
+ BufferedFrame first_frame = input_state.buffered_frames[signal_num][0];
if (first_frame.frame == nullptr) {
// No data yet.
return;
height = userdata->last_height[first_frame.field_number];
}
- movit::YCbCrLumaCoefficients ycbcr_coefficients = theme->input_state->ycbcr_coefficients[signal_num];
- bool full_range = theme->input_state->full_range[signal_num];
+ movit::YCbCrLumaCoefficients ycbcr_coefficients = input_state.ycbcr_coefficients[signal_num];
+ bool full_range = input_state.full_range[signal_num];
- if (theme->input_state->ycbcr_coefficients_auto[signal_num]) {
+ if (input_state.ycbcr_coefficients_auto[signal_num]) {
full_range = false;
// The Blackmagic driver docs claim that the device outputs Y'CbCr
BufferedFrame last_good_frame = first_frame;
for (unsigned i = 0; i < max(ycbcr_inputs.size(), rgba_inputs.size()); ++i) {
- BufferedFrame frame = theme->input_state->buffered_frames[signal_num][i];
+ BufferedFrame frame = input_state.buffered_frames[signal_num][i];
if (frame.frame == nullptr) {
// Not enough data; reuse last frame (well, field).
// This is suboptimal, but we have nothing better.
}
if (deinterlace) {
- BufferedFrame frame = theme->input_state->buffered_frames[signal_num][0];
+ BufferedFrame frame = input_state.buffered_frames[signal_num][0];
CHECK(deinterlace_effect->set_int("current_field_position", frame.field_number));
}
}
chain.setup_chain = [this, funcref, input_state]{
unique_lock<mutex> lock(m);
+ assert(this->input_state == nullptr);
this->input_state = &input_state;
// Set up state, including connecting signals.
exit(1);
}
assert(lua_gettop(L) == 0);
+
+ this->input_state = nullptr;
};
// TODO: Can we do better, e.g. by running setup_chain() and seeing what it references?
std::mutex m;
lua_State *L; // Protected by <m>.
- const InputState *input_state; // Protected by <m>. Only set temporarily, during chain setup.
+ const InputState *input_state = nullptr; // Protected by <m>. Only set temporarily, during chain setup.
movit::ResourcePool *resource_pool;
int num_channels;
unsigned num_cards;
// Note: <override_bounce> is irrelevant for PixelFormat_8BitBGRA.
LiveInputWrapper(Theme *theme, movit::EffectChain *chain, bmusb::PixelFormat pixel_format, bool override_bounce, bool deinterlace);
- void connect_signal(int signal_num);
- void connect_signal_raw(int signal_num);
+ void connect_signal(int signal_num); // Must be called with the theme's <m> lock held, since it accesses theme->input_state.
+ void connect_signal_raw(int signal_num, const InputState &input_state);
movit::Effect *get_effect() const
{
if (deinterlace) {