Fix freeze rate calculations

Using the actual render duration to determine if the previous frame was
dropped is flawed at the beginning of playback because the first frame
never has a previous frame.

Bug: 234833109
Test: atest VideoRenderQualityTrackerTest#capturesFreezeRate
Change-Id: I6d3db5e662462ec802e368e5a611c0bbb2f463b3
diff --git a/media/libstagefright/VideoRenderQualityTracker.cpp b/media/libstagefright/VideoRenderQualityTracker.cpp
index df25ead..239aefc 100644
--- a/media/libstagefright/VideoRenderQualityTracker.cpp
+++ b/media/libstagefright/VideoRenderQualityTracker.cpp
@@ -232,6 +232,7 @@
     mLastContentTimeUs = -1;
     mLastRenderTimeUs = -1;
     mLastFreezeEndTimeUs = -1;
+    mWasPreviousFrameDropped = false;
 
     // Don't worry about tracking frame rendering times from now up until playback catches up to the
     // discontinuity. While stuttering or freezing could be found in the next few frames, the impact
@@ -298,6 +299,7 @@
     updateFrameDurations(mDesiredFrameDurationUs, -1);
     updateFrameDurations(mActualFrameDurationUs, -1);
     updateFrameRate(mMetrics.contentFrameRate, mContentFrameDurationUs, mConfiguration);
+    mWasPreviousFrameDropped = false;
 }
 
 void VideoRenderQualityTracker::processMetricsForDroppedFrame(int64_t contentTimeUs,
@@ -308,6 +310,7 @@
     updateFrameDurations(mActualFrameDurationUs, -1);
     updateFrameRate(mMetrics.contentFrameRate, mContentFrameDurationUs, mConfiguration);
     updateFrameRate(mMetrics.desiredFrameRate, mDesiredFrameDurationUs, mConfiguration);
+    mWasPreviousFrameDropped = true;
 }
 
 void VideoRenderQualityTracker::processMetricsForRenderedFrame(int64_t contentTimeUs,
@@ -334,7 +337,7 @@
     updateFrameRate(mMetrics.actualFrameRate, mActualFrameDurationUs, mConfiguration);
 
     // If the previous frame was dropped, there was a freeze if we've already rendered a frame
-    if (mActualFrameDurationUs[1] == -1 && mLastRenderTimeUs != -1) {
+    if (mWasPreviousFrameDropped && mLastRenderTimeUs != -1) {
         processFreeze(actualRenderTimeUs, mLastRenderTimeUs, mLastFreezeEndTimeUs, mMetrics);
         mLastFreezeEndTimeUs = actualRenderTimeUs;
     }
@@ -346,6 +349,8 @@
     if (judderScore != 0) {
         mMetrics.judderScoreHistogram.insert(judderScore);
     }
+
+    mWasPreviousFrameDropped = false;
 }
 
 void VideoRenderQualityTracker::processFreeze(int64_t actualRenderTimeUs, int64_t lastRenderTimeUs,
diff --git a/media/libstagefright/include/media/stagefright/VideoRenderQualityTracker.h b/media/libstagefright/include/media/stagefright/VideoRenderQualityTracker.h
index 8bfead9..5cf674f 100644
--- a/media/libstagefright/include/media/stagefright/VideoRenderQualityTracker.h
+++ b/media/libstagefright/include/media/stagefright/VideoRenderQualityTracker.h
@@ -269,6 +269,9 @@
     // The most recent timestamp of the first frame rendered after the freeze.
     int64_t mLastFreezeEndTimeUs;
 
+    // The previous video frame was dropped.
+    bool mWasPreviousFrameDropped;
+
     // The render duration of the playback.
     int64_t mRenderDurationMs;
 
diff --git a/media/libstagefright/tests/VideoRenderQualityTracker_test.cpp b/media/libstagefright/tests/VideoRenderQualityTracker_test.cpp
index 9f14663..aca31f2 100644
--- a/media/libstagefright/tests/VideoRenderQualityTracker_test.cpp
+++ b/media/libstagefright/tests/VideoRenderQualityTracker_test.cpp
@@ -232,6 +232,18 @@
     EXPECT_EQ(h.getMetrics().actualFrameRate, FRAME_RATE_UNDETERMINED);
 }
 
+TEST_F(VideoRenderQualityTrackerTest, capturesFreezeRate) {
+    Configuration c;
+    Helper h(20, c);
+    h.render(3);
+    EXPECT_EQ(h.getMetrics().freezeRate, 0);
+    h.drop(3);
+    h.render(3);
+    // +1 because the first frame before drops is considered frozen
+    // and then -1 because the last frame has an unknown render duration
+    EXPECT_EQ(h.getMetrics().freezeRate, 4.0 / 8.0);
+}
+
 TEST_F(VideoRenderQualityTrackerTest, capturesFreezeDurationHistogram) {
     Configuration c;
     // +17 because freeze durations include the render time of the previous frame