Merge "Fix frame duration computations after discontinuities" into udc-dev am: 03ac6df71a am: 899452a7a1
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/av/+/23476322
Change-Id: I94811229a496bce765e0581f2ff1785bb962c70a
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 178458c..54ca1ea 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -6130,7 +6130,7 @@
ALOGI("rendring output error %d", err);
}
} else {
- if (mIsSurfaceToDisplay) {
+ if (mIsSurfaceToDisplay && buffer->size() != 0) {
int64_t mediaTimeUs = INT64_MIN;
if (buffer->meta()->findInt64("timeUs", &mediaTimeUs)) {
mVideoRenderQualityTracker.onFrameSkipped(mediaTimeUs);
diff --git a/media/libstagefright/VideoRenderQualityTracker.cpp b/media/libstagefright/VideoRenderQualityTracker.cpp
index c2ba767..4f12a37 100644
--- a/media/libstagefright/VideoRenderQualityTracker.cpp
+++ b/media/libstagefright/VideoRenderQualityTracker.cpp
@@ -228,6 +228,9 @@
if (mLastRenderTimeUs == -1) {
return;
}
+
+ resetIfDiscontinuity(contentTimeUs, -1);
+
// Frames skipped at the end of playback shouldn't be counted as skipped frames, since the
// app could be terminating the playback. The pending count will be added to the metrics if and
// when the next frame is rendered.
@@ -374,6 +377,9 @@
mDesiredFrameDurationUs[i] = -1;
mContentFrameDurationUs[i] = -1;
}
+ mActualFrameDurationUs.priorTimestampUs = -1;
+ mDesiredFrameDurationUs.priorTimestampUs = -1;
+ mContentFrameDurationUs.priorTimestampUs = -1;
}
bool VideoRenderQualityTracker::resetIfDiscontinuity(int64_t contentTimeUs,
@@ -397,11 +403,14 @@
// occur if the time the user spends seeking is equal to the duration of the seek. This is
// very unlikely to occur in practice but CAN occur - the user starts seeking forward, gets
// distracted, and then returns to seeking forward.
- int64_t contentFrameDurationUs = contentTimeUs - mLastContentTimeUs;
- int64_t desiredFrameDurationUs = desiredRenderTimeUs - mLastRenderTimeUs;
- bool skippedForwardDueToLiveContentFrameDrops =
- abs(contentFrameDurationUs - desiredFrameDurationUs) <
- mConfiguration.liveContentFrameDropToleranceUs;
+ bool skippedForwardDueToLiveContentFrameDrops = false;
+ if (desiredRenderTimeUs != -1) {
+ int64_t contentFrameDurationUs = contentTimeUs - mLastContentTimeUs;
+ int64_t desiredFrameDurationUs = desiredRenderTimeUs - mLastRenderTimeUs;
+ skippedForwardDueToLiveContentFrameDrops =
+ abs(contentFrameDurationUs - desiredFrameDurationUs) <
+ mConfiguration.liveContentFrameDropToleranceUs;
+ }
if (!skippedForwardDueToLiveContentFrameDrops) {
ALOGI("Video playback jumped %d ms forward in content time (%d -> %d) ",
int((contentTimeUs - mLastContentTimeUs) / 1000), int(mLastContentTimeUs / 1000),
@@ -475,9 +484,9 @@
int64_t judderScore = computePreviousJudderScore(mActualFrameDurationUs,
mContentFrameDurationUs,
mConfiguration);
- int64_t judderTimeUs = actualRenderTimeUs - mActualFrameDurationUs[0] -
- mActualFrameDurationUs[1];
if (judderScore != 0) {
+ int64_t judderTimeUs = actualRenderTimeUs - mActualFrameDurationUs[0] -
+ mActualFrameDurationUs[1];
processJudder(judderScore, judderTimeUs, mLastJudderEndTimeUs, mActualFrameDurationUs,
mContentFrameDurationUs, mJudderEvent, mMetrics, mConfiguration);
mLastJudderEndTimeUs = judderTimeUs + mActualFrameDurationUs[1];
diff --git a/media/libstagefright/tests/VideoRenderQualityTracker_test.cpp b/media/libstagefright/tests/VideoRenderQualityTracker_test.cpp
index db29bb5..7823922 100644
--- a/media/libstagefright/tests/VideoRenderQualityTracker_test.cpp
+++ b/media/libstagefright/tests/VideoRenderQualityTracker_test.cpp
@@ -432,6 +432,80 @@
EXPECT_NEAR(h.getMetrics().actualFrameRate, 60.0, 0.5);
}
+TEST_F(VideoRenderQualityTrackerTest, handlesSeeking) {
+ Configuration c;
+ c.maxExpectedContentFrameDurationUs = 30;
+ VideoRenderQualityTracker v(c);
+ v.onFrameReleased(0, 0);
+ v.onFrameRendered(0, 0);
+ v.onFrameReleased(20, 20);
+ v.onFrameRendered(20, 20);
+ v.onFrameReleased(40, 40);
+ v.onFrameRendered(40, 40);
+ v.onFrameReleased(60, 60);
+ v.onFrameRendered(60, 60);
+ v.onFrameReleased(80, 80);
+ v.onFrameRendered(80, 80);
+ v.onFrameReleased(7200000000, 100);
+ v.onFrameRendered(7200000000, 100);
+ v.onFrameReleased(7200000020, 120);
+ v.onFrameRendered(7200000020, 120);
+ v.onFrameReleased(7200000040, 140);
+ v.onFrameRendered(7200000040, 140);
+ v.onFrameReleased(7200000060, 160);
+ v.onFrameRendered(7200000060, 160);
+ v.onFrameReleased(7200000080, 180);
+ v.onFrameRendered(7200000080, 180);
+ v.onFrameReleased(0, 200);
+ v.onFrameRendered(0, 200);
+ v.onFrameReleased(20, 220);
+ v.onFrameRendered(20, 220);
+ v.onFrameReleased(40, 240);
+ v.onFrameRendered(40, 240);
+ v.onFrameReleased(60, 260);
+ v.onFrameRendered(60, 260);
+ const VideoRenderQualityMetrics &m = v.getMetrics();
+ EXPECT_EQ(m.judderRate, 0); // frame durations can get messed up during discontinuities so if
+ // the discontinuity is not detected, judder is expected
+ EXPECT_NE(m.contentFrameRate, FRAME_RATE_UNDETERMINED);
+}
+
+TEST_F(VideoRenderQualityTrackerTest, withSkipping_handlesSeeking) {
+ Configuration c;
+ c.maxExpectedContentFrameDurationUs = 30;
+ VideoRenderQualityTracker v(c);
+ v.onFrameReleased(0, 0);
+ v.onFrameRendered(0, 0);
+ v.onFrameReleased(20, 20);
+ v.onFrameRendered(20, 20);
+ v.onFrameReleased(40, 40);
+ v.onFrameRendered(40, 40);
+ v.onFrameReleased(60, 60);
+ v.onFrameRendered(60, 60);
+ v.onFrameReleased(80, 80);
+ v.onFrameRendered(80, 80);
+ v.onFrameSkipped(7200000000);
+ v.onFrameSkipped(7200000020);
+ v.onFrameReleased(7200000040, 100);
+ v.onFrameRendered(7200000040, 100);
+ v.onFrameReleased(7200000060, 120);
+ v.onFrameRendered(7200000060, 120);
+ v.onFrameReleased(7200000080, 140);
+ v.onFrameSkipped(0);
+ v.onFrameRendered(7200000080, 140);
+ v.onFrameSkipped(20);
+ v.onFrameReleased(40, 160);
+ v.onFrameRendered(40, 160);
+ v.onFrameReleased(60, 180);
+ v.onFrameRendered(60, 180);
+ v.onFrameReleased(80, 200);
+ v.onFrameRendered(80, 200);
+ const VideoRenderQualityMetrics &m = v.getMetrics();
+ EXPECT_EQ(m.judderRate, 0); // frame durations can get messed up during discontinuities so if
+ // the discontinuity is not detected, judder is expected
+ EXPECT_NE(m.contentFrameRate, FRAME_RATE_UNDETERMINED);
+}
+
TEST_F(VideoRenderQualityTrackerTest, whenLowTolerance_doesntDetectFrameRate) {
Configuration c;
c.frameRateDetectionToleranceUs = 0;