VideoFrameScheduler.cpp revision a3725d7b0cb79ddb49f81cba00a0164d8e645acd
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> 31a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar#include <media/stagefright/VideoFrameScheduler.h> 32dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar 33dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnarnamespace android { 34dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar 35dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnarstatic const nsecs_t kNanosIn1s = 1000000000; 36dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar 37c851b5de495169d7e9528644c2592746021bd968Lajos Molnartemplate<class T> 38c851b5de495169d7e9528644c2592746021bd968Lajos Molnarstatic int compare(const T *lhs, const T *rhs) { 39c851b5de495169d7e9528644c2592746021bd968Lajos Molnar if (*lhs < *rhs) { 40c851b5de495169d7e9528644c2592746021bd968Lajos Molnar return -1; 41c851b5de495169d7e9528644c2592746021bd968Lajos Molnar } else if (*lhs > *rhs) { 42c851b5de495169d7e9528644c2592746021bd968Lajos Molnar return 1; 43c851b5de495169d7e9528644c2592746021bd968Lajos Molnar } else { 44c851b5de495169d7e9528644c2592746021bd968Lajos Molnar return 0; 45c851b5de495169d7e9528644c2592746021bd968Lajos Molnar } 46c851b5de495169d7e9528644c2592746021bd968Lajos Molnar} 47c851b5de495169d7e9528644c2592746021bd968Lajos Molnar 48c851b5de495169d7e9528644c2592746021bd968Lajos Molnar/* ======================================================================= */ 49c851b5de495169d7e9528644c2592746021bd968Lajos Molnar/* PLL */ 50c851b5de495169d7e9528644c2592746021bd968Lajos Molnar/* ======================================================================= */ 51c851b5de495169d7e9528644c2592746021bd968Lajos Molnar 52c851b5de495169d7e9528644c2592746021bd968Lajos Molnarstatic const size_t kMinSamplesToStartPrime = 3; 53c851b5de495169d7e9528644c2592746021bd968Lajos Molnarstatic const size_t kMinSamplesToStopPrime = VideoFrameScheduler::kHistorySize; 54c851b5de495169d7e9528644c2592746021bd968Lajos Molnarstatic const size_t kMinSamplesToEstimatePeriod = 3; 55c851b5de495169d7e9528644c2592746021bd968Lajos Molnarstatic const size_t kMaxSamplesToEstimatePeriod = VideoFrameScheduler::kHistorySize; 56c851b5de495169d7e9528644c2592746021bd968Lajos Molnar 57c851b5de495169d7e9528644c2592746021bd968Lajos Molnarstatic const size_t kPrecision = 12; 58a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnarstatic const int64_t kErrorThreshold = (1 << (kPrecision * 2)) / 10; 59c851b5de495169d7e9528644c2592746021bd968Lajos Molnarstatic const int64_t kMultiplesThresholdDiv = 4; // 25% 60c851b5de495169d7e9528644c2592746021bd968Lajos Molnarstatic const int64_t kReFitThresholdDiv = 100; // 1% 61c851b5de495169d7e9528644c2592746021bd968Lajos Molnarstatic const nsecs_t kMaxAllowedFrameSkip = kNanosIn1s; // 1 sec 62c851b5de495169d7e9528644c2592746021bd968Lajos Molnarstatic const nsecs_t kMinPeriod = kNanosIn1s / 120; // 120Hz 63c851b5de495169d7e9528644c2592746021bd968Lajos Molnarstatic const nsecs_t kRefitRefreshPeriod = 10 * kNanosIn1s; // 10 sec 64c851b5de495169d7e9528644c2592746021bd968Lajos Molnar 65c851b5de495169d7e9528644c2592746021bd968Lajos MolnarVideoFrameScheduler::PLL::PLL() 66c851b5de495169d7e9528644c2592746021bd968Lajos Molnar : mPeriod(-1), 67c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mPhase(0), 68c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mPrimed(false), 69c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mSamplesUsedForPriming(0), 70c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mLastTime(-1), 71c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mNumSamples(0) { 72c851b5de495169d7e9528644c2592746021bd968Lajos Molnar} 73c851b5de495169d7e9528644c2592746021bd968Lajos Molnar 74c851b5de495169d7e9528644c2592746021bd968Lajos Molnarvoid VideoFrameScheduler::PLL::reset(float fps) { 75c851b5de495169d7e9528644c2592746021bd968Lajos Molnar //test(); 76c851b5de495169d7e9528644c2592746021bd968Lajos Molnar 77c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mSamplesUsedForPriming = 0; 78c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mLastTime = -1; 79c851b5de495169d7e9528644c2592746021bd968Lajos Molnar 80c851b5de495169d7e9528644c2592746021bd968Lajos Molnar // set up or reset video PLL 81c851b5de495169d7e9528644c2592746021bd968Lajos Molnar if (fps <= 0.f) { 82c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mPeriod = -1; 83c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mPrimed = false; 84c851b5de495169d7e9528644c2592746021bd968Lajos Molnar } else { 85c851b5de495169d7e9528644c2592746021bd968Lajos Molnar ALOGV("reset at %.1f fps", fps); 86c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mPeriod = (nsecs_t)(1e9 / fps + 0.5); 87c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mPrimed = true; 88c851b5de495169d7e9528644c2592746021bd968Lajos Molnar } 89c851b5de495169d7e9528644c2592746021bd968Lajos Molnar 90c851b5de495169d7e9528644c2592746021bd968Lajos Molnar restart(); 91c851b5de495169d7e9528644c2592746021bd968Lajos Molnar} 92c851b5de495169d7e9528644c2592746021bd968Lajos Molnar 93c851b5de495169d7e9528644c2592746021bd968Lajos Molnar// reset PLL but keep previous period estimate 94c851b5de495169d7e9528644c2592746021bd968Lajos Molnarvoid VideoFrameScheduler::PLL::restart() { 95c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mNumSamples = 0; 96c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mPhase = -1; 97c851b5de495169d7e9528644c2592746021bd968Lajos Molnar} 98c851b5de495169d7e9528644c2592746021bd968Lajos Molnar 99c851b5de495169d7e9528644c2592746021bd968Lajos Molnar#if 0 100c851b5de495169d7e9528644c2592746021bd968Lajos Molnar 101c851b5de495169d7e9528644c2592746021bd968Lajos Molnarvoid VideoFrameScheduler::PLL::test() { 102c851b5de495169d7e9528644c2592746021bd968Lajos Molnar nsecs_t period = kNanosIn1s / 60; 103c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mTimes[0] = 0; 104c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mTimes[1] = period; 105c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mTimes[2] = period * 3; 106c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mTimes[3] = period * 4; 107c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mTimes[4] = period * 7; 108c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mTimes[5] = period * 8; 109c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mTimes[6] = period * 10; 110c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mTimes[7] = period * 12; 111c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mNumSamples = 8; 112c851b5de495169d7e9528644c2592746021bd968Lajos Molnar int64_t a, b, err; 113c851b5de495169d7e9528644c2592746021bd968Lajos Molnar fit(0, period * 12 / 7, 8, &a, &b, &err); 114c851b5de495169d7e9528644c2592746021bd968Lajos Molnar // a = 0.8(5)+ 115c851b5de495169d7e9528644c2592746021bd968Lajos Molnar // b = -0.14097(2)+ 116c851b5de495169d7e9528644c2592746021bd968Lajos Molnar // err = 0.2750578(703)+ 117c851b5de495169d7e9528644c2592746021bd968Lajos Molnar ALOGD("a=%lld (%.6f), b=%lld (%.6f), err=%lld (%.6f)", 118c851b5de495169d7e9528644c2592746021bd968Lajos Molnar (long long)a, (a / (float)(1 << kPrecision)), 119c851b5de495169d7e9528644c2592746021bd968Lajos Molnar (long long)b, (b / (float)(1 << kPrecision)), 120c851b5de495169d7e9528644c2592746021bd968Lajos Molnar (long long)err, (err / (float)(1 << (kPrecision * 2)))); 121c851b5de495169d7e9528644c2592746021bd968Lajos Molnar} 122c851b5de495169d7e9528644c2592746021bd968Lajos Molnar 123c851b5de495169d7e9528644c2592746021bd968Lajos Molnar#endif 124c851b5de495169d7e9528644c2592746021bd968Lajos Molnar 1255d6fb5e41f57a71bd5b2902dc8334825de7bdcc0Lajos Molnarbool VideoFrameScheduler::PLL::fit( 126c851b5de495169d7e9528644c2592746021bd968Lajos Molnar nsecs_t phase, nsecs_t period, size_t numSamplesToUse, 127c851b5de495169d7e9528644c2592746021bd968Lajos Molnar int64_t *a, int64_t *b, int64_t *err) { 128c851b5de495169d7e9528644c2592746021bd968Lajos Molnar if (numSamplesToUse > mNumSamples) { 129c851b5de495169d7e9528644c2592746021bd968Lajos Molnar numSamplesToUse = mNumSamples; 130c851b5de495169d7e9528644c2592746021bd968Lajos Molnar } 131c851b5de495169d7e9528644c2592746021bd968Lajos Molnar 132c851b5de495169d7e9528644c2592746021bd968Lajos Molnar int64_t sumX = 0; 133c851b5de495169d7e9528644c2592746021bd968Lajos Molnar int64_t sumXX = 0; 134c851b5de495169d7e9528644c2592746021bd968Lajos Molnar int64_t sumXY = 0; 135c851b5de495169d7e9528644c2592746021bd968Lajos Molnar int64_t sumYY = 0; 136c851b5de495169d7e9528644c2592746021bd968Lajos Molnar int64_t sumY = 0; 137c851b5de495169d7e9528644c2592746021bd968Lajos Molnar 138c851b5de495169d7e9528644c2592746021bd968Lajos Molnar int64_t x = 0; // x usually is in [0..numSamplesToUse) 139c851b5de495169d7e9528644c2592746021bd968Lajos Molnar nsecs_t lastTime; 140c851b5de495169d7e9528644c2592746021bd968Lajos Molnar for (size_t i = 0; i < numSamplesToUse; i++) { 141c851b5de495169d7e9528644c2592746021bd968Lajos Molnar size_t ix = (mNumSamples - numSamplesToUse + i) % kHistorySize; 142c851b5de495169d7e9528644c2592746021bd968Lajos Molnar nsecs_t time = mTimes[ix]; 143c851b5de495169d7e9528644c2592746021bd968Lajos Molnar if (i > 0) { 144c851b5de495169d7e9528644c2592746021bd968Lajos Molnar x += divRound(time - lastTime, period); 145c851b5de495169d7e9528644c2592746021bd968Lajos Molnar } 146c851b5de495169d7e9528644c2592746021bd968Lajos Molnar // y is usually in [-numSamplesToUse..numSamplesToUse+kRefitRefreshPeriod/kMinPeriod) << kPrecision 147c851b5de495169d7e9528644c2592746021bd968Lajos Molnar // ideally in [0..numSamplesToUse), but shifted by -numSamplesToUse during 148c851b5de495169d7e9528644c2592746021bd968Lajos Molnar // priming, and possibly shifted by up to kRefitRefreshPeriod/kMinPeriod 149c851b5de495169d7e9528644c2592746021bd968Lajos Molnar // while we are not refitting. 150c851b5de495169d7e9528644c2592746021bd968Lajos Molnar int64_t y = divRound(time - phase, period >> kPrecision); 151c851b5de495169d7e9528644c2592746021bd968Lajos Molnar sumX += x; 152c851b5de495169d7e9528644c2592746021bd968Lajos Molnar sumY += y; 153c851b5de495169d7e9528644c2592746021bd968Lajos Molnar sumXX += x * x; 154c851b5de495169d7e9528644c2592746021bd968Lajos Molnar sumXY += x * y; 155c851b5de495169d7e9528644c2592746021bd968Lajos Molnar sumYY += y * y; 156c851b5de495169d7e9528644c2592746021bd968Lajos Molnar lastTime = time; 157c851b5de495169d7e9528644c2592746021bd968Lajos Molnar } 158c851b5de495169d7e9528644c2592746021bd968Lajos Molnar 159c851b5de495169d7e9528644c2592746021bd968Lajos Molnar int64_t div = numSamplesToUse * sumXX - sumX * sumX; 1605d6fb5e41f57a71bd5b2902dc8334825de7bdcc0Lajos Molnar if (div == 0) { 1615d6fb5e41f57a71bd5b2902dc8334825de7bdcc0Lajos Molnar return false; 1625d6fb5e41f57a71bd5b2902dc8334825de7bdcc0Lajos Molnar } 1635d6fb5e41f57a71bd5b2902dc8334825de7bdcc0Lajos Molnar 164c851b5de495169d7e9528644c2592746021bd968Lajos Molnar int64_t a_nom = numSamplesToUse * sumXY - sumX * sumY; 165c851b5de495169d7e9528644c2592746021bd968Lajos Molnar int64_t b_nom = sumXX * sumY - sumX * sumXY; 166c851b5de495169d7e9528644c2592746021bd968Lajos Molnar *a = divRound(a_nom, div); 167c851b5de495169d7e9528644c2592746021bd968Lajos Molnar *b = divRound(b_nom, div); 168c851b5de495169d7e9528644c2592746021bd968Lajos Molnar // don't use a and b directly as the rounding error is significant 169c851b5de495169d7e9528644c2592746021bd968Lajos Molnar *err = sumYY - divRound(a_nom * sumXY + b_nom * sumY, div); 170c851b5de495169d7e9528644c2592746021bd968Lajos Molnar ALOGV("fitting[%zu] a=%lld (%.6f), b=%lld (%.6f), err=%lld (%.6f)", 171c851b5de495169d7e9528644c2592746021bd968Lajos Molnar numSamplesToUse, 172c851b5de495169d7e9528644c2592746021bd968Lajos Molnar (long long)*a, (*a / (float)(1 << kPrecision)), 173c851b5de495169d7e9528644c2592746021bd968Lajos Molnar (long long)*b, (*b / (float)(1 << kPrecision)), 174c851b5de495169d7e9528644c2592746021bd968Lajos Molnar (long long)*err, (*err / (float)(1 << (kPrecision * 2)))); 1755d6fb5e41f57a71bd5b2902dc8334825de7bdcc0Lajos Molnar return true; 176c851b5de495169d7e9528644c2592746021bd968Lajos Molnar} 177c851b5de495169d7e9528644c2592746021bd968Lajos Molnar 178c851b5de495169d7e9528644c2592746021bd968Lajos Molnarvoid VideoFrameScheduler::PLL::prime(size_t numSamplesToUse) { 179c851b5de495169d7e9528644c2592746021bd968Lajos Molnar if (numSamplesToUse > mNumSamples) { 180c851b5de495169d7e9528644c2592746021bd968Lajos Molnar numSamplesToUse = mNumSamples; 181c851b5de495169d7e9528644c2592746021bd968Lajos Molnar } 182c851b5de495169d7e9528644c2592746021bd968Lajos Molnar CHECK(numSamplesToUse >= 3); // must have at least 3 samples 183c851b5de495169d7e9528644c2592746021bd968Lajos Molnar 184c851b5de495169d7e9528644c2592746021bd968Lajos Molnar // estimate video framerate from deltas between timestamps, and 185c851b5de495169d7e9528644c2592746021bd968Lajos Molnar // 2nd order deltas 186c851b5de495169d7e9528644c2592746021bd968Lajos Molnar Vector<nsecs_t> deltas; 187c851b5de495169d7e9528644c2592746021bd968Lajos Molnar nsecs_t lastTime, firstTime; 188c851b5de495169d7e9528644c2592746021bd968Lajos Molnar for (size_t i = 0; i < numSamplesToUse; ++i) { 189c851b5de495169d7e9528644c2592746021bd968Lajos Molnar size_t index = (mNumSamples - numSamplesToUse + i) % kHistorySize; 190c851b5de495169d7e9528644c2592746021bd968Lajos Molnar nsecs_t time = mTimes[index]; 191c851b5de495169d7e9528644c2592746021bd968Lajos Molnar if (i > 0) { 192c851b5de495169d7e9528644c2592746021bd968Lajos Molnar if (time - lastTime > kMinPeriod) { 193c851b5de495169d7e9528644c2592746021bd968Lajos Molnar //ALOGV("delta: %lld", (long long)(time - lastTime)); 194c851b5de495169d7e9528644c2592746021bd968Lajos Molnar deltas.push(time - lastTime); 195c851b5de495169d7e9528644c2592746021bd968Lajos Molnar } 196c851b5de495169d7e9528644c2592746021bd968Lajos Molnar } else { 197c851b5de495169d7e9528644c2592746021bd968Lajos Molnar firstTime = time; 198c851b5de495169d7e9528644c2592746021bd968Lajos Molnar } 199c851b5de495169d7e9528644c2592746021bd968Lajos Molnar lastTime = time; 200c851b5de495169d7e9528644c2592746021bd968Lajos Molnar } 201c851b5de495169d7e9528644c2592746021bd968Lajos Molnar deltas.sort(compare<nsecs_t>); 202c851b5de495169d7e9528644c2592746021bd968Lajos Molnar size_t numDeltas = deltas.size(); 203c851b5de495169d7e9528644c2592746021bd968Lajos Molnar if (numDeltas > 1) { 2045d6fb5e41f57a71bd5b2902dc8334825de7bdcc0Lajos Molnar nsecs_t deltaMinLimit = max(deltas[0] / kMultiplesThresholdDiv, kMinPeriod); 205c851b5de495169d7e9528644c2592746021bd968Lajos Molnar nsecs_t deltaMaxLimit = deltas[numDeltas / 2] * kMultiplesThresholdDiv; 206c851b5de495169d7e9528644c2592746021bd968Lajos Molnar for (size_t i = numDeltas / 2 + 1; i < numDeltas; ++i) { 207c851b5de495169d7e9528644c2592746021bd968Lajos Molnar if (deltas[i] > deltaMaxLimit) { 208c851b5de495169d7e9528644c2592746021bd968Lajos Molnar deltas.resize(i); 209c851b5de495169d7e9528644c2592746021bd968Lajos Molnar numDeltas = i; 210c851b5de495169d7e9528644c2592746021bd968Lajos Molnar break; 211c851b5de495169d7e9528644c2592746021bd968Lajos Molnar } 212c851b5de495169d7e9528644c2592746021bd968Lajos Molnar } 213c851b5de495169d7e9528644c2592746021bd968Lajos Molnar for (size_t i = 1; i < numDeltas; ++i) { 214c851b5de495169d7e9528644c2592746021bd968Lajos Molnar nsecs_t delta2nd = deltas[i] - deltas[i - 1]; 215c851b5de495169d7e9528644c2592746021bd968Lajos Molnar if (delta2nd >= deltaMinLimit) { 216c851b5de495169d7e9528644c2592746021bd968Lajos Molnar //ALOGV("delta2: %lld", (long long)(delta2nd)); 217c851b5de495169d7e9528644c2592746021bd968Lajos Molnar deltas.push(delta2nd); 218c851b5de495169d7e9528644c2592746021bd968Lajos Molnar } 219c851b5de495169d7e9528644c2592746021bd968Lajos Molnar } 220c851b5de495169d7e9528644c2592746021bd968Lajos Molnar } 221c851b5de495169d7e9528644c2592746021bd968Lajos Molnar 222c851b5de495169d7e9528644c2592746021bd968Lajos Molnar // use the one that yields the best match 223c851b5de495169d7e9528644c2592746021bd968Lajos Molnar int64_t bestScore; 224c851b5de495169d7e9528644c2592746021bd968Lajos Molnar for (size_t i = 0; i < deltas.size(); ++i) { 225c851b5de495169d7e9528644c2592746021bd968Lajos Molnar nsecs_t delta = deltas[i]; 226c851b5de495169d7e9528644c2592746021bd968Lajos Molnar int64_t score = 0; 227c851b5de495169d7e9528644c2592746021bd968Lajos Molnar#if 1 228c851b5de495169d7e9528644c2592746021bd968Lajos Molnar // simplest score: number of deltas that are near multiples 229c851b5de495169d7e9528644c2592746021bd968Lajos Molnar size_t matches = 0; 230c851b5de495169d7e9528644c2592746021bd968Lajos Molnar for (size_t j = 0; j < deltas.size(); ++j) { 231c851b5de495169d7e9528644c2592746021bd968Lajos Molnar nsecs_t err = periodicError(deltas[j], delta); 232c851b5de495169d7e9528644c2592746021bd968Lajos Molnar if (err < delta / kMultiplesThresholdDiv) { 233c851b5de495169d7e9528644c2592746021bd968Lajos Molnar ++matches; 234c851b5de495169d7e9528644c2592746021bd968Lajos Molnar } 235c851b5de495169d7e9528644c2592746021bd968Lajos Molnar } 236c851b5de495169d7e9528644c2592746021bd968Lajos Molnar score = matches; 237c851b5de495169d7e9528644c2592746021bd968Lajos Molnar#if 0 238c851b5de495169d7e9528644c2592746021bd968Lajos Molnar // could be weighed by the (1 - normalized error) 239c851b5de495169d7e9528644c2592746021bd968Lajos Molnar if (numSamplesToUse >= kMinSamplesToEstimatePeriod) { 240c851b5de495169d7e9528644c2592746021bd968Lajos Molnar int64_t a, b, err; 241c851b5de495169d7e9528644c2592746021bd968Lajos Molnar fit(firstTime, delta, numSamplesToUse, &a, &b, &err); 242c851b5de495169d7e9528644c2592746021bd968Lajos Molnar err = (1 << (2 * kPrecision)) - err; 243c851b5de495169d7e9528644c2592746021bd968Lajos Molnar score *= max(0, err); 244c851b5de495169d7e9528644c2592746021bd968Lajos Molnar } 245c851b5de495169d7e9528644c2592746021bd968Lajos Molnar#endif 246c851b5de495169d7e9528644c2592746021bd968Lajos Molnar#else 247c851b5de495169d7e9528644c2592746021bd968Lajos Molnar // or use the error as a negative score 248c851b5de495169d7e9528644c2592746021bd968Lajos Molnar if (numSamplesToUse >= kMinSamplesToEstimatePeriod) { 249c851b5de495169d7e9528644c2592746021bd968Lajos Molnar int64_t a, b, err; 250c851b5de495169d7e9528644c2592746021bd968Lajos Molnar fit(firstTime, delta, numSamplesToUse, &a, &b, &err); 251c851b5de495169d7e9528644c2592746021bd968Lajos Molnar score = -delta * err; 252c851b5de495169d7e9528644c2592746021bd968Lajos Molnar } 253c851b5de495169d7e9528644c2592746021bd968Lajos Molnar#endif 254c851b5de495169d7e9528644c2592746021bd968Lajos Molnar if (i == 0 || score > bestScore) { 255c851b5de495169d7e9528644c2592746021bd968Lajos Molnar bestScore = score; 256c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mPeriod = delta; 257c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mPhase = firstTime; 258c851b5de495169d7e9528644c2592746021bd968Lajos Molnar } 259c851b5de495169d7e9528644c2592746021bd968Lajos Molnar } 260a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar ALOGV("priming[%zu] phase:%lld period:%lld", 261a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar numSamplesToUse, (long long)mPhase, (long long)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 319a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnarnsecs_t VideoFrameScheduler::PLL::getPeriod() const { 320a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar return mPrimed ? mPeriod : 0; 321a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar} 322a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar 323dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar/* ======================================================================= */ 324dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar/* Frame Scheduler */ 325dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar/* ======================================================================= */ 326dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar 327dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnarstatic const nsecs_t kDefaultVsyncPeriod = kNanosIn1s / 60; // 60Hz 328dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnarstatic const nsecs_t kVsyncRefreshPeriod = kNanosIn1s; // 1 sec 329dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar 330dc43dfa1294470a4413c37e863ef3b621da8681fLajos MolnarVideoFrameScheduler::VideoFrameScheduler() 331dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar : mVsyncTime(0), 332dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar mVsyncPeriod(0), 333c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mVsyncRefreshAt(0), 334c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mLastVsyncTime(-1), 335c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mTimeCorrection(0) { 336dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar} 337dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar 338dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnarvoid VideoFrameScheduler::updateVsync() { 339dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar mVsyncRefreshAt = systemTime(SYSTEM_TIME_MONOTONIC) + kVsyncRefreshPeriod; 340dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar mVsyncPeriod = 0; 341dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar mVsyncTime = 0; 342dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar 343dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar // TODO: schedule frames for the destination surface 344dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar // For now, surface flinger only schedules frames on the primary display 345dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar if (mComposer == NULL) { 346dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar String16 name("SurfaceFlinger"); 347dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar sp<IServiceManager> sm = defaultServiceManager(); 348dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar mComposer = interface_cast<ISurfaceComposer>(sm->checkService(name)); 349dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar } 350dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar if (mComposer != NULL) { 351dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar DisplayStatInfo stats; 352dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar status_t res = mComposer->getDisplayStats(NULL /* display */, &stats); 353dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar if (res == OK) { 354dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar ALOGV("vsync time:%lld period:%lld", 355dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar (long long)stats.vsyncTime, (long long)stats.vsyncPeriod); 356dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar mVsyncTime = stats.vsyncTime; 357dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar mVsyncPeriod = stats.vsyncPeriod; 358dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar } else { 359dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar ALOGW("getDisplayStats returned %d", res); 360dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar } 361dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar } else { 362dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar ALOGW("could not get surface mComposer service"); 363dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar } 364dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar} 365dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar 366c851b5de495169d7e9528644c2592746021bd968Lajos Molnarvoid VideoFrameScheduler::init(float videoFps) { 367dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar updateVsync(); 368c851b5de495169d7e9528644c2592746021bd968Lajos Molnar 369c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mLastVsyncTime = -1; 370c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mTimeCorrection = 0; 371c851b5de495169d7e9528644c2592746021bd968Lajos Molnar 372c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mPll.reset(videoFps); 373c851b5de495169d7e9528644c2592746021bd968Lajos Molnar} 374c851b5de495169d7e9528644c2592746021bd968Lajos Molnar 375c851b5de495169d7e9528644c2592746021bd968Lajos Molnarvoid VideoFrameScheduler::restart() { 376c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mLastVsyncTime = -1; 377c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mTimeCorrection = 0; 378c851b5de495169d7e9528644c2592746021bd968Lajos Molnar 379c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mPll.restart(); 380dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar} 381dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar 382dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnarnsecs_t VideoFrameScheduler::getVsyncPeriod() { 383dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar if (mVsyncPeriod > 0) { 384dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar return mVsyncPeriod; 385dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar } 386dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar return kDefaultVsyncPeriod; 387dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar} 388dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar 389a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnarfloat VideoFrameScheduler::getFrameRate() { 390a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar nsecs_t videoPeriod = mPll.getPeriod(); 391a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar if (videoPeriod > 0) { 392a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar return 1e9 / videoPeriod; 393a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar } 394a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar return 0.f; 395a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar} 396a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar 397dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnarnsecs_t VideoFrameScheduler::schedule(nsecs_t renderTime) { 398dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar nsecs_t origRenderTime = renderTime; 399dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar 400dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); 401dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar if (now >= mVsyncRefreshAt) { 402dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar updateVsync(); 403dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar } 404dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar 405dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar // without VSYNC info, there is nothing to do 406dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar if (mVsyncPeriod == 0) { 407dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar ALOGV("no vsync: render=%lld", (long long)renderTime); 408dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar return renderTime; 409dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar } 410dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar 411dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar // ensure vsync time is well before (corrected) render time 412dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar if (mVsyncTime > renderTime - 4 * mVsyncPeriod) { 413dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar mVsyncTime -= 414dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar ((mVsyncTime - renderTime) / mVsyncPeriod + 5) * mVsyncPeriod; 415dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar } 416dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar 417dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar // Video presentation takes place at the VSYNC _after_ renderTime. Adjust renderTime 418dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar // so this effectively becomes a rounding operation (to the _closest_ VSYNC.) 419dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar renderTime -= mVsyncPeriod / 2; 420dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar 421c851b5de495169d7e9528644c2592746021bd968Lajos Molnar const nsecs_t videoPeriod = mPll.addSample(origRenderTime); 422c851b5de495169d7e9528644c2592746021bd968Lajos Molnar if (videoPeriod > 0) { 423c851b5de495169d7e9528644c2592746021bd968Lajos Molnar // Smooth out rendering 424c851b5de495169d7e9528644c2592746021bd968Lajos Molnar size_t N = 12; 425c851b5de495169d7e9528644c2592746021bd968Lajos Molnar nsecs_t fiveSixthDev = 426c851b5de495169d7e9528644c2592746021bd968Lajos Molnar abs(((videoPeriod * 5 + mVsyncPeriod) % (mVsyncPeriod * 6)) - mVsyncPeriod) 427c851b5de495169d7e9528644c2592746021bd968Lajos Molnar / (mVsyncPeriod / 100); 428c851b5de495169d7e9528644c2592746021bd968Lajos Molnar // use 20 samples if we are doing 5:6 ratio +- 1% (e.g. playing 50Hz on 60Hz) 429c851b5de495169d7e9528644c2592746021bd968Lajos Molnar if (fiveSixthDev < 12) { /* 12% / 6 = 2% */ 430c851b5de495169d7e9528644c2592746021bd968Lajos Molnar N = 20; 431c851b5de495169d7e9528644c2592746021bd968Lajos Molnar } 432c851b5de495169d7e9528644c2592746021bd968Lajos Molnar 433c851b5de495169d7e9528644c2592746021bd968Lajos Molnar nsecs_t offset = 0; 434c851b5de495169d7e9528644c2592746021bd968Lajos Molnar nsecs_t edgeRemainder = 0; 435c851b5de495169d7e9528644c2592746021bd968Lajos Molnar for (size_t i = 1; i <= N; i++) { 436c851b5de495169d7e9528644c2592746021bd968Lajos Molnar offset += 437c851b5de495169d7e9528644c2592746021bd968Lajos Molnar (renderTime + mTimeCorrection + videoPeriod * i - mVsyncTime) % mVsyncPeriod; 438c851b5de495169d7e9528644c2592746021bd968Lajos Molnar edgeRemainder += (videoPeriod * i) % mVsyncPeriod; 439c851b5de495169d7e9528644c2592746021bd968Lajos Molnar } 440c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mTimeCorrection += mVsyncPeriod / 2 - offset / N; 441c851b5de495169d7e9528644c2592746021bd968Lajos Molnar renderTime += mTimeCorrection; 442c851b5de495169d7e9528644c2592746021bd968Lajos Molnar nsecs_t correctionLimit = mVsyncPeriod * 3 / 5; 443c851b5de495169d7e9528644c2592746021bd968Lajos Molnar edgeRemainder = abs(edgeRemainder / N - mVsyncPeriod / 2); 444c851b5de495169d7e9528644c2592746021bd968Lajos Molnar if (edgeRemainder <= mVsyncPeriod / 3) { 445c851b5de495169d7e9528644c2592746021bd968Lajos Molnar correctionLimit /= 2; 446c851b5de495169d7e9528644c2592746021bd968Lajos Molnar } 447c851b5de495169d7e9528644c2592746021bd968Lajos Molnar 448c851b5de495169d7e9528644c2592746021bd968Lajos Molnar // estimate how many VSYNCs a frame will spend on the display 449c851b5de495169d7e9528644c2592746021bd968Lajos Molnar nsecs_t nextVsyncTime = 450c851b5de495169d7e9528644c2592746021bd968Lajos Molnar renderTime + mVsyncPeriod - ((renderTime - mVsyncTime) % mVsyncPeriod); 451c851b5de495169d7e9528644c2592746021bd968Lajos Molnar if (mLastVsyncTime >= 0) { 452c851b5de495169d7e9528644c2592746021bd968Lajos Molnar size_t minVsyncsPerFrame = videoPeriod / mVsyncPeriod; 453c851b5de495169d7e9528644c2592746021bd968Lajos Molnar size_t vsyncsForLastFrame = divRound(nextVsyncTime - mLastVsyncTime, mVsyncPeriod); 454c851b5de495169d7e9528644c2592746021bd968Lajos Molnar bool vsyncsPerFrameAreNearlyConstant = 455c851b5de495169d7e9528644c2592746021bd968Lajos Molnar periodicError(videoPeriod, mVsyncPeriod) / (mVsyncPeriod / 20) == 0; 456c851b5de495169d7e9528644c2592746021bd968Lajos Molnar 457c851b5de495169d7e9528644c2592746021bd968Lajos Molnar if (mTimeCorrection > correctionLimit && 458c851b5de495169d7e9528644c2592746021bd968Lajos Molnar (vsyncsPerFrameAreNearlyConstant || vsyncsForLastFrame > minVsyncsPerFrame)) { 459c851b5de495169d7e9528644c2592746021bd968Lajos Molnar // remove a VSYNC 460c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mTimeCorrection -= mVsyncPeriod / 2; 461c851b5de495169d7e9528644c2592746021bd968Lajos Molnar renderTime -= mVsyncPeriod / 2; 462c851b5de495169d7e9528644c2592746021bd968Lajos Molnar nextVsyncTime -= mVsyncPeriod; 463c851b5de495169d7e9528644c2592746021bd968Lajos Molnar --vsyncsForLastFrame; 464c851b5de495169d7e9528644c2592746021bd968Lajos Molnar } else if (mTimeCorrection < -correctionLimit && 465c851b5de495169d7e9528644c2592746021bd968Lajos Molnar (vsyncsPerFrameAreNearlyConstant || vsyncsForLastFrame == minVsyncsPerFrame)) { 466c851b5de495169d7e9528644c2592746021bd968Lajos Molnar // add a VSYNC 467c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mTimeCorrection += mVsyncPeriod / 2; 468c851b5de495169d7e9528644c2592746021bd968Lajos Molnar renderTime += mVsyncPeriod / 2; 469c851b5de495169d7e9528644c2592746021bd968Lajos Molnar nextVsyncTime += mVsyncPeriod; 470c851b5de495169d7e9528644c2592746021bd968Lajos Molnar ++vsyncsForLastFrame; 471c851b5de495169d7e9528644c2592746021bd968Lajos Molnar } 472c851b5de495169d7e9528644c2592746021bd968Lajos Molnar ATRACE_INT("FRAME_VSYNCS", vsyncsForLastFrame); 473c851b5de495169d7e9528644c2592746021bd968Lajos Molnar } 474c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mLastVsyncTime = nextVsyncTime; 475c851b5de495169d7e9528644c2592746021bd968Lajos Molnar } 476c851b5de495169d7e9528644c2592746021bd968Lajos Molnar 477dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar // align rendertime to the center between VSYNC edges 478dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar renderTime -= (renderTime - mVsyncTime) % mVsyncPeriod; 479dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar renderTime += mVsyncPeriod / 2; 480dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar ALOGV("adjusting render: %lld => %lld", (long long)origRenderTime, (long long)renderTime); 481dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar ATRACE_INT("FRAME_FLIP_IN(ms)", (renderTime - now) / 1000000); 482dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar return renderTime; 483dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar} 484dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar 485dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnarvoid VideoFrameScheduler::release() { 486dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar mComposer.clear(); 487dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar} 488dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar 489dc43dfa1294470a4413c37e863ef3b621da8681fLajos MolnarVideoFrameScheduler::~VideoFrameScheduler() { 490dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar release(); 491dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar} 492dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar 493dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar} // namespace android 494dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar 495