diff options
-rw-r--r-- | include/media/stagefright/ACodec.h | 1 | ||||
-rw-r--r-- | include/media/stagefright/foundation/ADebug.h | 20 | ||||
-rw-r--r-- | media/libstagefright/ACodec.cpp | 52 | ||||
-rw-r--r-- | media/libstagefright/Android.mk | 2 | ||||
-rw-r--r-- | media/libstagefright/foundation/ADebug.cpp | 39 |
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 |