1dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar/*
2dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar * Copyright (C) 2014 The Android Open Source Project
3dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar *
4dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar * Licensed under the Apache License, Version 2.0 (the "License");
5dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar * you may not use this file except in compliance with the License.
6dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar * You may obtain a copy of the License at
7dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar *
8dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar *      http://www.apache.org/licenses/LICENSE-2.0
9dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar *
10dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar * Unless required by applicable law or agreed to in writing, software
11dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar * distributed under the License is distributed on an "AS IS" BASIS,
12dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar * See the License for the specific language governing permissions and
14dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar * limitations under the License.
15dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar */
16dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
17dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar//#define LOG_NDEBUG 0
18dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar#define LOG_TAG "VideoFrameScheduler"
19dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar#include <utils/Log.h>
20dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar#define ATRACE_TAG ATRACE_TAG_VIDEO
21dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar#include <utils/Trace.h>
22dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
23dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar#include <sys/time.h>
24dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
25dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar#include <binder/IServiceManager.h>
26dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar#include <gui/ISurfaceComposer.h>
27dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar#include <ui/DisplayStatInfo.h>
28dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
29dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar#include <media/stagefright/foundation/ADebug.h>
30c416becd966945fca5fa7fb45ac51f84d1d8cd20Lajos Molnar#include <media/stagefright/foundation/AUtils.h>
31dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
32dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar#include "VideoFrameScheduler.h"
33dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
34dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnarnamespace android {
35dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
36dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnarstatic const nsecs_t kNanosIn1s = 1000000000;
37dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
38c851b5de495169d7e9528644c2592746021bd968Lajos Molnartemplate<class T>
39c851b5de495169d7e9528644c2592746021bd968Lajos Molnarstatic int compare(const T *lhs, const T *rhs) {
40c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    if (*lhs < *rhs) {
41c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        return -1;
42c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    } else if (*lhs > *rhs) {
43c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        return 1;
44c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    } else {
45c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        return 0;
46c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    }
47c851b5de495169d7e9528644c2592746021bd968Lajos Molnar}
48c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
49c851b5de495169d7e9528644c2592746021bd968Lajos Molnar/* ======================================================================= */
50c851b5de495169d7e9528644c2592746021bd968Lajos Molnar/*                                   PLL                                   */
51c851b5de495169d7e9528644c2592746021bd968Lajos Molnar/* ======================================================================= */
52c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
53c851b5de495169d7e9528644c2592746021bd968Lajos Molnarstatic const size_t kMinSamplesToStartPrime = 3;
54c851b5de495169d7e9528644c2592746021bd968Lajos Molnarstatic const size_t kMinSamplesToStopPrime = VideoFrameScheduler::kHistorySize;
55c851b5de495169d7e9528644c2592746021bd968Lajos Molnarstatic const size_t kMinSamplesToEstimatePeriod = 3;
56c851b5de495169d7e9528644c2592746021bd968Lajos Molnarstatic const size_t kMaxSamplesToEstimatePeriod = VideoFrameScheduler::kHistorySize;
57c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
58c851b5de495169d7e9528644c2592746021bd968Lajos Molnarstatic const size_t kPrecision = 12;
59c851b5de495169d7e9528644c2592746021bd968Lajos Molnarstatic const size_t kErrorThreshold = (1 << (kPrecision * 2)) / 10;
60c851b5de495169d7e9528644c2592746021bd968Lajos Molnarstatic const int64_t kMultiplesThresholdDiv = 4;            // 25%
61c851b5de495169d7e9528644c2592746021bd968Lajos Molnarstatic const int64_t kReFitThresholdDiv = 100;              // 1%
62c851b5de495169d7e9528644c2592746021bd968Lajos Molnarstatic const nsecs_t kMaxAllowedFrameSkip = kNanosIn1s;     // 1 sec
63c851b5de495169d7e9528644c2592746021bd968Lajos Molnarstatic const nsecs_t kMinPeriod = kNanosIn1s / 120;         // 120Hz
64c851b5de495169d7e9528644c2592746021bd968Lajos Molnarstatic const nsecs_t kRefitRefreshPeriod = 10 * kNanosIn1s; // 10 sec
65c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
66c851b5de495169d7e9528644c2592746021bd968Lajos MolnarVideoFrameScheduler::PLL::PLL()
67c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    : mPeriod(-1),
68c851b5de495169d7e9528644c2592746021bd968Lajos Molnar      mPhase(0),
69c851b5de495169d7e9528644c2592746021bd968Lajos Molnar      mPrimed(false),
70c851b5de495169d7e9528644c2592746021bd968Lajos Molnar      mSamplesUsedForPriming(0),
71c851b5de495169d7e9528644c2592746021bd968Lajos Molnar      mLastTime(-1),
72c851b5de495169d7e9528644c2592746021bd968Lajos Molnar      mNumSamples(0) {
73c851b5de495169d7e9528644c2592746021bd968Lajos Molnar}
74c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
75c851b5de495169d7e9528644c2592746021bd968Lajos Molnarvoid VideoFrameScheduler::PLL::reset(float fps) {
76c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    //test();
77c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
78c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    mSamplesUsedForPriming = 0;
79c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    mLastTime = -1;
80c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
81c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    // set up or reset video PLL
82c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    if (fps <= 0.f) {
83c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        mPeriod = -1;
84c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        mPrimed = false;
85c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    } else {
86c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        ALOGV("reset at %.1f fps", fps);
87c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        mPeriod = (nsecs_t)(1e9 / fps + 0.5);
88c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        mPrimed = true;
89c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    }
90c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
91c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    restart();
92c851b5de495169d7e9528644c2592746021bd968Lajos Molnar}
93c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
94c851b5de495169d7e9528644c2592746021bd968Lajos Molnar// reset PLL but keep previous period estimate
95c851b5de495169d7e9528644c2592746021bd968Lajos Molnarvoid VideoFrameScheduler::PLL::restart() {
96c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    mNumSamples = 0;
97c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    mPhase = -1;
98c851b5de495169d7e9528644c2592746021bd968Lajos Molnar}
99c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
100c851b5de495169d7e9528644c2592746021bd968Lajos Molnar#if 0
101c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
102c851b5de495169d7e9528644c2592746021bd968Lajos Molnarvoid VideoFrameScheduler::PLL::test() {
103c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    nsecs_t period = kNanosIn1s / 60;
104c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    mTimes[0] = 0;
105c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    mTimes[1] = period;
106c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    mTimes[2] = period * 3;
107c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    mTimes[3] = period * 4;
108c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    mTimes[4] = period * 7;
109c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    mTimes[5] = period * 8;
110c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    mTimes[6] = period * 10;
111c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    mTimes[7] = period * 12;
112c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    mNumSamples = 8;
113c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    int64_t a, b, err;
114c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    fit(0, period * 12 / 7, 8, &a, &b, &err);
115c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    // a = 0.8(5)+
116c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    // b = -0.14097(2)+
117c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    // err = 0.2750578(703)+
118c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    ALOGD("a=%lld (%.6f), b=%lld (%.6f), err=%lld (%.6f)",
119c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            (long long)a, (a / (float)(1 << kPrecision)),
120c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            (long long)b, (b / (float)(1 << kPrecision)),
121c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            (long long)err, (err / (float)(1 << (kPrecision * 2))));
122c851b5de495169d7e9528644c2592746021bd968Lajos Molnar}
123c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
124c851b5de495169d7e9528644c2592746021bd968Lajos Molnar#endif
125c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
1265d6fb5e41f57a71bd5b2902dc8334825de7bdcc0Lajos Molnarbool VideoFrameScheduler::PLL::fit(
127c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        nsecs_t phase, nsecs_t period, size_t numSamplesToUse,
128c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        int64_t *a, int64_t *b, int64_t *err) {
129c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    if (numSamplesToUse > mNumSamples) {
130c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        numSamplesToUse = mNumSamples;
131c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    }
132c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
133c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    int64_t sumX = 0;
134c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    int64_t sumXX = 0;
135c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    int64_t sumXY = 0;
136c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    int64_t sumYY = 0;
137c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    int64_t sumY = 0;
138c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
139c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    int64_t x = 0; // x usually is in [0..numSamplesToUse)
140c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    nsecs_t lastTime;
141c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    for (size_t i = 0; i < numSamplesToUse; i++) {
142c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        size_t ix = (mNumSamples - numSamplesToUse + i) % kHistorySize;
143c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        nsecs_t time = mTimes[ix];
144c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        if (i > 0) {
145c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            x += divRound(time - lastTime, period);
146c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        }
147c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        // y is usually in [-numSamplesToUse..numSamplesToUse+kRefitRefreshPeriod/kMinPeriod) << kPrecision
148c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        //   ideally in [0..numSamplesToUse), but shifted by -numSamplesToUse during
149c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        //   priming, and possibly shifted by up to kRefitRefreshPeriod/kMinPeriod
150c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        //   while we are not refitting.
151c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        int64_t y = divRound(time - phase, period >> kPrecision);
152c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        sumX += x;
153c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        sumY += y;
154c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        sumXX += x * x;
155c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        sumXY += x * y;
156c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        sumYY += y * y;
157c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        lastTime = time;
158c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    }
159c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
160c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    int64_t div   = numSamplesToUse * sumXX - sumX * sumX;
1615d6fb5e41f57a71bd5b2902dc8334825de7bdcc0Lajos Molnar    if (div == 0) {
1625d6fb5e41f57a71bd5b2902dc8334825de7bdcc0Lajos Molnar        return false;
1635d6fb5e41f57a71bd5b2902dc8334825de7bdcc0Lajos Molnar    }
1645d6fb5e41f57a71bd5b2902dc8334825de7bdcc0Lajos Molnar
165c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    int64_t a_nom = numSamplesToUse * sumXY - sumX * sumY;
166c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    int64_t b_nom = sumXX * sumY            - sumX * sumXY;
167c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    *a = divRound(a_nom, div);
168c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    *b = divRound(b_nom, div);
169c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    // don't use a and b directly as the rounding error is significant
170c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    *err = sumYY - divRound(a_nom * sumXY + b_nom * sumY, div);
171c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    ALOGV("fitting[%zu] a=%lld (%.6f), b=%lld (%.6f), err=%lld (%.6f)",
172c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            numSamplesToUse,
173c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            (long long)*a,   (*a / (float)(1 << kPrecision)),
174c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            (long long)*b,   (*b / (float)(1 << kPrecision)),
175c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            (long long)*err, (*err / (float)(1 << (kPrecision * 2))));
1765d6fb5e41f57a71bd5b2902dc8334825de7bdcc0Lajos Molnar    return true;
177c851b5de495169d7e9528644c2592746021bd968Lajos Molnar}
178c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
179c851b5de495169d7e9528644c2592746021bd968Lajos Molnarvoid VideoFrameScheduler::PLL::prime(size_t numSamplesToUse) {
180c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    if (numSamplesToUse > mNumSamples) {
181c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        numSamplesToUse = mNumSamples;
182c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    }
183c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    CHECK(numSamplesToUse >= 3);  // must have at least 3 samples
184c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
185c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    // estimate video framerate from deltas between timestamps, and
186c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    // 2nd order deltas
187c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    Vector<nsecs_t> deltas;
188c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    nsecs_t lastTime, firstTime;
189c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    for (size_t i = 0; i < numSamplesToUse; ++i) {
190c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        size_t index = (mNumSamples - numSamplesToUse + i) % kHistorySize;
191c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        nsecs_t time = mTimes[index];
192c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        if (i > 0) {
193c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            if (time - lastTime > kMinPeriod) {
194c851b5de495169d7e9528644c2592746021bd968Lajos Molnar                //ALOGV("delta: %lld", (long long)(time - lastTime));
195c851b5de495169d7e9528644c2592746021bd968Lajos Molnar                deltas.push(time - lastTime);
196c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            }
197c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        } else {
198c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            firstTime = time;
199c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        }
200c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        lastTime = time;
201c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    }
202c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    deltas.sort(compare<nsecs_t>);
203c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    size_t numDeltas = deltas.size();
204c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    if (numDeltas > 1) {
2055d6fb5e41f57a71bd5b2902dc8334825de7bdcc0Lajos Molnar        nsecs_t deltaMinLimit = max(deltas[0] / kMultiplesThresholdDiv, kMinPeriod);
206c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        nsecs_t deltaMaxLimit = deltas[numDeltas / 2] * kMultiplesThresholdDiv;
207c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        for (size_t i = numDeltas / 2 + 1; i < numDeltas; ++i) {
208c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            if (deltas[i] > deltaMaxLimit) {
209c851b5de495169d7e9528644c2592746021bd968Lajos Molnar                deltas.resize(i);
210c851b5de495169d7e9528644c2592746021bd968Lajos Molnar                numDeltas = i;
211c851b5de495169d7e9528644c2592746021bd968Lajos Molnar                break;
212c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            }
213c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        }
214c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        for (size_t i = 1; i < numDeltas; ++i) {
215c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            nsecs_t delta2nd = deltas[i] - deltas[i - 1];
216c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            if (delta2nd >= deltaMinLimit) {
217c851b5de495169d7e9528644c2592746021bd968Lajos Molnar                //ALOGV("delta2: %lld", (long long)(delta2nd));
218c851b5de495169d7e9528644c2592746021bd968Lajos Molnar                deltas.push(delta2nd);
219c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            }
220c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        }
221c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    }
222c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
223c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    // use the one that yields the best match
224c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    int64_t bestScore;
225c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    for (size_t i = 0; i < deltas.size(); ++i) {
226c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        nsecs_t delta = deltas[i];
227c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        int64_t score = 0;
228c851b5de495169d7e9528644c2592746021bd968Lajos Molnar#if 1
229c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        // simplest score: number of deltas that are near multiples
230c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        size_t matches = 0;
231c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        for (size_t j = 0; j < deltas.size(); ++j) {
232c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            nsecs_t err = periodicError(deltas[j], delta);
233c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            if (err < delta / kMultiplesThresholdDiv) {
234c851b5de495169d7e9528644c2592746021bd968Lajos Molnar                ++matches;
235c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            }
236c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        }
237c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        score = matches;
238c851b5de495169d7e9528644c2592746021bd968Lajos Molnar#if 0
239c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        // could be weighed by the (1 - normalized error)
240c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        if (numSamplesToUse >= kMinSamplesToEstimatePeriod) {
241c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            int64_t a, b, err;
242c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            fit(firstTime, delta, numSamplesToUse, &a, &b, &err);
243c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            err = (1 << (2 * kPrecision)) - err;
244c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            score *= max(0, err);
245c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        }
246c851b5de495169d7e9528644c2592746021bd968Lajos Molnar#endif
247c851b5de495169d7e9528644c2592746021bd968Lajos Molnar#else
248c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        // or use the error as a negative score
249c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        if (numSamplesToUse >= kMinSamplesToEstimatePeriod) {
250c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            int64_t a, b, err;
251c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            fit(firstTime, delta, numSamplesToUse, &a, &b, &err);
252c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            score = -delta * err;
253c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        }
254c851b5de495169d7e9528644c2592746021bd968Lajos Molnar#endif
255c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        if (i == 0 || score > bestScore) {
256c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            bestScore = score;
257c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            mPeriod = delta;
258c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            mPhase = firstTime;
259c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        }
260c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    }
261c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    ALOGV("priming[%zu] phase:%lld period:%lld", numSamplesToUse, mPhase, mPeriod);
262c851b5de495169d7e9528644c2592746021bd968Lajos Molnar}
263c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
264c851b5de495169d7e9528644c2592746021bd968Lajos Molnarnsecs_t VideoFrameScheduler::PLL::addSample(nsecs_t time) {
265c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    if (mLastTime >= 0
266c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            // if time goes backward, or we skipped rendering
267c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            && (time > mLastTime + kMaxAllowedFrameSkip || time < mLastTime)) {
268c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        restart();
269c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    }
270c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
271c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    mLastTime = time;
272c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    mTimes[mNumSamples % kHistorySize] = time;
273c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    ++mNumSamples;
274c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
275c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    bool doFit = time > mRefitAt;
276c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    if ((mPeriod <= 0 || !mPrimed) && mNumSamples >= kMinSamplesToStartPrime) {
277c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        prime(kMinSamplesToStopPrime);
278c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        ++mSamplesUsedForPriming;
279c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        doFit = true;
280c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    }
281c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    if (mPeriod > 0 && mNumSamples >= kMinSamplesToEstimatePeriod) {
282c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        if (mPhase < 0) {
283c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            // initialize phase to the current render time
284c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            mPhase = time;
285c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            doFit = true;
286c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        } else if (!doFit) {
287c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            int64_t err = periodicError(time - mPhase, mPeriod);
288c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            doFit = err > mPeriod / kReFitThresholdDiv;
289c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        }
290c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
291c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        if (doFit) {
292c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            int64_t a, b, err;
2935d6fb5e41f57a71bd5b2902dc8334825de7bdcc0Lajos Molnar            if (!fit(mPhase, mPeriod, kMaxSamplesToEstimatePeriod, &a, &b, &err)) {
2945d6fb5e41f57a71bd5b2902dc8334825de7bdcc0Lajos Molnar                // samples are not suitable for fitting.  this means they are
2955d6fb5e41f57a71bd5b2902dc8334825de7bdcc0Lajos Molnar                // also not suitable for priming.
2965d6fb5e41f57a71bd5b2902dc8334825de7bdcc0Lajos Molnar                ALOGV("could not fit - keeping old period:%lld", (long long)mPeriod);
2975d6fb5e41f57a71bd5b2902dc8334825de7bdcc0Lajos Molnar                return mPeriod;
2985d6fb5e41f57a71bd5b2902dc8334825de7bdcc0Lajos Molnar            }
2995d6fb5e41f57a71bd5b2902dc8334825de7bdcc0Lajos Molnar
300c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            mRefitAt = time + kRefitRefreshPeriod;
3015d6fb5e41f57a71bd5b2902dc8334825de7bdcc0Lajos Molnar
302c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            mPhase += (mPeriod * b) >> kPrecision;
303c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            mPeriod = (mPeriod * a) >> kPrecision;
304c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            ALOGV("new phase:%lld period:%lld", (long long)mPhase, (long long)mPeriod);
305c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
306c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            if (err < kErrorThreshold) {
307c851b5de495169d7e9528644c2592746021bd968Lajos Molnar                if (!mPrimed && mSamplesUsedForPriming >= kMinSamplesToStopPrime) {
308c851b5de495169d7e9528644c2592746021bd968Lajos Molnar                    mPrimed = true;
309c851b5de495169d7e9528644c2592746021bd968Lajos Molnar                }
310c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            } else {
311c851b5de495169d7e9528644c2592746021bd968Lajos Molnar                mPrimed = false;
312c851b5de495169d7e9528644c2592746021bd968Lajos Molnar                mSamplesUsedForPriming = 0;
313c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            }
314c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        }
315c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    }
316c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    return mPeriod;
317c851b5de495169d7e9528644c2592746021bd968Lajos Molnar}
318c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
319dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar/* ======================================================================= */
320dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar/*                             Frame Scheduler                             */
321dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar/* ======================================================================= */
322dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
323dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnarstatic const nsecs_t kDefaultVsyncPeriod = kNanosIn1s / 60;  // 60Hz
324dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnarstatic const nsecs_t kVsyncRefreshPeriod = kNanosIn1s;       // 1 sec
325dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
326dc43dfa1294470a4413c37e863ef3b621da8681fLajos MolnarVideoFrameScheduler::VideoFrameScheduler()
327dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    : mVsyncTime(0),
328dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar      mVsyncPeriod(0),
329c851b5de495169d7e9528644c2592746021bd968Lajos Molnar      mVsyncRefreshAt(0),
330c851b5de495169d7e9528644c2592746021bd968Lajos Molnar      mLastVsyncTime(-1),
331c851b5de495169d7e9528644c2592746021bd968Lajos Molnar      mTimeCorrection(0) {
332dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar}
333dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
334dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnarvoid VideoFrameScheduler::updateVsync() {
335dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    mVsyncRefreshAt = systemTime(SYSTEM_TIME_MONOTONIC) + kVsyncRefreshPeriod;
336dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    mVsyncPeriod = 0;
337dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    mVsyncTime = 0;
338dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
339dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    // TODO: schedule frames for the destination surface
340dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    // For now, surface flinger only schedules frames on the primary display
341dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    if (mComposer == NULL) {
342dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        String16 name("SurfaceFlinger");
343dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        sp<IServiceManager> sm = defaultServiceManager();
344dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        mComposer = interface_cast<ISurfaceComposer>(sm->checkService(name));
345dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    }
346dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    if (mComposer != NULL) {
347dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        DisplayStatInfo stats;
348dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        status_t res = mComposer->getDisplayStats(NULL /* display */, &stats);
349dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        if (res == OK) {
350dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar            ALOGV("vsync time:%lld period:%lld",
351dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar                    (long long)stats.vsyncTime, (long long)stats.vsyncPeriod);
352dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar            mVsyncTime = stats.vsyncTime;
353dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar            mVsyncPeriod = stats.vsyncPeriod;
354dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        } else {
355dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar            ALOGW("getDisplayStats returned %d", res);
356dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        }
357dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    } else {
358dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        ALOGW("could not get surface mComposer service");
359dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    }
360dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar}
361dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
362c851b5de495169d7e9528644c2592746021bd968Lajos Molnarvoid VideoFrameScheduler::init(float videoFps) {
363dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    updateVsync();
364c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
365c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    mLastVsyncTime = -1;
366c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    mTimeCorrection = 0;
367c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
368c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    mPll.reset(videoFps);
369c851b5de495169d7e9528644c2592746021bd968Lajos Molnar}
370c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
371c851b5de495169d7e9528644c2592746021bd968Lajos Molnarvoid VideoFrameScheduler::restart() {
372c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    mLastVsyncTime = -1;
373c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    mTimeCorrection = 0;
374c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
375c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    mPll.restart();
376dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar}
377dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
378dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnarnsecs_t VideoFrameScheduler::getVsyncPeriod() {
379dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    if (mVsyncPeriod > 0) {
380dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        return mVsyncPeriod;
381dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    }
382dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    return kDefaultVsyncPeriod;
383dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar}
384dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
385dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnarnsecs_t VideoFrameScheduler::schedule(nsecs_t renderTime) {
386dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    nsecs_t origRenderTime = renderTime;
387dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
388dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
389dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    if (now >= mVsyncRefreshAt) {
390dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        updateVsync();
391dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    }
392dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
393dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    // without VSYNC info, there is nothing to do
394dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    if (mVsyncPeriod == 0) {
395dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        ALOGV("no vsync: render=%lld", (long long)renderTime);
396dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        return renderTime;
397dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    }
398dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
399dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    // ensure vsync time is well before (corrected) render time
400dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    if (mVsyncTime > renderTime - 4 * mVsyncPeriod) {
401dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        mVsyncTime -=
402dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar            ((mVsyncTime - renderTime) / mVsyncPeriod + 5) * mVsyncPeriod;
403dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    }
404dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
405dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    // Video presentation takes place at the VSYNC _after_ renderTime.  Adjust renderTime
406dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    // so this effectively becomes a rounding operation (to the _closest_ VSYNC.)
407dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    renderTime -= mVsyncPeriod / 2;
408dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
409c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    const nsecs_t videoPeriod = mPll.addSample(origRenderTime);
410c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    if (videoPeriod > 0) {
411c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        // Smooth out rendering
412c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        size_t N = 12;
413c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        nsecs_t fiveSixthDev =
414c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            abs(((videoPeriod * 5 + mVsyncPeriod) % (mVsyncPeriod * 6)) - mVsyncPeriod)
415c851b5de495169d7e9528644c2592746021bd968Lajos Molnar                    / (mVsyncPeriod / 100);
416c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        // use 20 samples if we are doing 5:6 ratio +- 1% (e.g. playing 50Hz on 60Hz)
417c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        if (fiveSixthDev < 12) {  /* 12% / 6 = 2% */
418c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            N = 20;
419c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        }
420c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
421c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        nsecs_t offset = 0;
422c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        nsecs_t edgeRemainder = 0;
423c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        for (size_t i = 1; i <= N; i++) {
424c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            offset +=
425c851b5de495169d7e9528644c2592746021bd968Lajos Molnar                (renderTime + mTimeCorrection + videoPeriod * i - mVsyncTime) % mVsyncPeriod;
426c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            edgeRemainder += (videoPeriod * i) % mVsyncPeriod;
427c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        }
428c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        mTimeCorrection += mVsyncPeriod / 2 - offset / N;
429c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        renderTime += mTimeCorrection;
430c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        nsecs_t correctionLimit = mVsyncPeriod * 3 / 5;
431c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        edgeRemainder = abs(edgeRemainder / N - mVsyncPeriod / 2);
432c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        if (edgeRemainder <= mVsyncPeriod / 3) {
433c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            correctionLimit /= 2;
434c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        }
435c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
436c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        // estimate how many VSYNCs a frame will spend on the display
437c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        nsecs_t nextVsyncTime =
438c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            renderTime + mVsyncPeriod - ((renderTime - mVsyncTime) % mVsyncPeriod);
439c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        if (mLastVsyncTime >= 0) {
440c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            size_t minVsyncsPerFrame = videoPeriod / mVsyncPeriod;
441c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            size_t vsyncsForLastFrame = divRound(nextVsyncTime - mLastVsyncTime, mVsyncPeriod);
442c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            bool vsyncsPerFrameAreNearlyConstant =
443c851b5de495169d7e9528644c2592746021bd968Lajos Molnar                periodicError(videoPeriod, mVsyncPeriod) / (mVsyncPeriod / 20) == 0;
444c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
445c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            if (mTimeCorrection > correctionLimit &&
446c851b5de495169d7e9528644c2592746021bd968Lajos Molnar                    (vsyncsPerFrameAreNearlyConstant || vsyncsForLastFrame > minVsyncsPerFrame)) {
447c851b5de495169d7e9528644c2592746021bd968Lajos Molnar                // remove a VSYNC
448c851b5de495169d7e9528644c2592746021bd968Lajos Molnar                mTimeCorrection -= mVsyncPeriod / 2;
449c851b5de495169d7e9528644c2592746021bd968Lajos Molnar                renderTime -= mVsyncPeriod / 2;
450c851b5de495169d7e9528644c2592746021bd968Lajos Molnar                nextVsyncTime -= mVsyncPeriod;
451c851b5de495169d7e9528644c2592746021bd968Lajos Molnar                --vsyncsForLastFrame;
452c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            } else if (mTimeCorrection < -correctionLimit &&
453c851b5de495169d7e9528644c2592746021bd968Lajos Molnar                    (vsyncsPerFrameAreNearlyConstant || vsyncsForLastFrame == minVsyncsPerFrame)) {
454c851b5de495169d7e9528644c2592746021bd968Lajos Molnar                // add a VSYNC
455c851b5de495169d7e9528644c2592746021bd968Lajos Molnar                mTimeCorrection += mVsyncPeriod / 2;
456c851b5de495169d7e9528644c2592746021bd968Lajos Molnar                renderTime += mVsyncPeriod / 2;
457c851b5de495169d7e9528644c2592746021bd968Lajos Molnar                nextVsyncTime += mVsyncPeriod;
458c851b5de495169d7e9528644c2592746021bd968Lajos Molnar                ++vsyncsForLastFrame;
459c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            }
460c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            ATRACE_INT("FRAME_VSYNCS", vsyncsForLastFrame);
461c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        }
462c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        mLastVsyncTime = nextVsyncTime;
463c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    }
464c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
465dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    // align rendertime to the center between VSYNC edges
466dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    renderTime -= (renderTime - mVsyncTime) % mVsyncPeriod;
467dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    renderTime += mVsyncPeriod / 2;
468dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    ALOGV("adjusting render: %lld => %lld", (long long)origRenderTime, (long long)renderTime);
469dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    ATRACE_INT("FRAME_FLIP_IN(ms)", (renderTime - now) / 1000000);
470dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    return renderTime;
471dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar}
472dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
473dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnarvoid VideoFrameScheduler::release() {
474dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    mComposer.clear();
475dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar}
476dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
477dc43dfa1294470a4413c37e863ef3b621da8681fLajos MolnarVideoFrameScheduler::~VideoFrameScheduler() {
478dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    release();
479dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar}
480dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
481dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar} // namespace android
482dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
483