diff --git a/src/Timeline.cpp b/src/Timeline.cpp
index 61bf5905..6b3b015e 100644
--- a/src/Timeline.cpp
+++ b/src/Timeline.cpp
@@ -874,128 +874,139 @@ std::shared_ptr Timeline::GetFrame(int64_t requested_frame)
// Prevent async calls to the following code
const std::lock_guard lock(getFrameMutex);
- // Get a list of clips that intersect with the requested section of timeline
- // This also opens the readers for intersecting clips, and marks non-intersecting clips as 'needs closing'
- std::vector nearby_clips;
- nearby_clips = find_intersecting_clips(requested_frame, 1, true);
+ // Check cache 2nd time
+ std::shared_ptr frame;
+ frame = final_cache->GetFrame(requested_frame);
+ if (frame) {
+ // Debug output
+ ZmqLogger::Instance()->AppendDebugMethod(
+ "Timeline::GetFrame (Cached frame found on 2nd check)",
+ "requested_frame", requested_frame);
- // Debug output
- ZmqLogger::Instance()->AppendDebugMethod(
- "Timeline::GetFrame (processing frame)",
- "requested_frame", requested_frame,
- "omp_get_thread_num()", omp_get_thread_num());
-
- // Init some basic properties about this frame
- int samples_in_frame = Frame::GetSamplesPerFrame(requested_frame, info.fps, info.sample_rate, info.channels);
-
- // Create blank frame (which will become the requested frame)
- std::shared_ptr new_frame(std::make_shared(requested_frame, preview_width, preview_height, "#000000", samples_in_frame, info.channels));
- new_frame->AddAudioSilence(samples_in_frame);
- new_frame->SampleRate(info.sample_rate);
- new_frame->ChannelsLayout(info.channel_layout);
-
- // Debug output
- ZmqLogger::Instance()->AppendDebugMethod(
- "Timeline::GetFrame (Adding solid color)",
- "requested_frame", requested_frame,
- "info.width", info.width,
- "info.height", info.height);
-
- // Add Background Color to 1st layer (if animated or not black)
- if ((color.red.GetCount() > 1 || color.green.GetCount() > 1 || color.blue.GetCount() > 1) ||
- (color.red.GetValue(requested_frame) != 0.0 || color.green.GetValue(requested_frame) != 0.0 || color.blue.GetValue(requested_frame) != 0.0))
- new_frame->AddColor(preview_width, preview_height, color.GetColorHex(requested_frame));
-
- // Debug output
- ZmqLogger::Instance()->AppendDebugMethod(
- "Timeline::GetFrame (Loop through clips)",
- "requested_frame", requested_frame,
- "clips.size()", clips.size(),
- "nearby_clips.size()", nearby_clips.size());
-
- // Find Clips near this time
- for (auto clip : nearby_clips)
- {
- long clip_start_position = round(clip->Position() * info.fps.ToDouble()) + 1;
- long clip_end_position = round((clip->Position() + clip->Duration()) * info.fps.ToDouble());
- bool does_clip_intersect = (clip_start_position <= requested_frame && clip_end_position >= requested_frame);
+ // Return cached frame
+ return frame;
+ } else {
+ // Get a list of clips that intersect with the requested section of timeline
+ // This also opens the readers for intersecting clips, and marks non-intersecting clips as 'needs closing'
+ std::vector nearby_clips;
+ nearby_clips = find_intersecting_clips(requested_frame, 1, true);
// Debug output
ZmqLogger::Instance()->AppendDebugMethod(
- "Timeline::GetFrame (Does clip intersect)",
- "requested_frame", requested_frame,
- "clip->Position()", clip->Position(),
- "clip->Duration()", clip->Duration(),
- "does_clip_intersect", does_clip_intersect);
+ "Timeline::GetFrame (processing frame)",
+ "requested_frame", requested_frame,
+ "omp_get_thread_num()", omp_get_thread_num());
- // Clip is visible
- if (does_clip_intersect)
- {
- // Determine if clip is "top" clip on this layer (only happens when multiple clips are overlapping)
- bool is_top_clip = true;
- float max_volume = 0.0;
- for (auto nearby_clip : nearby_clips)
- {
- long nearby_clip_start_position = round(nearby_clip->Position() * info.fps.ToDouble()) + 1;
- long nearby_clip_end_position = round((nearby_clip->Position() + nearby_clip->Duration()) * info.fps.ToDouble()) + 1;
- long nearby_clip_start_frame = (nearby_clip->Start() * info.fps.ToDouble()) + 1;
- long nearby_clip_frame_number = requested_frame - nearby_clip_start_position + nearby_clip_start_frame;
+ // Init some basic properties about this frame
+ int samples_in_frame = Frame::GetSamplesPerFrame(requested_frame, info.fps, info.sample_rate, info.channels);
- // Determine if top clip
- if (clip->Id() != nearby_clip->Id() && clip->Layer() == nearby_clip->Layer() &&
+ // Create blank frame (which will become the requested frame)
+ std::shared_ptr new_frame(std::make_shared(requested_frame, preview_width, preview_height, "#000000", samples_in_frame, info.channels));
+ new_frame->AddAudioSilence(samples_in_frame);
+ new_frame->SampleRate(info.sample_rate);
+ new_frame->ChannelsLayout(info.channel_layout);
+
+ // Debug output
+ ZmqLogger::Instance()->AppendDebugMethod(
+ "Timeline::GetFrame (Adding solid color)",
+ "requested_frame", requested_frame,
+ "info.width", info.width,
+ "info.height", info.height);
+
+ // Add Background Color to 1st layer (if animated or not black)
+ if ((color.red.GetCount() > 1 || color.green.GetCount() > 1 || color.blue.GetCount() > 1) ||
+ (color.red.GetValue(requested_frame) != 0.0 || color.green.GetValue(requested_frame) != 0.0 ||
+ color.blue.GetValue(requested_frame) != 0.0))
+ new_frame->AddColor(preview_width, preview_height, color.GetColorHex(requested_frame));
+
+ // Debug output
+ ZmqLogger::Instance()->AppendDebugMethod(
+ "Timeline::GetFrame (Loop through clips)",
+ "requested_frame", requested_frame,
+ "clips.size()", clips.size(),
+ "nearby_clips.size()", nearby_clips.size());
+
+ // Find Clips near this time
+ for (auto clip : nearby_clips) {
+ long clip_start_position = round(clip->Position() * info.fps.ToDouble()) + 1;
+ long clip_end_position = round((clip->Position() + clip->Duration()) * info.fps.ToDouble());
+ bool does_clip_intersect = (clip_start_position <= requested_frame && clip_end_position >= requested_frame);
+
+ // Debug output
+ ZmqLogger::Instance()->AppendDebugMethod(
+ "Timeline::GetFrame (Does clip intersect)",
+ "requested_frame", requested_frame,
+ "clip->Position()", clip->Position(),
+ "clip->Duration()", clip->Duration(),
+ "does_clip_intersect", does_clip_intersect);
+
+ // Clip is visible
+ if (does_clip_intersect) {
+ // Determine if clip is "top" clip on this layer (only happens when multiple clips are overlapping)
+ bool is_top_clip = true;
+ float max_volume = 0.0;
+ for (auto nearby_clip : nearby_clips) {
+ long nearby_clip_start_position = round(nearby_clip->Position() * info.fps.ToDouble()) + 1;
+ long nearby_clip_end_position = round((nearby_clip->Position() + nearby_clip->Duration()) * info.fps.ToDouble()) + 1;
+ long nearby_clip_start_frame = (nearby_clip->Start() * info.fps.ToDouble()) + 1;
+ long nearby_clip_frame_number = requested_frame - nearby_clip_start_position + nearby_clip_start_frame;
+
+ // Determine if top clip
+ if (clip->Id() != nearby_clip->Id() && clip->Layer() == nearby_clip->Layer() &&
nearby_clip_start_position <= requested_frame && nearby_clip_end_position >= requested_frame &&
nearby_clip_start_position > clip_start_position && is_top_clip == true) {
- is_top_clip = false;
- }
+ is_top_clip = false;
+ }
- // Determine max volume of overlapping clips
- if (nearby_clip->Reader() && nearby_clip->Reader()->info.has_audio &&
+ // Determine max volume of overlapping clips
+ if (nearby_clip->Reader() && nearby_clip->Reader()->info.has_audio &&
nearby_clip->has_audio.GetInt(nearby_clip_frame_number) != 0 &&
nearby_clip_start_position <= requested_frame && nearby_clip_end_position >= requested_frame) {
max_volume += nearby_clip->volume.GetValue(nearby_clip_frame_number);
+ }
}
+
+ // Determine the frame needed for this clip (based on the position on the timeline)
+ long clip_start_frame = (clip->Start() * info.fps.ToDouble()) + 1;
+ long clip_frame_number = requested_frame - clip_start_position + clip_start_frame;
+
+ // Debug output
+ ZmqLogger::Instance()->AppendDebugMethod(
+ "Timeline::GetFrame (Calculate clip's frame #)",
+ "clip->Position()", clip->Position(),
+ "clip->Start()", clip->Start(),
+ "info.fps.ToFloat()", info.fps.ToFloat(),
+ "clip_frame_number", clip_frame_number);
+
+ // Add clip's frame as layer
+ add_layer(new_frame, clip, clip_frame_number, is_top_clip, max_volume);
+
+ } else {
+ // Debug output
+ ZmqLogger::Instance()->AppendDebugMethod(
+ "Timeline::GetFrame (clip does not intersect)",
+ "requested_frame", requested_frame,
+ "does_clip_intersect", does_clip_intersect);
}
- // Determine the frame needed for this clip (based on the position on the timeline)
- long clip_start_frame = (clip->Start() * info.fps.ToDouble()) + 1;
- long clip_frame_number = requested_frame - clip_start_position + clip_start_frame;
+ } // end clip loop
- // Debug output
- ZmqLogger::Instance()->AppendDebugMethod(
- "Timeline::GetFrame (Calculate clip's frame #)",
- "clip->Position()", clip->Position(),
- "clip->Start()", clip->Start(),
- "info.fps.ToFloat()", info.fps.ToFloat(),
- "clip_frame_number", clip_frame_number);
-
- // Add clip's frame as layer
- add_layer(new_frame, clip, clip_frame_number, is_top_clip, max_volume);
-
- } else {
- // Debug output
- ZmqLogger::Instance()->AppendDebugMethod(
- "Timeline::GetFrame (clip does not intersect)",
+ // Debug output
+ ZmqLogger::Instance()->AppendDebugMethod(
+ "Timeline::GetFrame (Add frame to cache)",
"requested_frame", requested_frame,
- "does_clip_intersect", does_clip_intersect);
- }
+ "info.width", info.width,
+ "info.height", info.height);
- } // end clip loop
+ // Set frame # on mapped frame
+ new_frame->SetFrameNumber(requested_frame);
- // Debug output
- ZmqLogger::Instance()->AppendDebugMethod(
- "Timeline::GetFrame (Add frame to cache)",
- "requested_frame", requested_frame,
- "info.width", info.width,
- "info.height", info.height);
+ // Add final frame to cache
+ final_cache->Add(new_frame);
- // Set frame # on mapped frame
- new_frame->SetFrameNumber(requested_frame);
-
- // Add final frame to cache
- final_cache->Add(new_frame);
-
- // Return frame (or blank frame)
- return new_frame;
+ // Return frame (or blank frame)
+ return new_frame;
+ }
}
}