Merge "Add tests for AudioInput|OutputFlags conversion" into main
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.cpp
index 18d0d95..e4ec2ba 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.cpp
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.cpp
@@ -169,8 +169,8 @@
const auto& measure = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
aidlParam, Visualizer, visualizer, Visualizer::measurement, Visualizer::Measurement));
int32_t* reply = (int32_t *) pReplyData;
- *reply++ = measure.rms;
- *reply = measure.peak;
+ *reply++ = measure.peak;
+ *reply = measure.rms;
return OK;
}
diff --git a/media/libeffects/visualizer/aidl/VisualizerContext.cpp b/media/libeffects/visualizer/aidl/VisualizerContext.cpp
index 5d0d08d..5d2bb3a 100644
--- a/media/libeffects/visualizer/aidl/VisualizerContext.cpp
+++ b/media/libeffects/visualizer/aidl/VisualizerContext.cpp
@@ -61,6 +61,7 @@
#endif
mChannelCount = channelCount;
mCommon = common;
+ std::fill(mCaptureBuf.begin(), mCaptureBuf.end(), 0x80);
return RetCode::SUCCESS;
}
@@ -84,7 +85,7 @@
void VisualizerContext::reset() {
std::lock_guard lg(mMutex);
- std::fill_n(mCaptureBuf.begin(), kMaxCaptureBufSize, 0x80);
+ std::fill(mCaptureBuf.begin(), mCaptureBuf.end(), 0x80);
}
RetCode VisualizerContext::setCaptureSamples(int samples) {
@@ -190,13 +191,12 @@
}
std::vector<uint8_t> VisualizerContext::capture() {
- std::vector<uint8_t> result;
std::lock_guard lg(mMutex);
+ uint32_t captureSamples = mCaptureSamples;
+ std::vector<uint8_t> result(captureSamples, 0x80);
// cts android.media.audio.cts.VisualizerTest expecting silence data when effect not running
// RETURN_VALUE_IF(mState != State::ACTIVE, result, "illegalState");
if (mState != State::ACTIVE) {
- result.resize(mCaptureSamples);
- memset(result.data(), 0x80, mCaptureSamples);
return result;
}
@@ -214,7 +214,7 @@
if (latencyMs < 0) {
latencyMs = 0;
}
- uint32_t deltaSamples = mCaptureSamples + mCommon.input.base.sampleRate * latencyMs / 1000;
+ uint32_t deltaSamples = captureSamples + mCommon.input.base.sampleRate * latencyMs / 1000;
// large sample rate, latency, or capture size, could cause overflow.
// do not offset more than the size of buffer.
@@ -224,21 +224,21 @@
}
int32_t capturePoint;
- //capturePoint = (int32_t)mCaptureIdx - deltaSamples;
__builtin_sub_overflow((int32_t) mCaptureIdx, deltaSamples, &capturePoint);
// a negative capturePoint means we wrap the buffer.
if (capturePoint < 0) {
uint32_t size = -capturePoint;
- if (size > mCaptureSamples) {
- size = mCaptureSamples;
+ if (size > captureSamples) {
+ size = captureSamples;
}
- result.insert(result.end(), &mCaptureBuf[kMaxCaptureBufSize + capturePoint],
- &mCaptureBuf[kMaxCaptureBufSize + capturePoint + size]);
- mCaptureSamples -= size;
+ std::copy(std::begin(mCaptureBuf) + kMaxCaptureBufSize - size,
+ std::begin(mCaptureBuf) + kMaxCaptureBufSize, result.begin());
+ captureSamples -= size;
capturePoint = 0;
}
- result.insert(result.end(), &mCaptureBuf[capturePoint],
- &mCaptureBuf[capturePoint + mCaptureSamples]);
+ std::copy(std::begin(mCaptureBuf) + capturePoint,
+ std::begin(mCaptureBuf) + capturePoint + captureSamples,
+ result.begin() + mCaptureSamples - captureSamples);
mLastCaptureIdx = mCaptureIdx;
return result;
}
@@ -256,16 +256,15 @@
// find the peak and RMS squared for the new buffer
float rmsSqAcc = 0;
float maxSample = 0.f;
- for (size_t inIdx = 0; inIdx < (unsigned)samples; ++inIdx) {
+ for (size_t inIdx = 0; inIdx < (unsigned) samples; ++inIdx) {
maxSample = fmax(maxSample, fabs(in[inIdx]));
rmsSqAcc += in[inIdx] * in[inIdx];
}
maxSample *= 1 << 15; // scale to int16_t, with exactly 1 << 15 representing positive num.
rmsSqAcc *= 1 << 30; // scale to int16_t * 2
- mPastMeasurements[mMeasurementBufferIdx] = {
- .mPeakU16 = (uint16_t)maxSample,
- .mRmsSquared = rmsSqAcc / samples,
- .mIsValid = true };
+ mPastMeasurements[mMeasurementBufferIdx] = {.mIsValid = true,
+ .mPeakU16 = (uint16_t)maxSample,
+ .mRmsSquared = rmsSqAcc / samples};
if (++mMeasurementBufferIdx >= mMeasurementWindowSizeInBuffers) {
mMeasurementBufferIdx = 0;
}
diff --git a/media/libmediaplayerservice/fuzzer/Android.bp b/media/libmediaplayerservice/fuzzer/Android.bp
index c3d6c89..b511372 100644
--- a/media/libmediaplayerservice/fuzzer/Android.bp
+++ b/media/libmediaplayerservice/fuzzer/Android.bp
@@ -174,6 +174,7 @@
"libnetd_client",
"libpowermanager",
"libstagefright_httplive",
+ "libaudiohal@7.0",
],
}
diff --git a/media/libstagefright/VideoRenderQualityTracker.cpp b/media/libstagefright/VideoRenderQualityTracker.cpp
index 3bd236a..eb9ac0f 100644
--- a/media/libstagefright/VideoRenderQualityTracker.cpp
+++ b/media/libstagefright/VideoRenderQualityTracker.cpp
@@ -28,6 +28,7 @@
#include <cmath>
#include <stdio.h>
#include <sys/time.h>
+#include <sys/wait.h>
#include <android-base/macros.h>
#include <android-base/parsebool.h>
@@ -161,7 +162,6 @@
getFlag(traceTriggerEnabled, "trace_trigger_enabled");
getFlag(traceTriggerThrottleMs, "trace_trigger_throttle_ms");
getFlag(traceMinFreezeDurationMs, "trace_minimum_freeze_duration_ms");
- getFlag(traceMaxFreezeDurationMs, "trace_maximum_freeze_duration_ms");
#undef getFlag
return c;
}
@@ -208,7 +208,6 @@
"ro.build.type", "user") != "user"; // Enabled for non-user builds for debugging.
traceTriggerThrottleMs = 5 * 60 * 1000; // 5 mins.
traceMinFreezeDurationMs = 400;
- traceMaxFreezeDurationMs = 1500;
}
VideoRenderQualityTracker::VideoRenderQualityTracker()
@@ -300,15 +299,7 @@
int64_t actualRenderTimeUs = actualRenderTimeNs / 1000;
if (mLastRenderTimeUs != -1) {
- int64_t frameRenderDurationMs = (actualRenderTimeUs - mLastRenderTimeUs) / 1000;
- mRenderDurationMs += frameRenderDurationMs;
- if (mConfiguration.traceTriggerEnabled
- // Threshold for visible video freeze.
- && frameRenderDurationMs >= mConfiguration.traceMinFreezeDurationMs
- // Threshold for removing long render durations which could be video pause.
- && frameRenderDurationMs < mConfiguration.traceMaxFreezeDurationMs) {
- triggerTraceWithThrottle(mTraceTriggerFn, mConfiguration, actualRenderTimeUs);
- }
+ mRenderDurationMs += (actualRenderTimeUs - mLastRenderTimeUs) / 1000;
}
// Now that a frame has been rendered, the previously skipped frames can be processed as skipped
@@ -549,7 +540,7 @@
}
if (!isLikelyCatchingUpAfterPause) {
processFreeze(actualRenderTimeUs, mLastRenderTimeUs, mLastFreezeEndTimeUs, mFreezeEvent,
- mMetrics, mConfiguration);
+ mMetrics, mConfiguration, mTraceTriggerFn);
mLastFreezeEndTimeUs = actualRenderTimeUs;
}
}
@@ -575,8 +566,8 @@
void VideoRenderQualityTracker::processFreeze(int64_t actualRenderTimeUs, int64_t lastRenderTimeUs,
int64_t lastFreezeEndTimeUs, FreezeEvent &e,
- VideoRenderQualityMetrics &m,
- const Configuration &c) {
+ VideoRenderQualityMetrics &m, const Configuration &c,
+ const TraceTriggerFn traceTriggerFn) {
int32_t durationMs = int32_t((actualRenderTimeUs - lastRenderTimeUs) / 1000);
m.freezeDurationMsHistogram.insert(durationMs);
int32_t distanceMs = -1;
@@ -612,6 +603,11 @@
e.details.distanceMs.push_back(distanceMs); // -1 for first detail in the first event
}
}
+
+ if (c.traceTriggerEnabled && durationMs >= c.traceMinFreezeDurationMs) {
+ ALOGI("Video freezed %lld ms", (long long) durationMs);
+ triggerTraceWithThrottle(traceTriggerFn, c, actualRenderTimeUs);
+ }
}
void VideoRenderQualityTracker::maybeCaptureFreezeEvent(int64_t actualRenderTimeUs,
@@ -818,36 +814,48 @@
static int64_t lastTriggerUs = -1;
static Mutex updateLastTriggerLock;
- Mutex::Autolock autoLock(updateLastTriggerLock);
- if (lastTriggerUs != -1) {
- int32_t sinceLastTriggerMs = int32_t((triggerTimeUs - lastTriggerUs) / 1000);
- // Throttle the trace trigger calls to reduce continuous PID fork calls in a short time
- // to impact device performance, and reduce spamming trace reports.
- if (sinceLastTriggerMs < c.traceTriggerThrottleMs) {
- ALOGI("Not triggering trace - not enough time since last trigger");
- return;
+ {
+ Mutex::Autolock autoLock(updateLastTriggerLock);
+ if (lastTriggerUs != -1) {
+ int32_t sinceLastTriggerMs = int32_t((triggerTimeUs - lastTriggerUs) / 1000);
+ // Throttle the trace trigger calls to reduce continuous PID fork calls in a short time
+ // to impact device performance, and reduce spamming trace reports.
+ if (sinceLastTriggerMs < c.traceTriggerThrottleMs) {
+ ALOGI("Not triggering trace - not enough time since last trigger");
+ return;
+ }
}
+ lastTriggerUs = triggerTimeUs;
}
- lastTriggerUs = triggerTimeUs;
+
(*traceTriggerFn)();
}
void VideoRenderQualityTracker::triggerTrace() {
// Trigger perfetto to stop always-on-tracing (AOT) to collect trace into a file for video
// freeze event, the collected trace categories are configured by AOT.
- const char* args[] = {"/system/bin/trigger_perfetto", "com.android.codec-video-freeze", NULL};
+ static const char* args[] = {"/system/bin/trigger_perfetto",
+ "com.android.codec-video-freeze", NULL};
+
pid_t pid = fork();
if (pid < 0) {
ALOGI("Failed to fork for triggering trace");
- return;
- }
- if (pid == 0) {
- // child process.
+ } else if (pid == 0) {
+ // Child process.
+ ALOGI("Trigger trace %s", args[1]);
execvp(args[0], const_cast<char**>(args));
ALOGW("Failed to trigger trace %s", args[1]);
_exit(1);
+ } else {
+ // Parent process.
+ int status;
+ // Wait for the child process (pid) gets terminated, and allow the system to release
+ // the resource associated with the child. Or the child process will remain in a
+ // zombie state and get killed by llkd to cause foreground app crash.
+ if (waitpid(pid, &status, 0) < 0) {
+ ALOGW("Failed to waitpid for triggering trace");
+ }
}
- ALOGI("Triggered trace %s", args[1]);
}
} // namespace android
diff --git a/media/libstagefright/include/media/stagefright/VideoRenderQualityTracker.h b/media/libstagefright/include/media/stagefright/VideoRenderQualityTracker.h
index d58dfad..7139deb 100644
--- a/media/libstagefright/include/media/stagefright/VideoRenderQualityTracker.h
+++ b/media/libstagefright/include/media/stagefright/VideoRenderQualityTracker.h
@@ -220,11 +220,6 @@
//
// The minimum frame render duration to recognize video freeze event to collect trace.
int32_t traceMinFreezeDurationMs;
- //
- // The maximum frame render duration to recognize video freeze event. A frame render
- // duration that is larger than the max duration would not trigger trace collection for
- // video freeze because it's highly possible a video pause.
- int32_t traceMaxFreezeDurationMs;
};
struct FreezeEvent {
@@ -380,7 +375,8 @@
// Process a frame freeze.
static void processFreeze(int64_t actualRenderTimeUs, int64_t lastRenderTimeUs,
int64_t lastFreezeEndTimeUs, FreezeEvent &e,
- VideoRenderQualityMetrics &m, const Configuration &c);
+ VideoRenderQualityMetrics &m, const Configuration &c,
+ const TraceTriggerFn traceTriggerFn);
// Retrieve a freeze event if an event just finished.
static void maybeCaptureFreezeEvent(int64_t actualRenderTimeUs, int64_t lastFreezeEndTimeUs,
diff --git a/media/libstagefright/tests/VideoRenderQualityTracker_test.cpp b/media/libstagefright/tests/VideoRenderQualityTracker_test.cpp
index 9b6315c..16f8294 100644
--- a/media/libstagefright/tests/VideoRenderQualityTracker_test.cpp
+++ b/media/libstagefright/tests/VideoRenderQualityTracker_test.cpp
@@ -156,7 +156,6 @@
EXPECT_EQ(c.traceTriggerEnabled, d.traceTriggerEnabled);
EXPECT_EQ(c.traceTriggerThrottleMs, d.traceTriggerThrottleMs);
EXPECT_EQ(c.traceMinFreezeDurationMs, d.traceMinFreezeDurationMs);
- EXPECT_EQ(c.traceMaxFreezeDurationMs, d.traceMaxFreezeDurationMs);
}
TEST_F(VideoRenderQualityTrackerTest, getFromServerConfigurableFlags_withEmpty) {
@@ -188,7 +187,6 @@
EXPECT_EQ(c.traceTriggerEnabled, d.traceTriggerEnabled);
EXPECT_EQ(c.traceTriggerThrottleMs, d.traceTriggerThrottleMs);
EXPECT_EQ(c.traceMinFreezeDurationMs, d.traceMinFreezeDurationMs);
- EXPECT_EQ(c.traceMaxFreezeDurationMs, d.traceMaxFreezeDurationMs);
}
TEST_F(VideoRenderQualityTrackerTest, getFromServerConfigurableFlags_withInvalid) {
@@ -220,7 +218,6 @@
EXPECT_EQ(c.traceTriggerEnabled, d.traceTriggerEnabled);
EXPECT_EQ(c.traceTriggerThrottleMs, d.traceTriggerThrottleMs);
EXPECT_EQ(c.traceMinFreezeDurationMs, d.traceMinFreezeDurationMs);
- EXPECT_EQ(c.traceMaxFreezeDurationMs, d.traceMaxFreezeDurationMs);
}
TEST_F(VideoRenderQualityTrackerTest, getFromServerConfigurableFlags_withAlmostValid) {
@@ -297,7 +294,6 @@
EXPECT_EQ(c.traceTriggerEnabled, d.traceTriggerEnabled);
EXPECT_EQ(c.traceTriggerThrottleMs, d.traceTriggerThrottleMs);
EXPECT_EQ(c.traceMinFreezeDurationMs, d.traceMinFreezeDurationMs);
- EXPECT_EQ(c.traceMaxFreezeDurationMs, d.traceMaxFreezeDurationMs);
}
TEST_F(VideoRenderQualityTrackerTest, getFromServerConfigurableFlags_withValid) {
@@ -412,7 +408,6 @@
EXPECT_EQ(c.traceTriggerEnabled, true);
EXPECT_EQ(c.traceTriggerThrottleMs, 50000);
EXPECT_EQ(c.traceMinFreezeDurationMs, 1000);
- EXPECT_EQ(c.traceMaxFreezeDurationMs, 5000);
}
TEST_F(VideoRenderQualityTrackerTest, countsReleasedFrames) {
@@ -1126,53 +1121,34 @@
c.enabled = true;
c.traceTriggerEnabled = true; // The trigger is enabled, so traces should be triggered.
// The value of traceTriggerThrottleMs must be larger than traceMinFreezeDurationMs. Otherwise,
- // the throttle does work.
+ // the throttle does not work.
c.traceTriggerThrottleMs = 200;
- c.traceMinFreezeDurationMs = 40;
- int32_t freeze = c.traceMinFreezeDurationMs;
+ c.traceMinFreezeDurationMs = 4 * 20; // 4 frames.
Helper h(20, c);
- // Freeze triggers separated by 80ms which is less than the threshold.
- h.render({
- freeze, // Freeze duration does not check trace trigger.
- 20, // Trace triggered.
- 20, // Throttle time: 20/200ms
- 20, // Throttle time: 40/200ms
- freeze, // Throttle time: 80/200ms
- 20, // Throttle time: 100/200ms (Trace not triggered)
- });
+ // Freeze triggers separated by 100ms which is less than the threshold.
+ h.render(1); // Video start.
+ h.drop(3); // Freeze.
+ h.render(1); // Trace triggered.
+ h.render(1); // Throttle time: 20/200ms
+ h.drop(3); // Throttle time: 80/200ms
+ h.render(1); // Throttle time: 100/200ms (Trace not triggered)
EXPECT_EQ(h.getTraceTriggeredCount(), 1);
// Next freeze trigger is separated by 200ms which breaks the throttle threshold.
- h.render({
- 20, // Throttle time: 120/200ms
- 20, // Throttle time: 140/200ms
- 20, // Throttle time: 160/200ms
- freeze, // Throttle time: 200/200ms
- 20, // Trace triggered.
- });
+ h.render(1); // Throttle time: 120/200ms
+ h.drop(3); // Throttle time: 180/200ms
+ h.render(1); // Throttle time: 200/200ms (Trace triggered)
EXPECT_EQ(h.getTraceTriggeredCount(), 2);
- // Next freeze trigger is separated by 80ms which is less than the threshold.
- h.render({
- 20, // Throttle time: 20/200ms
- 20, // Throttle time: 40/200ms
- freeze, // Throttle time: 80/200ms
- 20, // Throttle time: 100/200ms (Trace not triggered)
- });
+ // Next freeze trigger is separated by 100ms which is less than the threshold.
+ h.render(1); // Throttle time: 20/200ms
+ h.drop(3); // Throttle time: 80/200ms
+ h.render(1); // Throttle time: 100/200ms (Trace not triggered)
EXPECT_EQ(h.getTraceTriggeredCount(), 2);
-}
-
-TEST_F(VideoRenderQualityTrackerTest, freezeForTraceDuration_triggersTrace) {
- Configuration c;
- c.enabled = true;
- c.traceTriggerEnabled = true; // The trigger is enabled, so traces should be triggered.
- c.traceTriggerThrottleMs = 0; // Disable throttle in the test case.
- int32_t freeze1 = c.traceMinFreezeDurationMs;
- int32_t freeze2 = c.traceMaxFreezeDurationMs - 1;
- int32_t couldBeAPause = c.traceMaxFreezeDurationMs + 1;
-
- Helper h(20, c);
- h.render({freeze1, 20, freeze2, 20, couldBeAPause, 20});
-
+ // Freeze duration is less than traceMinFreezeDurationMs and throttle ends.
+ h.render(1); // Throttle time: 120/200ms
+ h.render(1); // Throttle time: 140/200ms
+ h.drop(2); // Throttle time: 180/200ms
+ h.render(1); // Throttle time: 200/200ms (Trace not triggered, freeze duration = 60ms)
EXPECT_EQ(h.getTraceTriggeredCount(), 2);
}
@@ -1182,12 +1158,14 @@
c.enabled = true;
c.traceTriggerEnabled = false; // The trigger is disabled, so no traces should be triggered.
c.traceTriggerThrottleMs = 0; // Disable throttle in the test case.
- int32_t freeze1 = c.traceMinFreezeDurationMs;
- int32_t freeze2 = c.traceMaxFreezeDurationMs - 1;
- int32_t couldBeAPause = c.traceMaxFreezeDurationMs + 1;
+ c.traceMinFreezeDurationMs = 4 * 20; // 4 frames.
Helper h(20, c);
- h.render({freeze1, 20, freeze2, 20, couldBeAPause, 20});
+ h.render(1);
+ h.drop(3);
+ h.render(1); // Render duration is 80 ms.
+ h.drop(4);
+ h.render(1); // Render duration is 100 ms.
EXPECT_EQ(h.getTraceTriggeredCount(), 0);
}