blob: 67e4a0912ec739a61fb8711f19bc1efd8dd3f772 [file] [log] [blame]
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08001#include <private/dvr/frame_history.h>
2
3#include <cutils/log.h>
4#include <errno.h>
5#include <sync/sync.h>
6
7#include <pdx/file_handle.h>
8#include <private/dvr/clock_ns.h>
9#include <private/dvr/sync_util.h>
10
11using android::pdx::LocalHandle;
12
13constexpr int kNumFramesToUseForSchedulePrediction = 10;
14constexpr int kDefaultVsyncIntervalPrediction = 1;
15constexpr int kMaxVsyncIntervalPrediction = 4;
16constexpr int kDefaultPendingFrameBufferSize = 10;
17
18namespace android {
19namespace dvr {
20
21FrameHistory::PendingFrame::PendingFrame()
22 : start_ns(0), scheduled_vsync(0), scheduled_finish_ns(0) {}
23
24FrameHistory::PendingFrame::PendingFrame(int64_t start_ns,
25 uint32_t scheduled_vsync,
26 int64_t scheduled_finish_ns,
27 LocalHandle&& fence)
28 : start_ns(start_ns), scheduled_vsync(scheduled_vsync),
29 scheduled_finish_ns(scheduled_finish_ns), fence(std::move(fence)) {}
30
31FrameHistory::FrameHistory() : FrameHistory(kDefaultPendingFrameBufferSize) {}
32
33FrameHistory::FrameHistory(int pending_frame_buffer_size)
34 : pending_frames_(pending_frame_buffer_size),
35 finished_frames_(pending_frame_buffer_size),
36 frame_duration_history_(kNumFramesToUseForSchedulePrediction) {}
37
38void FrameHistory::Reset(int pending_frame_buffer_size) {
39 pending_frames_.Reset(pending_frame_buffer_size);
40 finished_frames_.Reset(pending_frame_buffer_size);
41 frame_duration_history_.Clear();
42}
43
44void FrameHistory::OnFrameStart(uint32_t scheduled_vsync,
45 int64_t scheduled_finish_ns) {
46 if (!pending_frames_.IsEmpty() && !pending_frames_.Back().fence) {
47 // If we don't have a fence set for the previous frame it's because
48 // OnFrameStart() was called twice in a row with no OnFrameSubmit() call. In
49 // that case throw out the pending frame data for the last frame.
50 pending_frames_.PopBack();
51 }
52
53 if (pending_frames_.IsFull()) {
54 ALOGW("Pending frames buffer is full. Discarding pending frame data.");
55 }
56
57 pending_frames_.Append(PendingFrame(GetSystemClockNs(), scheduled_vsync,
58 scheduled_finish_ns, LocalHandle()));
59}
60
61void FrameHistory::OnFrameSubmit(LocalHandle&& fence) {
62 // Add the fence to the previous frame data in pending_frames so we can
63 // track when it finishes.
64 if (!pending_frames_.IsEmpty() && !pending_frames_.Back().fence) {
65 if (fence && pending_frames_.Back().scheduled_vsync != UINT32_MAX)
66 pending_frames_.Back().fence = std::move(fence);
67 else
68 pending_frames_.PopBack();
69 }
70}
71
72void FrameHistory::CheckForFinishedFrames() {
73 if (pending_frames_.IsEmpty())
74 return;
75
76 android::dvr::FenceInfoBuffer fence_info_buffer;
77 while (!pending_frames_.IsEmpty()) {
78 const auto& pending_frame = pending_frames_.Front();
79 if (!pending_frame.fence) {
80 // The frame hasn't been submitted yet, so there's nothing more to do
81 break;
82 }
83
84 int64_t fence_signaled_time = -1;
85 int fence = pending_frame.fence.Get();
86 int sync_result = sync_wait(fence, 0);
87 if (sync_result == 0) {
88 int fence_signaled_result =
89 GetFenceSignaledTimestamp(fence, &fence_info_buffer,
90 &fence_signaled_time);
91 if (fence_signaled_result < 0) {
92 ALOGE("Failed getting signaled timestamp from fence");
93 } else {
94 // The frame is finished. Record the duration and move the frame data
95 // from pending_frames_ to finished_frames_.
96 DvrFrameScheduleResult schedule_result = {};
97 schedule_result.vsync_count = pending_frame.scheduled_vsync;
98 schedule_result.scheduled_frame_finish_ns =
99 pending_frame.scheduled_finish_ns;
100 schedule_result.frame_finish_offset_ns =
101 fence_signaled_time - pending_frame.scheduled_finish_ns;
102 finished_frames_.Append(schedule_result);
103 frame_duration_history_.Append(
104 fence_signaled_time - pending_frame.start_ns);
105 }
106 pending_frames_.PopFront();
107 } else {
108 if (errno != ETIME) {
109 ALOGE("sync_wait on frame fence failed. fence=%d errno=%d (%s).",
110 fence, errno, strerror(errno));
111 }
112 break;
113 }
114 }
115}
116
117int FrameHistory::PredictNextFrameVsyncInterval(int64_t vsync_period_ns) const {
118 if (frame_duration_history_.IsEmpty())
119 return kDefaultVsyncIntervalPrediction;
120
121 double total = 0;
122 for (size_t i = 0; i < frame_duration_history_.GetSize(); ++i)
123 total += frame_duration_history_.Get(i);
124 double avg_duration = total / frame_duration_history_.GetSize();
125
126 return std::min(kMaxVsyncIntervalPrediction,
127 static_cast<int>(avg_duration / vsync_period_ns) + 1);
128}
129
130int FrameHistory::GetPreviousFrameResults(DvrFrameScheduleResult* results,
131 int in_result_count) {
132 int out_result_count =
133 std::min(in_result_count, static_cast<int>(finished_frames_.GetSize()));
134 for (int i = 0; i < out_result_count; ++i) {
135 results[i] = finished_frames_.Get(0);
136 finished_frames_.PopFront();
137 }
138 return out_result_count;
139}
140
141uint32_t FrameHistory::GetCurrentFrameVsync() const {
142 return pending_frames_.IsEmpty() ?
143 UINT32_MAX : pending_frames_.Back().scheduled_vsync;
144}
145
146} // namespace dvr
147} // namespace android