Get an openshot::Frame object for a specific frame number of this reader.
| 948 | |
| 949 | // Get an openshot::Frame object for a specific frame number of this reader. |
| 950 | std::shared_ptr<Frame> Timeline::GetFrame(int64_t requested_frame) |
| 951 | { |
| 952 | // Adjust out of bounds frame number |
| 953 | if (requested_frame < 1) |
| 954 | requested_frame = 1; |
| 955 | const int64_t max_frame = GetMaxFrame(); |
| 956 | const bool past_timeline_end = (max_frame > 0 && requested_frame > max_frame); |
| 957 | |
| 958 | // Check cache |
| 959 | std::shared_ptr<Frame> frame; |
| 960 | if (!past_timeline_end) |
| 961 | frame = final_cache->GetFrame(requested_frame); |
| 962 | if (frame) { |
| 963 | // Debug output |
| 964 | ZmqLogger::Instance()->AppendDebugMethod( |
| 965 | "Timeline::GetFrame (Cached frame found)", |
| 966 | "requested_frame", requested_frame); |
| 967 | |
| 968 | // Return cached frame |
| 969 | return frame; |
| 970 | } |
| 971 | else |
| 972 | { |
| 973 | // Prevent async calls to the following code |
| 974 | const std::lock_guard<std::recursive_mutex> lock(getFrameMutex); |
| 975 | |
| 976 | // Check cache 2nd time |
| 977 | std::shared_ptr<Frame> frame; |
| 978 | if (!past_timeline_end) |
| 979 | frame = final_cache->GetFrame(requested_frame); |
| 980 | if (frame) { |
| 981 | // Debug output |
| 982 | ZmqLogger::Instance()->AppendDebugMethod( |
| 983 | "Timeline::GetFrame (Cached frame found on 2nd check)", |
| 984 | "requested_frame", requested_frame); |
| 985 | |
| 986 | // Return cached frame |
| 987 | return frame; |
| 988 | } else { |
| 989 | // Get a list of clips that intersect with the requested section of timeline |
| 990 | // This also opens the readers for intersecting clips, and marks non-intersecting clips as 'needs closing' |
| 991 | std::vector<Clip *> nearby_clips; |
| 992 | nearby_clips = find_intersecting_clips(requested_frame, 1, true); |
| 993 | |
| 994 | // Debug output |
| 995 | ZmqLogger::Instance()->AppendDebugMethod( |
| 996 | "Timeline::GetFrame (processing frame)", |
| 997 | "requested_frame", requested_frame, |
| 998 | "omp_get_thread_num()", omp_get_thread_num()); |
| 999 | |
| 1000 | // Init some basic properties about this frame |
| 1001 | int samples_in_frame = Frame::GetSamplesPerFrame(requested_frame, info.fps, info.sample_rate, info.channels); |
| 1002 | |
| 1003 | // Create blank frame (which will become the requested frame) |
| 1004 | std::shared_ptr<Frame> new_frame(std::make_shared<Frame>(requested_frame, preview_width, preview_height, "#000000", samples_in_frame, info.channels)); |
| 1005 | new_frame->AddAudioSilence(samples_in_frame); |
| 1006 | new_frame->SampleRate(info.sample_rate); |
| 1007 | new_frame->ChannelsLayout(info.channel_layout); |
no test coverage detected