From 5d6fb5e41f57a71bd5b2902dc8334825de7bdcc0 Mon Sep 17 00:00:00 2001 From: Lajos Molnar Date: Wed, 24 Sep 2014 11:30:21 -0700 Subject: [PATCH] mediaplayer: handle bad input in VideoFrameScheduler Bug: 17626098 Change-Id: I2ae22ed43b35ff532a47818b118dd328ce2abf63 --- media/libmediaplayerservice/VideoFrameScheduler.cpp | 18 +++++++++++++++--- media/libmediaplayerservice/VideoFrameScheduler.h | 3 ++- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/media/libmediaplayerservice/VideoFrameScheduler.cpp b/media/libmediaplayerservice/VideoFrameScheduler.cpp index 4251c4e381..1a5f3e0027 100644 --- a/media/libmediaplayerservice/VideoFrameScheduler.cpp +++ b/media/libmediaplayerservice/VideoFrameScheduler.cpp @@ -152,7 +152,7 @@ void VideoFrameScheduler::PLL::test() { #endif -void VideoFrameScheduler::PLL::fit( +bool VideoFrameScheduler::PLL::fit( nsecs_t phase, nsecs_t period, size_t numSamplesToUse, int64_t *a, int64_t *b, int64_t *err) { if (numSamplesToUse > mNumSamples) { @@ -187,6 +187,10 @@ void VideoFrameScheduler::PLL::fit( } int64_t div = numSamplesToUse * sumXX - sumX * sumX; + if (div == 0) { + return false; + } + int64_t a_nom = numSamplesToUse * sumXY - sumX * sumY; int64_t b_nom = sumXX * sumY - sumX * sumXY; *a = divRound(a_nom, div); @@ -198,6 +202,7 @@ void VideoFrameScheduler::PLL::fit( (long long)*a, (*a / (float)(1 << kPrecision)), (long long)*b, (*b / (float)(1 << kPrecision)), (long long)*err, (*err / (float)(1 << (kPrecision * 2)))); + return true; } void VideoFrameScheduler::PLL::prime(size_t numSamplesToUse) { @@ -226,7 +231,7 @@ void VideoFrameScheduler::PLL::prime(size_t numSamplesToUse) { deltas.sort(compare); size_t numDeltas = deltas.size(); if (numDeltas > 1) { - nsecs_t deltaMinLimit = min(deltas[0] / kMultiplesThresholdDiv, kMinPeriod); + nsecs_t deltaMinLimit = max(deltas[0] / kMultiplesThresholdDiv, kMinPeriod); nsecs_t deltaMaxLimit = deltas[numDeltas / 2] * kMultiplesThresholdDiv; for (size_t i = numDeltas / 2 + 1; i < numDeltas; ++i) { if (deltas[i] > deltaMaxLimit) { @@ -314,8 +319,15 @@ nsecs_t VideoFrameScheduler::PLL::addSample(nsecs_t time) { if (doFit) { int64_t a, b, err; + if (!fit(mPhase, mPeriod, kMaxSamplesToEstimatePeriod, &a, &b, &err)) { + // samples are not suitable for fitting. this means they are + // also not suitable for priming. + ALOGV("could not fit - keeping old period:%lld", (long long)mPeriod); + return mPeriod; + } + mRefitAt = time + kRefitRefreshPeriod; - fit(mPhase, mPeriod, kMaxSamplesToEstimatePeriod, &a, &b, &err); + mPhase += (mPeriod * b) >> kPrecision; mPeriod = (mPeriod * a) >> kPrecision; ALOGV("new phase:%lld period:%lld", (long long)mPhase, (long long)mPeriod); diff --git a/media/libmediaplayerservice/VideoFrameScheduler.h b/media/libmediaplayerservice/VideoFrameScheduler.h index 19f0787fd5..84b27b4b4e 100644 --- a/media/libmediaplayerservice/VideoFrameScheduler.h +++ b/media/libmediaplayerservice/VideoFrameScheduler.h @@ -71,7 +71,8 @@ private: nsecs_t mTimes[kHistorySize]; void test(); - void fit(nsecs_t phase, nsecs_t period, size_t numSamples, + // returns whether fit was successful + bool fit(nsecs_t phase, nsecs_t period, size_t numSamples, int64_t *a, int64_t *b, int64_t *err); void prime(size_t numSamples); }; -- 2.11.0