Make video render quality metrics configurable
Bug: 234833109
Test: atest VideoRenderQualityTracker_test
Test: manual test with 'adb shell device_config' commands
Change-Id: I9b06fd1c5085e32ba4a87b1bd5ccc0e6797f058d
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index f1534c9..a26fcbe 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -314,6 +314,7 @@
"framework-permission-aidl-cpp",
"libaudioclient_aidl_conversion",
"packagemanager_aidl-cpp",
+ "server_configurable_flags",
],
static_libs: [
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 9f16a81..178458c 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -82,6 +82,7 @@
#include <media/stagefright/SurfaceUtils.h>
#include <nativeloader/dlext_namespaces.h>
#include <private/android_filesystem_config.h>
+#include <server_configurable_flags/get_flags.h>
#include <utils/Singleton.h>
namespace android {
@@ -1024,6 +1025,9 @@
mHavePendingInputBuffers(false),
mCpuBoostRequested(false),
mIsSurfaceToDisplay(false),
+ mVideoRenderQualityTracker(
+ VideoRenderQualityTracker::Configuration::getFromServerConfigurableFlags(
+ server_configurable_flags::GetServerConfigurableFlag)),
mLatencyUnknown(0),
mBytesEncoded(0),
mEarliestEncodedPtsUs(INT64_MAX),
diff --git a/media/libstagefright/VideoRenderQualityTracker.cpp b/media/libstagefright/VideoRenderQualityTracker.cpp
index e46deea..0996b87 100644
--- a/media/libstagefright/VideoRenderQualityTracker.cpp
+++ b/media/libstagefright/VideoRenderQualityTracker.cpp
@@ -20,15 +20,92 @@
#include <media/stagefright/VideoRenderQualityTracker.h>
#include <assert.h>
+#include <charconv>
#include <cmath>
+#include <stdio.h>
#include <sys/time.h>
+#include <android-base/parsebool.h>
+#include <android-base/parseint.h>
+
namespace android {
+using android::base::ParseBoolResult;
+
static constexpr float FRAME_RATE_UNDETERMINED = VideoRenderQualityMetrics::FRAME_RATE_UNDETERMINED;
static constexpr float FRAME_RATE_24_3_2_PULLDOWN =
VideoRenderQualityMetrics::FRAME_RATE_24_3_2_PULLDOWN;
+typedef VideoRenderQualityTracker::Configuration::GetServerConfigurableFlagFn
+ GetServerConfigurableFlagFn;
+
+static void getServerConfigurableFlag(GetServerConfigurableFlagFn getServerConfigurableFlagFn,
+ char const *flagNameSuffix, bool *value) {
+ std::string flagName("render_metrics_");
+ flagName.append(flagNameSuffix);
+ std::string valueStr = (*getServerConfigurableFlagFn)("media_native", flagName,
+ *value ? "true" : "false");
+ switch (android::base::ParseBool(valueStr)) {
+ case ParseBoolResult::kTrue: *value = true; break;
+ case ParseBoolResult::kFalse: *value = false; break;
+ case ParseBoolResult::kError:
+ ALOGW("failed to parse server-configurable flag '%s' from '%s'", flagNameSuffix,
+ valueStr.c_str());
+ break;
+ }
+}
+
+static void getServerConfigurableFlag(GetServerConfigurableFlagFn getServerConfigurableFlagFn,
+ char const *flagNameSuffix, int32_t *value) {
+ char defaultStr[11];
+ sprintf(defaultStr, "%d", int(*value));
+ std::string flagName("render_metrics_");
+ flagName.append(flagNameSuffix);
+ std::string valueStr = (*getServerConfigurableFlagFn)("media_native", flagName, defaultStr);
+ if (!android::base::ParseInt(valueStr.c_str(), value) || valueStr.size() == 0) {
+ ALOGW("failed to parse server-configurable flag '%s' from '%s'", flagNameSuffix,
+ valueStr.c_str());
+ return;
+ }
+}
+
+template<typename T>
+static void getServerConfigurableFlag(GetServerConfigurableFlagFn getServerConfigurableFlagFn,
+ char const *flagNameSuffix, std::vector<T> *value) {
+ std::stringstream sstr;
+ for (int i = 0; i < value->size(); ++i) {
+ if (i != 0) {
+ sstr << ",";
+ }
+ sstr << (*value)[i];
+ }
+ std::string flagName("render_metrics_");
+ flagName.append(flagNameSuffix);
+ std::string valueStr = (*getServerConfigurableFlagFn)("media_native", flagName, sstr.str());
+ if (valueStr.size() == 0) {
+ return;
+ }
+ // note: using android::base::Tokenize fails to catch parsing failures for values ending in ','
+ std::vector<T> newValues;
+ const char *p = valueStr.c_str();
+ const char *last = p + valueStr.size();
+ while (p != last) {
+ if (*p == ',') {
+ p++;
+ }
+ T value = -1;
+ auto [ptr, error] = std::from_chars(p, last, value);
+ if (error == std::errc::invalid_argument || error == std::errc::result_out_of_range) {
+ ALOGW("failed to parse server-configurable flag '%s' from '%s'", flagNameSuffix,
+ valueStr.c_str());
+ return;
+ }
+ p = ptr;
+ newValues.push_back(value);
+ }
+ *value = std::move(newValues);
+}
+
VideoRenderQualityMetrics::VideoRenderQualityMetrics() {
clear();
}
@@ -49,6 +126,33 @@
judderScoreHistogram.clear();
}
+VideoRenderQualityTracker::Configuration
+ VideoRenderQualityTracker::Configuration::getFromServerConfigurableFlags(
+ GetServerConfigurableFlagFn getServerConfigurableFlagFn) {
+ VideoRenderQualityTracker::Configuration c;
+#define getFlag(FIELDNAME, FLAGNAME) \
+ getServerConfigurableFlag(getServerConfigurableFlagFn, FLAGNAME, &c.FIELDNAME)
+ getFlag(enabled, "enabled");
+ getFlag(areSkippedFramesDropped, "are_skipped_frames_dropped");
+ getFlag(maxExpectedContentFrameDurationUs, "max_expected_content_frame_duration_us");
+ getFlag(frameRateDetectionToleranceUs, "frame_rate_detection_tolerance_us");
+ getFlag(liveContentFrameDropToleranceUs, "live_content_frame_drop_tolerance_us");
+ getFlag(freezeDurationMsHistogramBuckets, "freeze_duration_ms_histogram_buckets");
+ getFlag(freezeDurationMsHistogramToScore, "freeze_duration_ms_histogram_to_score");
+ getFlag(freezeDistanceMsHistogramBuckets, "freeze_distance_ms_histogram_buckets");
+ getFlag(freezeEventMax, "freeze_event_max");
+ getFlag(freezeEventDetailsMax, "freeze_event_details_max");
+ getFlag(freezeEventDistanceToleranceMs, "freeze_event_distance_tolerance_ms");
+ getFlag(judderErrorToleranceUs, "judder_error_tolerance_us");
+ getFlag(judderScoreHistogramBuckets, "judder_score_histogram_buckets");
+ getFlag(judderScoreHistogramToScore, "judder_score_histogram_to_score");
+ getFlag(judderEventMax, "judder_event_max");
+ getFlag(judderEventDetailsMax, "judder_event_details_max");
+ getFlag(judderEventDistanceToleranceMs, "judder_event_distance_tolerance_ms");
+#undef getFlag
+ return c;
+}
+
VideoRenderQualityTracker::Configuration::Configuration() {
enabled = true;
@@ -64,7 +168,7 @@
// Allow for a tolerance of 200 milliseconds for determining if we moved forward in content time
// because of frame drops for live content, or because the user is seeking.
- contentTimeAdvancedForLiveContentToleranceUs = 200 * 1000;
+ liveContentFrameDropToleranceUs = 200 * 1000;
// Freeze configuration
freezeDurationMsHistogramBuckets = {1, 20, 40, 60, 80, 100, 120, 150, 175, 225, 300, 400, 500};
@@ -303,7 +407,7 @@
int64_t desiredFrameDurationUs = desiredRenderTimeUs - mLastRenderTimeUs;
bool skippedForwardDueToLiveContentFrameDrops =
abs(contentFrameDurationUs - desiredFrameDurationUs) <
- mConfiguration.contentTimeAdvancedForLiveContentToleranceUs;
+ mConfiguration.liveContentFrameDropToleranceUs;
if (!skippedForwardDueToLiveContentFrameDrops) {
ALOGI("Video playback jumped %d ms forward in content time (%d -> %d) ",
int((contentTimeUs - mLastContentTimeUs) / 1000), int(mLastContentTimeUs / 1000),
diff --git a/media/libstagefright/include/media/stagefright/VideoRenderQualityTracker.h b/media/libstagefright/include/media/stagefright/VideoRenderQualityTracker.h
index 0fd6a5b..2b3dbcb 100644
--- a/media/libstagefright/include/media/stagefright/VideoRenderQualityTracker.h
+++ b/media/libstagefright/include/media/stagefright/VideoRenderQualityTracker.h
@@ -105,6 +105,15 @@
// Configurable elements of the metrics algorithms
class Configuration {
public:
+ // system/server_configurable_flags/libflags/include/get_flags.h:GetServerConfigurableFlag
+ typedef std::string (*GetServerConfigurableFlagFn)(
+ const std::string& experiment_category_name,
+ const std::string& experiment_flag_name,
+ const std::string& default_value);
+
+ static Configuration getFromServerConfigurableFlags(
+ GetServerConfigurableFlagFn getServerConfigurableFlagFn);
+
Configuration();
// Whether or not frame render quality is tracked.
@@ -128,7 +137,7 @@
// skip forward in content time is due to frame drops. If the app-desired frame duration is
// short, but the content frame duration is large, it is assumed the app is intentionally
// seeking forward.
- int32_t contentTimeAdvancedForLiveContentToleranceUs;
+ int32_t liveContentFrameDropToleranceUs;
// Freeze configuration
//
@@ -140,12 +149,12 @@
// The values used to distribute distances between freezes across a histogram.
std::vector<int32_t> freezeDistanceMsHistogramBuckets;
// The maximum number of freeze events to send back to the caller.
- int64_t freezeEventMax;
+ int32_t freezeEventMax;
// The maximum number of detail entries tracked per freeze event.
- int64_t freezeEventDetailsMax;
+ int32_t freezeEventDetailsMax;
// The maximum distance in time between two freeze occurrences such that both will be
// lumped into the same freeze event.
- int64_t freezeEventDistanceToleranceMs;
+ int32_t freezeEventDistanceToleranceMs;
// Judder configuration
//
@@ -155,14 +164,14 @@
std::vector<int32_t> judderScoreHistogramBuckets;
// The values used to compare against judder score histogram counts when determining an
// overall score.
- std::vector<int32_t> judderScoreHistogramToScore;
+ std::vector<int64_t> judderScoreHistogramToScore;
// The maximum number of judder events to send back to the caller.
- int64_t judderEventMax;
+ int32_t judderEventMax;
// The maximum number of detail entries tracked per judder event.
- int64_t judderEventDetailsMax;
+ int32_t judderEventDetailsMax;
// The maximum distance in time between two judder occurrences such that both will be
// lumped into the same judder event.
- int64_t judderEventDistanceToleranceMs;
+ int32_t judderEventDistanceToleranceMs;
};
struct FreezeEvent {
diff --git a/media/libstagefright/tests/Android.bp b/media/libstagefright/tests/Android.bp
index 7f89605..581292e 100644
--- a/media/libstagefright/tests/Android.bp
+++ b/media/libstagefright/tests/Android.bp
@@ -60,10 +60,10 @@
name: "VideoRenderQualityTracker_test",
srcs: ["VideoRenderQualityTracker_test.cpp"],
- // TODO(b/234833109): Figure out why shared_libs linkage causes stack corruption
- static_libs: [
- "libstagefright",
+ shared_libs: [
+ "libbase",
"liblog",
+ "libstagefright",
],
cflags: [
diff --git a/media/libstagefright/tests/VideoRenderQualityTracker_test.cpp b/media/libstagefright/tests/VideoRenderQualityTracker_test.cpp
index 5aac34a..3ff7482 100644
--- a/media/libstagefright/tests/VideoRenderQualityTracker_test.cpp
+++ b/media/libstagefright/tests/VideoRenderQualityTracker_test.cpp
@@ -114,6 +114,247 @@
VideoRenderQualityTrackerTest() {}
};
+TEST_F(VideoRenderQualityTrackerTest, getFromServerConfigurableFlags_withDefaults) {
+ Configuration::GetServerConfigurableFlagFn getServerConfigurableFlagFn =
+ [](const std::string &, const std::string &, const std::string &defaultStr) -> std::string {
+ return defaultStr;
+ };
+
+ Configuration c = Configuration::getFromServerConfigurableFlags(getServerConfigurableFlagFn);
+ Configuration d; // default configuration
+ EXPECT_EQ(c.enabled, d.enabled);
+ EXPECT_EQ(c.areSkippedFramesDropped, d.areSkippedFramesDropped);
+ EXPECT_EQ(c.maxExpectedContentFrameDurationUs, d.maxExpectedContentFrameDurationUs);
+ EXPECT_EQ(c.frameRateDetectionToleranceUs, d.frameRateDetectionToleranceUs);
+ EXPECT_EQ(c.liveContentFrameDropToleranceUs, d.liveContentFrameDropToleranceUs);
+ EXPECT_EQ(c.freezeDurationMsHistogramBuckets, d.freezeDurationMsHistogramBuckets);
+ EXPECT_EQ(c.freezeDurationMsHistogramToScore, d.freezeDurationMsHistogramToScore);
+ EXPECT_EQ(c.freezeDistanceMsHistogramBuckets, d.freezeDistanceMsHistogramBuckets);
+ EXPECT_EQ(c.freezeEventMax, d.freezeEventMax);
+ EXPECT_EQ(c.freezeEventDetailsMax, d.freezeEventDetailsMax);
+ EXPECT_EQ(c.freezeEventDistanceToleranceMs, d.freezeEventDistanceToleranceMs);
+ EXPECT_EQ(c.judderErrorToleranceUs, d.judderErrorToleranceUs);
+ EXPECT_EQ(c.judderScoreHistogramBuckets, d.judderScoreHistogramBuckets);
+ EXPECT_EQ(c.judderScoreHistogramToScore, d.judderScoreHistogramToScore);
+ EXPECT_EQ(c.judderEventMax, d.judderEventMax);
+ EXPECT_EQ(c.judderEventDetailsMax, d.judderEventDetailsMax);
+ EXPECT_EQ(c.judderEventDistanceToleranceMs, d.judderEventDistanceToleranceMs);
+}
+
+TEST_F(VideoRenderQualityTrackerTest, getFromServerConfigurableFlags_withEmpty) {
+ Configuration::GetServerConfigurableFlagFn getServerConfigurableFlagFn{
+ [](const std::string &, const std::string &, const std::string &) -> std::string {
+ return "";
+ }
+ };
+ Configuration c = Configuration::getFromServerConfigurableFlags(getServerConfigurableFlagFn);
+ Configuration d; // default configuration
+ EXPECT_EQ(c.enabled, d.enabled);
+ EXPECT_EQ(c.areSkippedFramesDropped, d.areSkippedFramesDropped);
+ EXPECT_EQ(c.maxExpectedContentFrameDurationUs, d.maxExpectedContentFrameDurationUs);
+ EXPECT_EQ(c.frameRateDetectionToleranceUs, d.frameRateDetectionToleranceUs);
+ EXPECT_EQ(c.liveContentFrameDropToleranceUs, d.liveContentFrameDropToleranceUs);
+ EXPECT_EQ(c.freezeDurationMsHistogramBuckets, d.freezeDurationMsHistogramBuckets);
+ EXPECT_EQ(c.freezeDurationMsHistogramToScore, d.freezeDurationMsHistogramToScore);
+ EXPECT_EQ(c.freezeDistanceMsHistogramBuckets, d.freezeDistanceMsHistogramBuckets);
+ EXPECT_EQ(c.freezeEventMax, d.freezeEventMax);
+ EXPECT_EQ(c.freezeEventDetailsMax, d.freezeEventDetailsMax);
+ EXPECT_EQ(c.freezeEventDistanceToleranceMs, d.freezeEventDistanceToleranceMs);
+ EXPECT_EQ(c.judderErrorToleranceUs, d.judderErrorToleranceUs);
+ EXPECT_EQ(c.judderScoreHistogramBuckets, d.judderScoreHistogramBuckets);
+ EXPECT_EQ(c.judderScoreHistogramToScore, d.judderScoreHistogramToScore);
+ EXPECT_EQ(c.judderEventMax, d.judderEventMax);
+ EXPECT_EQ(c.judderEventDetailsMax, d.judderEventDetailsMax);
+ EXPECT_EQ(c.judderEventDistanceToleranceMs, d.judderEventDistanceToleranceMs);
+}
+
+TEST_F(VideoRenderQualityTrackerTest, getFromServerConfigurableFlags_withInvalid) {
+ Configuration::GetServerConfigurableFlagFn getServerConfigurableFlagFn{
+ [](const std::string &, const std::string &, const std::string &) -> std::string {
+ return "abc";
+ }
+ };
+ Configuration c = Configuration::getFromServerConfigurableFlags(getServerConfigurableFlagFn);
+ Configuration d; // default configuration
+ EXPECT_EQ(c.enabled, d.enabled);
+ EXPECT_EQ(c.areSkippedFramesDropped, d.areSkippedFramesDropped);
+ EXPECT_EQ(c.maxExpectedContentFrameDurationUs, d.maxExpectedContentFrameDurationUs);
+ EXPECT_EQ(c.frameRateDetectionToleranceUs, d.frameRateDetectionToleranceUs);
+ EXPECT_EQ(c.liveContentFrameDropToleranceUs, d.liveContentFrameDropToleranceUs);
+ EXPECT_EQ(c.freezeDurationMsHistogramBuckets, d.freezeDurationMsHistogramBuckets);
+ EXPECT_EQ(c.freezeDurationMsHistogramToScore, d.freezeDurationMsHistogramToScore);
+ EXPECT_EQ(c.freezeDistanceMsHistogramBuckets, d.freezeDistanceMsHistogramBuckets);
+ EXPECT_EQ(c.freezeEventMax, d.freezeEventMax);
+ EXPECT_EQ(c.freezeEventDetailsMax, d.freezeEventDetailsMax);
+ EXPECT_EQ(c.freezeEventDistanceToleranceMs, d.freezeEventDistanceToleranceMs);
+ EXPECT_EQ(c.judderErrorToleranceUs, d.judderErrorToleranceUs);
+ EXPECT_EQ(c.judderScoreHistogramBuckets, d.judderScoreHistogramBuckets);
+ EXPECT_EQ(c.judderScoreHistogramToScore, d.judderScoreHistogramToScore);
+ EXPECT_EQ(c.judderEventMax, d.judderEventMax);
+ EXPECT_EQ(c.judderEventDetailsMax, d.judderEventDetailsMax);
+ EXPECT_EQ(c.judderEventDistanceToleranceMs, d.judderEventDistanceToleranceMs);
+}
+
+TEST_F(VideoRenderQualityTrackerTest, getFromServerConfigurableFlags_withAlmostValid) {
+ Configuration::GetServerConfigurableFlagFn getServerConfigurableFlagFn{
+ [](const std::string &, const std::string &flag, const std::string &) -> std::string {
+ if (flag == "render_metrics_enabled") {
+ return "fals";
+ } else if (flag == "render_metrics_are_skipped_frames_dropped") {
+ return "fals";
+ } else if (flag == "render_metrics_max_expected_content_frame_duration_us") {
+ return "100a";
+ } else if (flag == "render_metrics_frame_rate_detection_tolerance_us") {
+ return "10b0";
+ } else if (flag == "render_metrics_live_content_frame_drop_tolerance_us") {
+ return "c100";
+ } else if (flag == "render_metrics_freeze_duration_ms_histogram_buckets") {
+ return "1,5300,3b400,123";
+ } else if (flag == "render_metrics_freeze_duration_ms_histogram_to_score") {
+ return "2,5300*400,132";
+ } else if (flag == "render_metrics_freeze_distance_ms_histogram_buckets") {
+ return "3,12345678901234,5,7";
+ } else if (flag == "render_metrics_freeze_event_max") {
+ return "12345678901234";
+ } else if (flag == "render_metrics_freeze_event_details_max") {
+ return "12345.11321";
+ } else if (flag == "render_metrics_freeze_event_distance_tolerance_ms") {
+ return "*!-";
+ } else if (flag == "render_metrics_judder_error_tolerance_us") {
+ return "10.5";
+ } else if (flag == "render_metrics_judder_score_histogram_buckets") {
+ return "abc";
+ } else if (flag == "render_metrics_judder_score_histogram_to_score") {
+ return "123,";
+ } else if (flag == "render_metrics_judder_event_max") {
+ return ",1234";
+ } else if (flag == "render_metrics_judder_event_details_max") {
+ return "10*10";
+ } else if (flag == "render_metrics_judder_event_distance_tolerance_ms") {
+ return "140-a";
+ }
+ return "";
+ }
+ };
+ Configuration c = Configuration::getFromServerConfigurableFlags(getServerConfigurableFlagFn);
+ Configuration d; // default configuration
+ EXPECT_EQ(c.enabled, d.enabled);
+ EXPECT_EQ(c.areSkippedFramesDropped, d.areSkippedFramesDropped);
+ EXPECT_EQ(c.maxExpectedContentFrameDurationUs, d.maxExpectedContentFrameDurationUs);
+ EXPECT_EQ(c.frameRateDetectionToleranceUs, d.frameRateDetectionToleranceUs);
+ EXPECT_EQ(c.liveContentFrameDropToleranceUs, d.liveContentFrameDropToleranceUs);
+ EXPECT_EQ(c.freezeDurationMsHistogramBuckets, d.freezeDurationMsHistogramBuckets);
+ EXPECT_EQ(c.freezeDurationMsHistogramToScore, d.freezeDurationMsHistogramToScore);
+ EXPECT_EQ(c.freezeDistanceMsHistogramBuckets, d.freezeDistanceMsHistogramBuckets);
+ EXPECT_EQ(c.freezeEventMax, d.freezeEventMax);
+ EXPECT_EQ(c.freezeEventDetailsMax, d.freezeEventDetailsMax);
+ EXPECT_EQ(c.freezeEventDistanceToleranceMs, d.freezeEventDistanceToleranceMs);
+ EXPECT_EQ(c.judderErrorToleranceUs, d.judderErrorToleranceUs);
+ EXPECT_EQ(c.judderScoreHistogramBuckets, d.judderScoreHistogramBuckets);
+ EXPECT_EQ(c.judderScoreHistogramToScore, d.judderScoreHistogramToScore);
+ EXPECT_EQ(c.judderEventMax, d.judderEventMax);
+ EXPECT_EQ(c.judderEventDetailsMax, d.judderEventDetailsMax);
+ EXPECT_EQ(c.judderEventDistanceToleranceMs, d.judderEventDistanceToleranceMs);
+}
+
+TEST_F(VideoRenderQualityTrackerTest, getFromServerConfigurableFlags_withValid) {
+ Configuration::GetServerConfigurableFlagFn getServerConfigurableFlagFn{
+ [](const std::string &, const std::string &flag, const std::string &) -> std::string {
+ if (flag == "render_metrics_enabled") {
+ return "false";
+ } else if (flag == "render_metrics_are_skipped_frames_dropped") {
+ return "false";
+ } else if (flag == "render_metrics_max_expected_content_frame_duration_us") {
+ return "2000";
+ } else if (flag == "render_metrics_frame_rate_detection_tolerance_us") {
+ return "3000";
+ } else if (flag == "render_metrics_live_content_frame_drop_tolerance_us") {
+ return "4000";
+ } else if (flag == "render_metrics_freeze_duration_ms_histogram_buckets") {
+ return "100,200,300,400";
+ } else if (flag == "render_metrics_freeze_duration_ms_histogram_to_score") {
+ return "1234567890120,1234567890121,1234567890122";
+ } else if (flag == "render_metrics_freeze_distance_ms_histogram_buckets") {
+ return "500,600,700,800,900";
+ } else if (flag == "render_metrics_freeze_event_max") {
+ return "5000";
+ } else if (flag == "render_metrics_freeze_event_details_max") {
+ return "6000";
+ } else if (flag == "render_metrics_freeze_event_distance_tolerance_ms") {
+ return "7000";
+ } else if (flag == "render_metrics_judder_error_tolerance_us") {
+ return "8000";
+ } else if (flag == "render_metrics_judder_score_histogram_buckets") {
+ return "1,2,3,4,5";
+ } else if (flag == "render_metrics_judder_score_histogram_to_score") {
+ return "-1,-2,-3,-4,-5";
+ } else if (flag == "render_metrics_judder_event_max") {
+ return "9000";
+ } else if (flag == "render_metrics_judder_event_details_max") {
+ return "10000";
+ } else if (flag == "render_metrics_judder_event_distance_tolerance_ms") {
+ return "11000";
+ }
+ return "";
+ }
+ };
+
+ Configuration c = Configuration::getFromServerConfigurableFlags(getServerConfigurableFlagFn);
+ // The default configuration here used to verify we're not configuring the values to the
+ // default - if we are accidentally configuring to the default then we're not necessarily
+ // testing the parsing.
+ Configuration d;
+ EXPECT_EQ(c.enabled, false);
+ EXPECT_NE(c.enabled, d.enabled);
+ EXPECT_EQ(c.areSkippedFramesDropped, false);
+ EXPECT_NE(c.areSkippedFramesDropped, d.areSkippedFramesDropped);
+ EXPECT_EQ(c.maxExpectedContentFrameDurationUs, 2000);
+ EXPECT_NE(c.maxExpectedContentFrameDurationUs, d.maxExpectedContentFrameDurationUs);
+ EXPECT_EQ(c.frameRateDetectionToleranceUs, 3000);
+ EXPECT_NE(c.frameRateDetectionToleranceUs, d.frameRateDetectionToleranceUs);
+ EXPECT_EQ(c.liveContentFrameDropToleranceUs, 4000);
+ EXPECT_NE(c.liveContentFrameDropToleranceUs, d.liveContentFrameDropToleranceUs);
+ {
+ std::vector<int32_t> expected({100,200,300,400});
+ EXPECT_EQ(c.freezeDurationMsHistogramBuckets, expected);
+ EXPECT_NE(c.freezeDurationMsHistogramBuckets, d.freezeDurationMsHistogramBuckets);
+ }
+ {
+ std::vector<int64_t> expected({1234567890120LL,1234567890121LL,1234567890122LL});
+ EXPECT_EQ(c.freezeDurationMsHistogramToScore, expected);
+ EXPECT_NE(c.freezeDurationMsHistogramToScore, d.freezeDurationMsHistogramToScore);
+ }
+ {
+ std::vector<int32_t> expected({500,600,700,800,900});
+ EXPECT_EQ(c.freezeDistanceMsHistogramBuckets, expected);
+ EXPECT_NE(c.freezeDistanceMsHistogramBuckets, d.freezeDistanceMsHistogramBuckets);
+ }
+ EXPECT_EQ(c.freezeEventMax, 5000);
+ EXPECT_NE(c.freezeEventMax, d.freezeEventMax);
+ EXPECT_EQ(c.freezeEventDetailsMax, 6000);
+ EXPECT_NE(c.freezeEventDetailsMax, d.freezeEventDetailsMax);
+ EXPECT_EQ(c.freezeEventDistanceToleranceMs, 7000);
+ EXPECT_NE(c.freezeEventDistanceToleranceMs, d.freezeEventDistanceToleranceMs);
+ EXPECT_EQ(c.judderErrorToleranceUs, 8000);
+ EXPECT_NE(c.judderErrorToleranceUs, d.judderErrorToleranceUs);
+ {
+ std::vector<int32_t> expected({1,2,3,4,5});
+ EXPECT_EQ(c.judderScoreHistogramBuckets, expected);
+ EXPECT_NE(c.judderScoreHistogramBuckets, d.judderScoreHistogramBuckets);
+ }
+ {
+ std::vector<int64_t> expected({-1,-2,-3,-4,-5});
+ EXPECT_EQ(c.judderScoreHistogramToScore, expected);
+ EXPECT_NE(c.judderScoreHistogramToScore, d.judderScoreHistogramToScore);
+ }
+ EXPECT_EQ(c.judderEventMax, 9000);
+ EXPECT_NE(c.judderEventMax, d.judderEventMax);
+ EXPECT_EQ(c.judderEventDetailsMax, 10000);
+ EXPECT_NE(c.judderEventDetailsMax, d.judderEventDetailsMax);
+ EXPECT_EQ(c.judderEventDistanceToleranceMs, 11000);
+ EXPECT_NE(c.judderEventDistanceToleranceMs, d.judderEventDistanceToleranceMs);
+}
+
TEST_F(VideoRenderQualityTrackerTest, countsReleasedFrames) {
Configuration c;
Helper h(16.66, c);