+ if (global_mixer == nullptr) {
+ // No data yet.
+ return;
+ }
+
+ signal_num = theme->map_signal(signal_num);
+
+ BufferedFrame first_frame = theme->input_state->buffered_frames[signal_num][0];
+ if (first_frame.frame == nullptr) {
+ // No data yet.
+ return;
+ }
+ unsigned width, height;
+ {
+ const PBOFrameAllocator::Userdata *userdata = (const PBOFrameAllocator::Userdata *)first_frame.frame->userdata;
+ width = userdata->last_width[first_frame.field_number];
+ height = userdata->last_height[first_frame.field_number];
+ }
+
+ BufferedFrame last_good_frame = first_frame;
+ for (unsigned i = 0; i < inputs.size(); ++i) {
+ BufferedFrame frame = theme->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.
+ frame = last_good_frame;
+ }
+ const PBOFrameAllocator::Userdata *userdata = (const PBOFrameAllocator::Userdata *)frame.frame->userdata;
+
+ if (userdata->last_width[frame.field_number] != width ||
+ userdata->last_height[frame.field_number] != height) {
+ // Resolution changed; reuse last frame/field.
+ frame = last_good_frame;
+ userdata = (const PBOFrameAllocator::Userdata *)frame.frame->userdata;
+ }
+
+ inputs[i]->set_texture_num(0, userdata->tex_y[frame.field_number]);
+ inputs[i]->set_texture_num(1, userdata->tex_cbcr[frame.field_number]);
+ inputs[i]->set_width(userdata->last_width[frame.field_number]);
+ inputs[i]->set_height(userdata->last_height[frame.field_number]);
+
+ last_good_frame = frame;
+ }
+
+ if (deinterlace) {
+ BufferedFrame frame = theme->input_state->buffered_frames[signal_num][0];
+ CHECK(deinterlace_effect->set_int("current_field_position", frame.field_number));
+ }