Timeline now checks cache 2nd time, after mutex - incase previous call generated the same frame

This commit is contained in:
Jonathan Thomas
2022-10-11 23:01:26 -05:00
parent 5f9c4e06d8
commit 8fcdbc9d03

View File

@@ -874,128 +874,139 @@ std::shared_ptr<Frame> Timeline::GetFrame(int64_t requested_frame)
// Prevent async calls to the following code
const std::lock_guard<std::recursive_mutex> 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<Clip*> nearby_clips;
nearby_clips = find_intersecting_clips(requested_frame, 1, true);
// Check cache 2nd time
std::shared_ptr<Frame> 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<Frame> new_frame(std::make_shared<Frame>(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<Clip *> 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<Frame> new_frame(std::make_shared<Frame>(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;
}
}
}