blob: c9c387f8e4ce76e89b9b3c4c4aafdc0e31875018 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <src/camera/simple_camera/simple_camera_lib/frame_scheduler.h>
#include <src/lib/fxl/command_line.h>
#include <zircon/syscalls.h>
namespace simple_camera {
uint64_t SimpleFrameScheduler::GetPresentationTimeNs(uint64_t capture_time_ns) {
std::lock_guard<std::mutex> lck(times_lock_);
uint64_t now_ns = zx_clock_get_monotonic();
if (now_ns < capture_time_ns) {
FXL_LOG(WARNING) << "Capture time is in the future!"
<< " now: " << now_ns << " capture_time_ns "
<< capture_time_ns;
capture_time_ns = now_ns;
}
if (last_capture_time_ns_ > capture_time_ns) {
FXL_LOG(ERROR) << "Capture times out of sequence! Previous: "
<< last_capture_time_ns_
<< " Current capture time: " << capture_time_ns;
// Just update the capture time. Previous time cannot be in future...
capture_time_ns = last_capture_time_ns_;
}
last_capture_time_ns_ = capture_time_ns;
// To keep the frame rate as smooth as possible, we want to present in
// reference to the capture time:
// presentation_time = capture_time_ns + kLeadDelayNs + kAcquireDelayNs
uint64_t pres_time = capture_time_ns + kLeadDelayNs + kAcquireDelayNs;
// But if the delay is too long between capture and acquire, we're going
// to miss our deadline. In that case, the best thing we can do is just
// add the lead delay, and send it out:
if (now_ns - capture_time_ns > kAcquireDelayNs) {
FXL_VLOG(1) << "Unexpected delay between capture and availability!"
<< " now_ns - capture_time_ns = " << now_ns - capture_time_ns
<< " > AcquireDelay (" << kAcquireDelayNs << ")";
pres_time = now_ns + kLeadDelayNs;
}
// The consumer requires that all presentation times be monotonic.
// At this point, it should be impossible, since capture_time_ns and
// now_ns are monotonic. But we check here incase the logic above
// changes.
FXL_DCHECK(last_presentation_time_ns_ <= pres_time)
<< "Presentation "
<< "time decreased! Previous: " << last_presentation_time_ns_
<< " Current presentation time: " << pres_time;
last_presentation_time_ns_ = pres_time;
return pres_time;
}
// Currently this function only exists as a stub, which complains if we
// are not meeting our assumptions. It could be augmented to
// keep an estimate of the lead time required by the compositor. See this
// class's header file for more information.
void SimpleFrameScheduler::OnFramePresented(uint64_t pres_time,
uint64_t pres_interval,
uint64_t requested_pres_time) {
if (pres_time > requested_pres_time + pres_interval) {
// This means we missed the frame we were targetting.
// Eventually, we will use this information to update Dlead.
FXL_LOG(WARNING) << "Missed rendering deadline!"
<< "\n Requested time: " << requested_pres_time
<< "\n Actual pres time: " << pres_time
<< "\n Difference: "
<< pres_time - requested_pres_time
<< " > presentation_interval (" << pres_interval << ")";
}
}
} // namespace simple_camera