232{
233 const auto& ring = layer.ring;
234 const uint64_t head = ring->get_write_head();
235 if (head < 3) {
236 return;
237 }
238
239 place(state, layer, head, ring->get_frame_rate(), 2.0, elapsed);
240
241 const double whole = std::max(std::floor(layer.position), 0.0);
242 const auto frame = static_cast<uint64_t>(whole);
243 if (!ring->is_frame_available(frame)) {
244 if (!layer.missed) {
246 "Chimera layer {} is outside the ring, holding its last frame",
index);
247 layer.missed = true;
248 }
249 return;
250 }
251 layer.missed = false;
252
253 std::span<const uint8_t>
pixels = ring->get_frame_pixels(frame);
255 return;
256 }
257
258 const double fraction = layer.position - whole;
259 if (layer.smooth && fraction > 0.0 && ring->is_frame_available(frame + 1)) {
260 const auto next = ring->get_frame_pixels(frame + 1);
261 layer.scratch.resize(
pixels.size());
262 if (!next.empty()
264 pixels = std::span<const uint8_t>(layer.scratch);
265 }
266 }
267
268 const bool same_extent = ring->get_width() == state.buffer->get_width()
269 && ring->get_height() == state.buffer->get_height()
270 && ring->get_format() == state.buffer->get_format();
271
272 bool stored = false;
273 if (same_extent) {
274 stored = state.buffer->submit_layer(
index,
pixels);
276 ring->get_width(), ring->get_height(),
278 ring->get_format(),
pixels)) {
279 stored = state.buffer->submit_layer(
index, *
image);
280 }
281
282 if (stored) {
284 glm::vec4(static_cast<float>(elapsed), static_cast<float>(static_cast<double>(head) - layer.position),
285 static_cast<float>(layer.position), 1.0F));
286 }
287}
#define MF_WARN(comp, ctx,...)
const std::vector< float > * pixels
static void stamp(State &state, uint32_t index, const glm::vec4 &timing)
static void place(const State &state, Layer &layer, uint64_t head, double rate, double nearest, double elapsed)
static uint32_t get_channel_count(ImageFormat format)
Get the number of color channels for a given format.
@ CoroutineScheduling
Coroutine scheduling and temporal coordination (Vruta::TaskScheduler)
@ Kriya
Automatable tasks and fluent scheduling api for Nodes and Buffers.
bool blend_frames(ImageFormat format, std::span< const uint8_t > a, std::span< const uint8_t > b, uint8_t *out, double weight)
Linearly blend two frames of the same size and format.
static std::optional< ImageData > from_bytes(uint32_t width, uint32_t height, uint32_t channels, ImageFormat format, std::span< const uint8_t > bytes)
Build an ImageData from raw pixel bytes in format's layout.