diff options
Diffstat (limited to 'media/libstagefright/foundation')
-rw-r--r-- | media/libstagefright/foundation/ABitReader.cpp | 68 | ||||
-rw-r--r-- | media/libstagefright/foundation/ABuffer.cpp | 31 | ||||
-rw-r--r-- | media/libstagefright/foundation/AHierarchicalStateMachine.cpp | 2 | ||||
-rw-r--r-- | media/libstagefright/foundation/ALooper.cpp | 8 | ||||
-rw-r--r-- | media/libstagefright/foundation/ALooperRoster.cpp | 67 | ||||
-rw-r--r-- | media/libstagefright/foundation/AMessage.cpp | 122 | ||||
-rw-r--r-- | media/libstagefright/foundation/ANetworkSession.cpp | 6 | ||||
-rw-r--r-- | media/libstagefright/foundation/AString.cpp | 88 | ||||
-rw-r--r-- | media/libstagefright/foundation/Android.mk | 2 | ||||
-rw-r--r-- | media/libstagefright/foundation/base64.cpp | 6 |
10 files changed, 311 insertions, 89 deletions
diff --git a/media/libstagefright/foundation/ABitReader.cpp b/media/libstagefright/foundation/ABitReader.cpp index 5499c32..beb5cc0 100644 --- a/media/libstagefright/foundation/ABitReader.cpp +++ b/media/libstagefright/foundation/ABitReader.cpp @@ -27,6 +27,9 @@ ABitReader::ABitReader(const uint8_t *data, size_t size) mNumBitsLeft(0) { } +ABitReader::~ABitReader() { +} + void ABitReader::fillReservoir() { CHECK_GT(mSize, 0u); @@ -99,4 +102,69 @@ const uint8_t *ABitReader::data() const { return mData - (mNumBitsLeft + 7) / 8; } +NALBitReader::NALBitReader(const uint8_t *data, size_t size) + : ABitReader(data, size), + mNumZeros(0) { +} + +bool NALBitReader::atLeastNumBitsLeft(size_t n) const { + // check against raw size and reservoir bits first + size_t numBits = numBitsLeft(); + if (n > numBits) { + return false; + } + + ssize_t numBitsRemaining = n - mNumBitsLeft; + + size_t size = mSize; + const uint8_t *data = mData; + int32_t numZeros = mNumZeros; + while (size > 0 && numBitsRemaining > 0) { + bool isEmulationPreventionByte = (numZeros >= 2 && *data == 3); + + if (*data == 0) { + ++numZeros; + } else { + numZeros = 0; + } + + if (!isEmulationPreventionByte) { + numBitsRemaining -= 8; + } + + ++data; + --size; + } + + return (numBitsRemaining <= 0); +} + +void NALBitReader::fillReservoir() { + CHECK_GT(mSize, 0u); + + mReservoir = 0; + size_t i = 0; + while (mSize > 0 && i < 4) { + bool isEmulationPreventionByte = (mNumZeros >= 2 && *mData == 3); + + if (*mData == 0) { + ++mNumZeros; + } else { + mNumZeros = 0; + } + + // skip emulation_prevention_three_byte + if (!isEmulationPreventionByte) { + mReservoir = (mReservoir << 8) | *mData; + ++i; + } + + ++mData; + --mSize; + } + + mNumBitsLeft = 8 * i; + mReservoir <<= 32 - mNumBitsLeft; +} + } // namespace android diff --git a/media/libstagefright/foundation/ABuffer.cpp b/media/libstagefright/foundation/ABuffer.cpp index 5f5c977..4913fd4 100644 --- a/media/libstagefright/foundation/ABuffer.cpp +++ b/media/libstagefright/foundation/ABuffer.cpp @@ -19,11 +19,13 @@ #include "ADebug.h" #include "ALooper.h" #include "AMessage.h" +#include "MediaBufferBase.h" namespace android { ABuffer::ABuffer(size_t capacity) - : mRangeOffset(0), + : mMediaBufferBase(NULL), + mRangeOffset(0), mInt32Data(0), mOwnsData(true) { mData = malloc(capacity); @@ -37,7 +39,8 @@ ABuffer::ABuffer(size_t capacity) } ABuffer::ABuffer(void *data, size_t capacity) - : mData(data), + : mMediaBufferBase(NULL), + mData(data), mCapacity(capacity), mRangeOffset(0), mRangeLength(capacity), @@ -45,6 +48,14 @@ ABuffer::ABuffer(void *data, size_t capacity) mOwnsData(false) { } +// static +sp<ABuffer> ABuffer::CreateAsCopy(const void *data, size_t capacity) +{ + sp<ABuffer> res = new ABuffer(capacity); + memcpy(res->data(), data, capacity); + return res; +} + ABuffer::~ABuffer() { if (mOwnsData) { if (mData != NULL) { @@ -56,6 +67,8 @@ ABuffer::~ABuffer() { if (mFarewell != NULL) { mFarewell->post(); } + + setMediaBufferBase(NULL); } void ABuffer::setRange(size_t offset, size_t size) { @@ -77,5 +90,19 @@ sp<AMessage> ABuffer::meta() { return mMeta; } +MediaBufferBase *ABuffer::getMediaBufferBase() { + if (mMediaBufferBase != NULL) { + mMediaBufferBase->add_ref(); + } + return mMediaBufferBase; +} + +void ABuffer::setMediaBufferBase(MediaBufferBase *mediaBuffer) { + if (mMediaBufferBase != NULL) { + mMediaBufferBase->release(); + } + mMediaBufferBase = mediaBuffer; +} + } // namespace android diff --git a/media/libstagefright/foundation/AHierarchicalStateMachine.cpp b/media/libstagefright/foundation/AHierarchicalStateMachine.cpp index f7a00d8..5f7c70d 100644 --- a/media/libstagefright/foundation/AHierarchicalStateMachine.cpp +++ b/media/libstagefright/foundation/AHierarchicalStateMachine.cpp @@ -51,7 +51,7 @@ AHierarchicalStateMachine::AHierarchicalStateMachine() { AHierarchicalStateMachine::~AHierarchicalStateMachine() { } -void AHierarchicalStateMachine::onMessageReceived(const sp<AMessage> &msg) { +void AHierarchicalStateMachine::handleMessage(const sp<AMessage> &msg) { sp<AState> save = mState; sp<AState> cur = mState; diff --git a/media/libstagefright/foundation/ALooper.cpp b/media/libstagefright/foundation/ALooper.cpp index ebf9d8d..88b1c92 100644 --- a/media/libstagefright/foundation/ALooper.cpp +++ b/media/libstagefright/foundation/ALooper.cpp @@ -68,14 +68,14 @@ int64_t ALooper::GetNowUs() { ALooper::ALooper() : mRunningLocally(false) { + // clean up stale AHandlers. Doing it here instead of in the destructor avoids + // the side effect of objects being deleted from the unregister function recursively. + gLooperRoster.unregisterStaleHandlers(); } ALooper::~ALooper() { stop(); - - // Since this looper is "dead" (or as good as dead by now), - // have ALooperRoster unregister any handlers still registered for it. - gLooperRoster.unregisterStaleHandlers(); + // stale AHandlers are now cleaned up in the constructor of the next ALooper to come along } void ALooper::setName(const char *name) { diff --git a/media/libstagefright/foundation/ALooperRoster.cpp b/media/libstagefright/foundation/ALooperRoster.cpp index 0c181ff..e0dc768 100644 --- a/media/libstagefright/foundation/ALooperRoster.cpp +++ b/media/libstagefright/foundation/ALooperRoster.cpp @@ -72,50 +72,40 @@ void ALooperRoster::unregisterHandler(ALooper::handler_id handlerID) { } void ALooperRoster::unregisterStaleHandlers() { - Mutex::Autolock autoLock(mLock); - for (size_t i = mHandlers.size(); i-- > 0;) { - const HandlerInfo &info = mHandlers.valueAt(i); + Vector<sp<ALooper> > activeLoopers; + { + Mutex::Autolock autoLock(mLock); - sp<ALooper> looper = info.mLooper.promote(); - if (looper == NULL) { - ALOGV("Unregistering stale handler %d", mHandlers.keyAt(i)); - mHandlers.removeItemsAt(i); + for (size_t i = mHandlers.size(); i-- > 0;) { + const HandlerInfo &info = mHandlers.valueAt(i); + + sp<ALooper> looper = info.mLooper.promote(); + if (looper == NULL) { + ALOGV("Unregistering stale handler %d", mHandlers.keyAt(i)); + mHandlers.removeItemsAt(i); + } else { + // At this point 'looper' might be the only sp<> keeping + // the object alive. To prevent it from going out of scope + // and having ~ALooper call this method again recursively + // and then deadlocking because of the Autolock above, add + // it to a Vector which will go out of scope after the lock + // has been released. + activeLoopers.add(looper); + } } } } status_t ALooperRoster::postMessage( const sp<AMessage> &msg, int64_t delayUs) { - Mutex::Autolock autoLock(mLock); - return postMessage_l(msg, delayUs); -} - -status_t ALooperRoster::postMessage_l( - const sp<AMessage> &msg, int64_t delayUs) { - ssize_t index = mHandlers.indexOfKey(msg->target()); - if (index < 0) { - ALOGW("failed to post message '%s'. Target handler not registered.", - msg->debugString().c_str()); - return -ENOENT; - } - - const HandlerInfo &info = mHandlers.valueAt(index); - - sp<ALooper> looper = info.mLooper.promote(); + sp<ALooper> looper = findLooper(msg->target()); if (looper == NULL) { - ALOGW("failed to post message. " - "Target handler %d still registered, but object gone.", - msg->target()); - - mHandlers.removeItemsAt(index); return -ENOENT; } - looper->post(msg, delayUs); - return OK; } @@ -169,18 +159,23 @@ sp<ALooper> ALooperRoster::findLooper(ALooper::handler_id handlerID) { status_t ALooperRoster::postAndAwaitResponse( const sp<AMessage> &msg, sp<AMessage> *response) { + sp<ALooper> looper = findLooper(msg->target()); + + if (looper == NULL) { + ALOGW("failed to post message. " + "Target handler %d still registered, but object gone.", + msg->target()); + response->clear(); + return -ENOENT; + } + Mutex::Autolock autoLock(mLock); uint32_t replyID = mNextReplyID++; msg->setInt32("replyID", replyID); - status_t err = postMessage_l(msg, 0 /* delayUs */); - - if (err != OK) { - response->clear(); - return err; - } + looper->post(msg, 0 /* delayUs */); ssize_t index; while ((index = mReplies.indexOfKey(replyID)) < 0) { diff --git a/media/libstagefright/foundation/AMessage.cpp b/media/libstagefright/foundation/AMessage.cpp index dc42f91..795e8a6 100644 --- a/media/libstagefright/foundation/AMessage.cpp +++ b/media/libstagefright/foundation/AMessage.cpp @@ -14,6 +14,11 @@ * limitations under the License. */ +#define LOG_TAG "AMessage" +//#define LOG_NDEBUG 0 +//#define DUMP_STATS +#include <cutils/log.h> + #include "AMessage.h" #include <ctype.h> @@ -60,12 +65,14 @@ ALooper::handler_id AMessage::target() const { void AMessage::clear() { for (size_t i = 0; i < mNumItems; ++i) { Item *item = &mItems[i]; - freeItem(item); + delete[] item->mName; + item->mName = NULL; + freeItemValue(item); } mNumItems = 0; } -void AMessage::freeItem(Item *item) { +void AMessage::freeItemValue(Item *item) { switch (item->mType) { case kTypeString: { @@ -88,25 +95,85 @@ void AMessage::freeItem(Item *item) { } } -AMessage::Item *AMessage::allocateItem(const char *name) { - name = AAtomizer::Atomize(name); +#ifdef DUMP_STATS +#include <utils/Mutex.h> + +Mutex gLock; +static int32_t gFindItemCalls = 1; +static int32_t gDupCalls = 1; +static int32_t gAverageNumItems = 0; +static int32_t gAverageNumChecks = 0; +static int32_t gAverageNumMemChecks = 0; +static int32_t gAverageDupItems = 0; +static int32_t gLastChecked = -1; + +static void reportStats() { + int32_t time = (ALooper::GetNowUs() / 1000); + if (time / 1000 != gLastChecked / 1000) { + gLastChecked = time; + ALOGI("called findItemIx %zu times (for len=%.1f i=%.1f/%.1f mem) dup %zu times (for len=%.1f)", + gFindItemCalls, + gAverageNumItems / (float)gFindItemCalls, + gAverageNumChecks / (float)gFindItemCalls, + gAverageNumMemChecks / (float)gFindItemCalls, + gDupCalls, + gAverageDupItems / (float)gDupCalls); + gFindItemCalls = gDupCalls = 1; + gAverageNumItems = gAverageNumChecks = gAverageNumMemChecks = gAverageDupItems = 0; + gLastChecked = time; + } +} +#endif +inline size_t AMessage::findItemIndex(const char *name, size_t len) const { +#ifdef DUMP_STATS + size_t memchecks = 0; +#endif size_t i = 0; - while (i < mNumItems && mItems[i].mName != name) { - ++i; + for (; i < mNumItems; i++) { + if (len != mItems[i].mNameLength) { + continue; + } +#ifdef DUMP_STATS + ++memchecks; +#endif + if (!memcmp(mItems[i].mName, name, len)) { + break; + } } +#ifdef DUMP_STATS + { + Mutex::Autolock _l(gLock); + ++gFindItemCalls; + gAverageNumItems += mNumItems; + gAverageNumMemChecks += memchecks; + gAverageNumChecks += i; + reportStats(); + } +#endif + return i; +} + +// assumes item's name was uninitialized or NULL +void AMessage::Item::setName(const char *name, size_t len) { + mNameLength = len; + mName = new char[len + 1]; + memcpy((void*)mName, name, len + 1); +} +AMessage::Item *AMessage::allocateItem(const char *name) { + size_t len = strlen(name); + size_t i = findItemIndex(name, len); Item *item; if (i < mNumItems) { item = &mItems[i]; - freeItem(item); + freeItemValue(item); } else { CHECK(mNumItems < kMaxNumItems); i = mNumItems++; item = &mItems[i]; - - item->mName = name; + item->setName(name, len); } return item; @@ -114,19 +181,20 @@ AMessage::Item *AMessage::allocateItem(const char *name) { const AMessage::Item *AMessage::findItem( const char *name, Type type) const { - name = AAtomizer::Atomize(name); - - for (size_t i = 0; i < mNumItems; ++i) { + size_t i = findItemIndex(name, strlen(name)); + if (i < mNumItems) { const Item *item = &mItems[i]; + return item->mType == type ? item : NULL; - if (item->mName == name) { - return item->mType == type ? item : NULL; - } } - return NULL; } +bool AMessage::contains(const char *name) const { + size_t i = findItemIndex(name, strlen(name)); + return i < mNumItems; +} + #define BASIC_TYPE(NAME,FIELDNAME,TYPENAME) \ void AMessage::set##NAME(const char *name, TYPENAME value) { \ Item *item = allocateItem(name); \ @@ -160,6 +228,11 @@ void AMessage::setString( item->u.stringValue = new AString(s, len < 0 ? strlen(s) : len); } +void AMessage::setString( + const char *name, const AString &s) { + setString(name, s.c_str(), s.size()); +} + void AMessage::setObjectInternal( const char *name, const sp<RefBase> &obj, Type type) { Item *item = allocateItem(name); @@ -278,11 +351,20 @@ sp<AMessage> AMessage::dup() const { sp<AMessage> msg = new AMessage(mWhat, mTarget); msg->mNumItems = mNumItems; +#ifdef DUMP_STATS + { + Mutex::Autolock _l(gLock); + ++gDupCalls; + gAverageDupItems += mNumItems; + reportStats(); + } +#endif + for (size_t i = 0; i < mNumItems; ++i) { const Item *from = &mItems[i]; Item *to = &msg->mItems[i]; - to->mName = from->mName; + to->setName(from->mName, from->mNameLength); to->mType = from->mType; switch (from->mType) { @@ -403,7 +485,7 @@ AString AMessage::debugString(int32_t indent) const { { sp<ABuffer> buffer = static_cast<ABuffer *>(item.u.refValue); - if (buffer != NULL && buffer->size() <= 64) { + if (buffer != NULL && buffer->data() != NULL && buffer->size() <= 64) { tmp = StringPrintf("Buffer %s = {\n", item.mName); hexdump(buffer->data(), buffer->size(), indent + 4, &tmp); appendIndent(&tmp, indent + 2); @@ -453,11 +535,11 @@ sp<AMessage> AMessage::FromParcel(const Parcel &parcel) { sp<AMessage> msg = new AMessage(what); msg->mNumItems = static_cast<size_t>(parcel.readInt32()); - for (size_t i = 0; i < msg->mNumItems; ++i) { Item *item = &msg->mItems[i]; - item->mName = AAtomizer::Atomize(parcel.readCString()); + const char *name = parcel.readCString(); + item->setName(name, strlen(name)); item->mType = static_cast<Type>(parcel.readInt32()); switch (item->mType) { diff --git a/media/libstagefright/foundation/ANetworkSession.cpp b/media/libstagefright/foundation/ANetworkSession.cpp index e629588..4504c2b 100644 --- a/media/libstagefright/foundation/ANetworkSession.cpp +++ b/media/libstagefright/foundation/ANetworkSession.cpp @@ -521,7 +521,7 @@ status_t ANetworkSession::Session::readMore() { return err; } -void ANetworkSession::Session::dumpFragmentStats(const Fragment &frag) { +void ANetworkSession::Session::dumpFragmentStats(const Fragment & /* frag */) { #if 0 int64_t nowUs = ALooper::GetNowUs(); int64_t delayMs = (nowUs - frag.mTimeUs) / 1000ll; @@ -579,7 +579,7 @@ status_t ANetworkSession::Session::writeMore() { if (err == -EAGAIN) { if (!mOutFragments.empty()) { - ALOGI("%d datagrams remain queued.", mOutFragments.size()); + ALOGI("%zu datagrams remain queued.", mOutFragments.size()); } err = OK; } @@ -623,7 +623,7 @@ status_t ANetworkSession::Session::writeMore() { CHECK_EQ(mState, CONNECTED); CHECK(!mOutFragments.empty()); - ssize_t n; + ssize_t n = -1; while (!mOutFragments.empty()) { const Fragment &frag = *mOutFragments.begin(); diff --git a/media/libstagefright/foundation/AString.cpp b/media/libstagefright/foundation/AString.cpp index dee786d..9835ca3 100644 --- a/media/libstagefright/foundation/AString.cpp +++ b/media/libstagefright/foundation/AString.cpp @@ -20,6 +20,8 @@ #include <stdlib.h> #include <string.h> +#include <binder/Parcel.h> +#include <utils/String8.h> #include "ADebug.h" #include "AString.h" @@ -48,6 +50,13 @@ AString::AString(const char *s, size_t size) setTo(s, size); } +AString::AString(const String8 &from) + : mData(NULL), + mSize(0), + mAllocSize(1) { + setTo(from.string(), from.length()); +} + AString::AString(const AString &from) : mData(NULL), mSize(0), @@ -189,64 +198,64 @@ void AString::append(const AString &from, size_t offset, size_t n) { void AString::append(int x) { char s[16]; - sprintf(s, "%d", x); - + int result = snprintf(s, sizeof(s), "%d", x); + CHECK((result > 0) && ((size_t) result) < sizeof(s)); append(s); } void AString::append(unsigned x) { char s[16]; - sprintf(s, "%u", x); - + int result = snprintf(s, sizeof(s), "%u", x); + CHECK((result > 0) && ((size_t) result) < sizeof(s)); append(s); } void AString::append(long x) { - char s[16]; - sprintf(s, "%ld", x); - + char s[32]; + int result = snprintf(s, sizeof(s), "%ld", x); + CHECK((result > 0) && ((size_t) result) < sizeof(s)); append(s); } void AString::append(unsigned long x) { - char s[16]; - sprintf(s, "%lu", x); - + char s[32]; + int result = snprintf(s, sizeof(s), "%lu", x); + CHECK((result > 0) && ((size_t) result) < sizeof(s)); append(s); } void AString::append(long long x) { char s[32]; - sprintf(s, "%lld", x); - + int result = snprintf(s, sizeof(s), "%lld", x); + CHECK((result > 0) && ((size_t) result) < sizeof(s)); append(s); } void AString::append(unsigned long long x) { char s[32]; - sprintf(s, "%llu", x); - + int result = snprintf(s, sizeof(s), "%llu", x); + CHECK((result > 0) && ((size_t) result) < sizeof(s)); append(s); } void AString::append(float x) { char s[16]; - sprintf(s, "%f", x); - + int result = snprintf(s, sizeof(s), "%f", x); + CHECK((result > 0) && ((size_t) result) < sizeof(s)); append(s); } void AString::append(double x) { char s[16]; - sprintf(s, "%f", x); - + int result = snprintf(s, sizeof(s), "%f", x); + CHECK((result > 0) && ((size_t) result) < sizeof(s)); append(s); } void AString::append(void *x) { - char s[16]; - sprintf(s, "%p", x); - + char s[32]; + int result = snprintf(s, sizeof(s), "%p", x); + CHECK((result > 0) && ((size_t) result) < sizeof(s)); append(s); } @@ -298,6 +307,14 @@ int AString::compare(const AString &other) const { return strcmp(mData, other.mData); } +int AString::compareIgnoreCase(const AString &other) const { + return strcasecmp(mData, other.mData); +} + +bool AString::equalsIgnoreCase(const AString &other) const { + return compareIgnoreCase(other) == 0; +} + void AString::tolower() { makeMutable(); @@ -320,6 +337,35 @@ bool AString::endsWith(const char *suffix) const { return !strcmp(mData + mSize - suffixLen, suffix); } +bool AString::startsWithIgnoreCase(const char *prefix) const { + return !strncasecmp(mData, prefix, strlen(prefix)); +} + +bool AString::endsWithIgnoreCase(const char *suffix) const { + size_t suffixLen = strlen(suffix); + + if (mSize < suffixLen) { + return false; + } + + return !strcasecmp(mData + mSize - suffixLen, suffix); +} + +// static +AString AString::FromParcel(const Parcel &parcel) { + size_t size = static_cast<size_t>(parcel.readInt32()); + return AString(static_cast<const char *>(parcel.readInplace(size)), size); +} + +status_t AString::writeToParcel(Parcel *parcel) const { + CHECK_LE(mSize, static_cast<size_t>(INT32_MAX)); + status_t err = parcel->writeInt32(mSize); + if (err == OK) { + err = parcel->write(mData, mSize); + } + return err; +} + AString StringPrintf(const char *format, ...) { va_list ap; va_start(ap, format); diff --git a/media/libstagefright/foundation/Android.mk b/media/libstagefright/foundation/Android.mk index ad2dab5..90a6a23 100644 --- a/media/libstagefright/foundation/Android.mk +++ b/media/libstagefright/foundation/Android.mk @@ -24,7 +24,7 @@ LOCAL_SHARED_LIBRARIES := \ libutils \ liblog -LOCAL_CFLAGS += -Wno-multichar +LOCAL_CFLAGS += -Wno-multichar -Werror LOCAL_MODULE:= libstagefright_foundation diff --git a/media/libstagefright/foundation/base64.cpp b/media/libstagefright/foundation/base64.cpp index d5fb4e0..dcf5bef 100644 --- a/media/libstagefright/foundation/base64.cpp +++ b/media/libstagefright/foundation/base64.cpp @@ -33,6 +33,10 @@ sp<ABuffer> decodeBase64(const AString &s) { if (n >= 2 && s.c_str()[n - 2] == '=') { padding = 2; + + if (n >= 3 && s.c_str()[n - 3] == '=') { + padding = 3; + } } } @@ -71,7 +75,7 @@ sp<ABuffer> decodeBase64(const AString &s) { if (((i + 1) % 4) == 0) { out[j++] = (accum >> 16); - if (j < outLen) { out[j++] = (accum >> 8) & 0xff; } + if (j < outLen) { out[j++] = (accum >> 8) & 0xff; } if (j < outLen) { out[j++] = accum & 0xff; } accum = 0; |