summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/media/stagefright/ACodec.h1
-rw-r--r--include/media/stagefright/foundation/ADebug.h20
-rw-r--r--media/libstagefright/ACodec.cpp52
-rw-r--r--media/libstagefright/Android.mk2
-rw-r--r--media/libstagefright/foundation/ADebug.cpp39
5 files changed, 110 insertions, 4 deletions
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index 0a54df9..b8327a3 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -216,6 +216,7 @@ private:
int32_t mChannelMask;
unsigned mDequeueCounter;
bool mStoreMetaDataInOutputBuffers;
+ bool mLegacyAdaptiveExperiment;
int32_t mMetaDataBuffersToSubmit;
size_t mNumUndequeuedBuffers;
diff --git a/include/media/stagefright/foundation/ADebug.h b/include/media/stagefright/foundation/ADebug.h
index 1d0e2cb..a97dd9b 100644
--- a/include/media/stagefright/foundation/ADebug.h
+++ b/include/media/stagefright/foundation/ADebug.h
@@ -108,6 +108,26 @@ struct ADebug {
// remove redundant segments of a codec name, and return a newly allocated
// string suitable for debugging
static char *GetDebugName(const char *name);
+
+ inline static bool isExperimentEnabled(
+ const char *name __unused /* nonnull */, bool allow __unused = true) {
+#ifdef ENABLE_STAGEFRIGHT_EXPERIMENTS
+ if (!strcmp(name, "legacy-adaptive")) {
+ return getExperimentFlag(allow, name, 2, 1); // every other day
+ } else if (!strcmp(name, "legacy-setsurface")) {
+ return getExperimentFlag(allow, name, 3, 1); // every third day
+ } else {
+ ALOGE("unknown experiment '%s' (disabled)", name);
+ }
+#endif
+ return false;
+ }
+
+private:
+ // pass in allow, so we can print in the log if the experiment is disabled
+ static bool getExperimentFlag(
+ bool allow, const char *name, uint64_t modulo, uint64_t limit,
+ uint64_t plus = 0, uint64_t timeDivisor = 24 * 60 * 60 /* 1 day */);
};
} // namespace android
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 006f07d..0843ad1 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -422,6 +422,7 @@ ACodec::ACodec()
mChannelMask(0),
mDequeueCounter(0),
mStoreMetaDataInOutputBuffers(false),
+ mLegacyAdaptiveExperiment(false),
mMetaDataBuffersToSubmit(0),
mRepeatFrameDelayUs(-1ll),
mMaxPtsGapUs(-1ll),
@@ -619,6 +620,7 @@ status_t ACodec::handleSetSurface(const sp<Surface> &surface) {
const BufferInfo &info = buffers[i];
// skip undequeued buffers for meta data mode
if (mStoreMetaDataInOutputBuffers
+ && !mLegacyAdaptiveExperiment
&& info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
ALOGV("skipping buffer %p", info.mGraphicBuffer->getNativeBuffer());
continue;
@@ -635,7 +637,7 @@ status_t ACodec::handleSetSurface(const sp<Surface> &surface) {
}
// cancel undequeued buffers to new surface
- if (!mStoreMetaDataInOutputBuffers) {
+ if (!mStoreMetaDataInOutputBuffers || mLegacyAdaptiveExperiment) {
for (size_t i = 0; i < buffers.size(); ++i) {
const BufferInfo &info = buffers[i];
if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
@@ -970,6 +972,44 @@ status_t ACodec::allocateOutputMetaDataBuffers() {
return err;
mNumUndequeuedBuffers = minUndequeuedBuffers;
+ if (mLegacyAdaptiveExperiment) {
+ // preallocate buffers
+ static_cast<Surface *>(mNativeWindow.get())
+ ->getIGraphicBufferProducer()->allowAllocation(true);
+
+ ALOGV("[%s] Allocating %u buffers from a native window of size %u on "
+ "output port",
+ mComponentName.c_str(), bufferCount, bufferSize);
+
+ // Dequeue buffers then cancel them all
+ for (OMX_U32 i = 0; i < bufferCount; i++) {
+ ANativeWindowBuffer *buf;
+ err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &buf);
+ if (err != 0) {
+ ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
+ break;
+ }
+
+ sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false));
+ BufferInfo info;
+ info.mStatus = BufferInfo::OWNED_BY_US;
+ info.mGraphicBuffer = graphicBuffer;
+ mBuffers[kPortIndexOutput].push(info);
+ }
+
+ for (OMX_U32 i = 0; i < mBuffers[kPortIndexOutput].size(); i++) {
+ BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
+ status_t error = cancelBufferToNativeWindow(info);
+ if (err == OK) {
+ err = error;
+ }
+ }
+
+ mBuffers[kPortIndexOutput].clear();
+ static_cast<Surface*>(mNativeWindow.get())
+ ->getIGraphicBufferProducer()->allowAllocation(false);
+ }
+
ALOGV("[%s] Allocating %u meta buffers on output port",
mComponentName.c_str(), bufferCount);
@@ -1085,7 +1125,7 @@ ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() {
// same is possible in meta mode, in which case, it will be treated
// as a normal buffer, which is not desirable.
// TODO: fix this.
- if (!stale && !mStoreMetaDataInOutputBuffers) {
+ if (!stale && (!mStoreMetaDataInOutputBuffers || mLegacyAdaptiveExperiment)) {
ALOGI("dequeued unrecognized (stale) buffer %p. discarding", buf);
stale = true;
}
@@ -1418,6 +1458,7 @@ status_t ACodec::configureCodec(
bool haveNativeWindow = msg->findObject("native-window", &obj)
&& obj != NULL && video && !encoder;
mStoreMetaDataInOutputBuffers = false;
+ mLegacyAdaptiveExperiment = false;
if (video && !encoder) {
inputFormat->setInt32("adaptive-playback", false);
@@ -1555,6 +1596,9 @@ status_t ACodec::configureCodec(
ALOGV("[%s] storeMetaDataInBuffers succeeded",
mComponentName.c_str());
mStoreMetaDataInOutputBuffers = true;
+ mLegacyAdaptiveExperiment = ADebug::isExperimentEnabled(
+ "legacy-adaptive", !msg->contains("no-experiments"));
+
inputFormat->setInt32("adaptive-playback", true);
}
@@ -4169,7 +4213,9 @@ bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) {
sp<RefBase> obj;
CHECK(msg->findObject("surface", &obj));
- status_t err = mCodec->handleSetSurface(static_cast<Surface *>(obj.get()));
+ status_t err =
+ ADebug::isExperimentEnabled("legacy-setsurface") ? BAD_VALUE :
+ mCodec->handleSetSurface(static_cast<Surface *>(obj.get()));
sp<AMessage> response = new AMessage;
response->setInt32("err", err);
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index fa17b2e..6010558 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -124,7 +124,7 @@ LOCAL_SHARED_LIBRARIES += \
libdl \
libRScpp \
-LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
+LOCAL_CFLAGS += -Wno-multichar -Werror -Wall -DENABLE_STAGEFRIGHT_EXPERIMENTS
LOCAL_CLANG := true
LOCAL_MODULE:= libstagefright
diff --git a/media/libstagefright/foundation/ADebug.cpp b/media/libstagefright/foundation/ADebug.cpp
index ec4a960..0d1cea4 100644
--- a/media/libstagefright/foundation/ADebug.cpp
+++ b/media/libstagefright/foundation/ADebug.cpp
@@ -19,6 +19,7 @@
#include <ctype.h>
#define LOG_TAG "ADebug"
+#include <cutils/atomic.h>
#include <utils/Log.h>
#include <utils/misc.h>
@@ -113,5 +114,43 @@ char *ADebug::GetDebugName(const char *name) {
return debugName;
}
+//static
+bool ADebug::getExperimentFlag(
+ bool allow, const char *name, uint64_t modulo,
+ uint64_t limit, uint64_t plus, uint64_t timeDivisor) {
+ static volatile int32_t haveSerial = 0;
+ static uint64_t serialNum;
+ if (!android_atomic_acquire_load(&haveSerial)) {
+ // calculate initial counter value based on serial number
+ static char serial[PROPERTY_VALUE_MAX];
+ property_get("ro.serialno", serial, "0");
+ uint64_t num = 0; // it is okay for this number to overflow
+ for (size_t i = 0; i < NELEM(serial) && serial[i] != '\0'; ++i) {
+ const char &c = serial[i];
+ // try to use most letters of serialno
+ if (isdigit(c)) {
+ num = num * 10 + (c - '0');
+ } else if (islower(c)) {
+ num = num * 26 + (c - 'a');
+ } else if (isupper(c)) {
+ num = num * 26 + (c - 'A');
+ } else {
+ num = num * 256 + c;
+ }
+ }
+ ALOGI("got serial");
+ serialNum = num;
+ android_atomic_release_store(1, &haveSerial);
+ }
+ ALOGI("serial: %llu, time: %llu", (long long)serialNum, (long long)time(NULL));
+ // MINOR: use modulo for counter and time, so that their sum does not
+ // roll over, and mess up the correlation between related experiments.
+ // e.g. keep (a mod 2N) = 0 impl (a mod N) = 0
+ time_t counter = (time(NULL) / timeDivisor) % modulo + plus + serialNum % modulo;
+ bool enable = allow && (counter % modulo < limit);
+ ALOGI("experiment '%s': %s", name, enable ? "ENABLED" : "disabled");
+ return enable;
+}
+
} // namespace android