diff options
Diffstat (limited to 'media/libstagefright')
-rw-r--r-- | media/libstagefright/foundation/AAtomizer.cpp | 67 | ||||
-rw-r--r-- | media/libstagefright/foundation/ABuffer.cpp | 76 | ||||
-rw-r--r-- | media/libstagefright/foundation/ADebug.cpp | 76 | ||||
-rw-r--r-- | media/libstagefright/foundation/ALooper.cpp | 196 | ||||
-rw-r--r-- | media/libstagefright/foundation/ALooperRoster.cpp | 100 | ||||
-rw-r--r-- | media/libstagefright/foundation/AMessage.cpp | 241 | ||||
-rw-r--r-- | media/libstagefright/foundation/AString.cpp | 331 | ||||
-rw-r--r-- | media/libstagefright/foundation/Android.mk | 35 | ||||
-rw-r--r-- | media/libstagefright/foundation/base64.cpp | 139 | ||||
-rw-r--r-- | media/libstagefright/foundation/hexdump.cpp | 73 |
10 files changed, 1334 insertions, 0 deletions
diff --git a/media/libstagefright/foundation/AAtomizer.cpp b/media/libstagefright/foundation/AAtomizer.cpp new file mode 100644 index 0000000..b7b9e9f --- /dev/null +++ b/media/libstagefright/foundation/AAtomizer.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <sys/types.h> + +#include "AAtomizer.h" + +namespace android { + +// static +AAtomizer AAtomizer::gAtomizer; + +// static +const char *AAtomizer::Atomize(const char *name) { + return gAtomizer.atomize(name); +} + +AAtomizer::AAtomizer() { + for (size_t i = 0; i < 128; ++i) { + mAtoms.push(List<AString>()); + } +} + +const char *AAtomizer::atomize(const char *name) { + Mutex::Autolock autoLock(mLock); + + const size_t n = mAtoms.size(); + size_t index = AAtomizer::Hash(name) % n; + List<AString> &entry = mAtoms.editItemAt(index); + List<AString>::iterator it = entry.begin(); + while (it != entry.end()) { + if ((*it) == name) { + return (*it).c_str(); + } + ++it; + } + + entry.push_back(AString(name)); + + return (*--entry.end()).c_str(); +} + +// static +uint32_t AAtomizer::Hash(const char *s) { + uint32_t sum = 0; + while (*s != '\0') { + sum = (sum * 31) + *s; + ++s; + } + + return sum; +} + +} // namespace android diff --git a/media/libstagefright/foundation/ABuffer.cpp b/media/libstagefright/foundation/ABuffer.cpp new file mode 100644 index 0000000..6173db4 --- /dev/null +++ b/media/libstagefright/foundation/ABuffer.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ABuffer.h" + +#include "ADebug.h" +#include "ALooper.h" +#include "AMessage.h" + +namespace android { + +ABuffer::ABuffer(size_t capacity) + : mData(malloc(capacity)), + mCapacity(capacity), + mRangeOffset(0), + mRangeLength(capacity), + mInt32Data(0), + mOwnsData(true) { +} + +ABuffer::ABuffer(void *data, size_t capacity) + : mData(data), + mCapacity(capacity), + mRangeOffset(0), + mRangeLength(capacity), + mInt32Data(0), + mOwnsData(false) { +} + +ABuffer::~ABuffer() { + if (mOwnsData) { + if (mData != NULL) { + free(mData); + mData = NULL; + } + } + + if (mFarewell != NULL) { + mFarewell->post(); + } +} + +void ABuffer::setRange(size_t offset, size_t size) { + CHECK_LE(offset, mCapacity); + CHECK_LE(offset + size, mCapacity); + + mRangeOffset = offset; + mRangeLength = size; +} + +void ABuffer::setFarewellMessage(const sp<AMessage> msg) { + mFarewell = msg; +} + +sp<AMessage> ABuffer::meta() { + if (mMeta == NULL) { + mMeta = new AMessage; + } + return mMeta; +} + +} // namespace android + diff --git a/media/libstagefright/foundation/ADebug.cpp b/media/libstagefright/foundation/ADebug.cpp new file mode 100644 index 0000000..16f8b22 --- /dev/null +++ b/media/libstagefright/foundation/ADebug.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ADebug.h" + +#include <stdio.h> +#include <stdlib.h> + +#ifdef ANDROID +#include <cutils/log.h> +#endif + +namespace android { + +Logger::Logger(LogType type) + : mLogType(type) { + switch (mLogType) { + case VERBOSE: + mMessage = "V "; + break; + case INFO: + mMessage = "I "; + break; + case WARNING: + mMessage = "W "; + break; + case ERROR: + mMessage = "E "; + break; + case FATAL: + mMessage = "F "; + break; + + default: + break; + } +} + +Logger::~Logger() { + if (mLogType == VERBOSE) { + return; + } + + mMessage.append("\n"); + +#if defined(ANDROID) && 1 + LOG_PRI(ANDROID_LOG_INFO, "ADebug", "%s", mMessage.c_str()); +#else + fprintf(stderr, mMessage.c_str()); + fflush(stderr); +#endif + + if (mLogType == FATAL) { + abort(); + } +} + +const char *LeafName(const char *s) { + const char *lastSlash = strrchr(s, '/'); + return lastSlash != NULL ? lastSlash + 1 : s; +} + +} // namespace android diff --git a/media/libstagefright/foundation/ALooper.cpp b/media/libstagefright/foundation/ALooper.cpp new file mode 100644 index 0000000..831fa2a --- /dev/null +++ b/media/libstagefright/foundation/ALooper.cpp @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "ALooper" +#include <utils/Log.h> + +#include <sys/time.h> + +#include "ALooper.h" + +#include "AHandler.h" +#include "ALooperRoster.h" +#include "AMessage.h" + +namespace android { + +ALooperRoster gLooperRoster; + +struct ALooper::LooperThread : public Thread { + LooperThread(ALooper *looper) + : mLooper(looper) { + } + + virtual bool threadLoop() { + return mLooper->loop(); + } + +protected: + virtual ~LooperThread() {} + +private: + ALooper *mLooper; + + DISALLOW_EVIL_CONSTRUCTORS(LooperThread); +}; + +// static +int64_t ALooper::GetNowUs() { + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int64_t)tv.tv_sec * 1000000ll + tv.tv_usec; +} + +ALooper::ALooper() + : mRunningLocally(false) { +} + +ALooper::~ALooper() { + stop(); +} + +ALooper::handler_id ALooper::registerHandler(const sp<AHandler> &handler) { + return gLooperRoster.registerHandler(this, handler); +} + +void ALooper::unregisterHandler(handler_id handlerID) { + gLooperRoster.unregisterHandler(handlerID); +} + +status_t ALooper::start(bool runOnCallingThread) { + if (runOnCallingThread) { + { + Mutex::Autolock autoLock(mLock); + + if (mThread != NULL || mRunningLocally) { + return INVALID_OPERATION; + } + + mRunningLocally = true; + } + + do { + } while (loop()); + + return OK; + } + + Mutex::Autolock autoLock(mLock); + + if (mThread != NULL || mRunningLocally) { + return INVALID_OPERATION; + } + + mThread = new LooperThread(this); + + status_t err = mThread->run("ALooper"); + if (err != OK) { + mThread.clear(); + } + + return err; +} + +status_t ALooper::stop() { + sp<LooperThread> thread; + bool runningLocally; + + { + Mutex::Autolock autoLock(mLock); + + thread = mThread; + runningLocally = mRunningLocally; + mThread.clear(); + mRunningLocally = false; + } + + if (thread == NULL && !runningLocally) { + return INVALID_OPERATION; + } + + if (thread != NULL) { + thread->requestExit(); + } + + mQueueChangedCondition.signal(); + + if (!runningLocally) { + thread->requestExitAndWait(); + } + + return OK; +} + +void ALooper::post(const sp<AMessage> &msg, int64_t delayUs) { + Mutex::Autolock autoLock(mLock); + + int64_t whenUs; + if (delayUs > 0) { + whenUs = GetNowUs() + delayUs; + } else { + whenUs = GetNowUs(); + } + + List<Event>::iterator it = mEventQueue.begin(); + while (it != mEventQueue.end() && (*it).mWhenUs <= whenUs) { + ++it; + } + + Event event; + event.mWhenUs = whenUs; + event.mMessage = msg; + + if (it == mEventQueue.begin()) { + mQueueChangedCondition.signal(); + } + + mEventQueue.insert(it, event); +} + +bool ALooper::loop() { + Event event; + + { + Mutex::Autolock autoLock(mLock); + if (mThread == NULL && !mRunningLocally) { + return false; + } + if (mEventQueue.empty()) { + mQueueChangedCondition.wait(mLock); + return true; + } + int64_t whenUs = (*mEventQueue.begin()).mWhenUs; + int64_t nowUs = GetNowUs(); + + if (whenUs > nowUs) { + int64_t delayUs = whenUs - nowUs; + mQueueChangedCondition.waitRelative(mLock, delayUs * 1000ll); + + return true; + } + + event = *mEventQueue.begin(); + mEventQueue.erase(mEventQueue.begin()); + } + + gLooperRoster.deliverMessage(event.mMessage); + + return true; +} + +} // namespace android diff --git a/media/libstagefright/foundation/ALooperRoster.cpp b/media/libstagefright/foundation/ALooperRoster.cpp new file mode 100644 index 0000000..5bb1cf9 --- /dev/null +++ b/media/libstagefright/foundation/ALooperRoster.cpp @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "ALooperRoster" +#include <utils/Log.h> + +#include "ALooperRoster.h" + +#include "ADebug.h" +#include "AHandler.h" +#include "AMessage.h" + +namespace android { + +ALooperRoster::ALooperRoster() + : mNextHandlerID(1) { +} + +ALooper::handler_id ALooperRoster::registerHandler( + const sp<ALooper> looper, const sp<AHandler> &handler) { + Mutex::Autolock autoLock(mLock); + + if (handler->id() != 0) { + CHECK(!"A handler must only be registered once."); + return INVALID_OPERATION; + } + + HandlerInfo info; + info.mLooper = looper; + info.mHandler = handler; + ALooper::handler_id handlerID = mNextHandlerID++; + mHandlers.add(handlerID, info); + + handler->setID(handlerID); + + return handlerID; +} + +void ALooperRoster::unregisterHandler(ALooper::handler_id handlerID) { + Mutex::Autolock autoLock(mLock); + + ssize_t index = mHandlers.indexOfKey(handlerID); + CHECK(index >= 0); + + const HandlerInfo &info = mHandlers.valueAt(index); + info.mHandler->setID(0); + + mHandlers.removeItemsAt(index); +} + +void ALooperRoster::postMessage( + const sp<AMessage> &msg, int64_t delayUs) { + Mutex::Autolock autoLock(mLock); + + ssize_t index = mHandlers.indexOfKey(msg->target()); + + if (index < 0) { + LOG(WARNING) << "failed to post message. Target handler not registered."; + return; + } + + const HandlerInfo &info = mHandlers.valueAt(index); + info.mLooper->post(msg, delayUs); +} + +void ALooperRoster::deliverMessage(const sp<AMessage> &msg) { + sp<AHandler> handler; + + { + Mutex::Autolock autoLock(mLock); + + ssize_t index = mHandlers.indexOfKey(msg->target()); + + if (index < 0) { + LOG(WARNING) << "failed to deliver message. Target handler not registered."; + return; + } + + const HandlerInfo &info = mHandlers.valueAt(index); + handler = info.mHandler; + } + + handler->onMessageReceived(msg); +} + +} // namespace android diff --git a/media/libstagefright/foundation/AMessage.cpp b/media/libstagefright/foundation/AMessage.cpp new file mode 100644 index 0000000..dfd1ae3 --- /dev/null +++ b/media/libstagefright/foundation/AMessage.cpp @@ -0,0 +1,241 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "AMessage.h" + +#include "AAtomizer.h" +#include "ADebug.h" +#include "ALooperRoster.h" +#include "AString.h" + +namespace android { + +AMessage::AMessage(uint32_t what, ALooper::handler_id target) + : mWhat(what), + mTarget(target), + mNumItems(0) { +} + +AMessage::~AMessage() { + clear(); +} + +void AMessage::setWhat(uint32_t what) { + mWhat = what; +} + +uint32_t AMessage::what() const { + return mWhat; +} + +void AMessage::setTarget(ALooper::handler_id handlerID) { + mTarget = handlerID; +} + +ALooper::handler_id AMessage::target() const { + return mTarget; +} + +void AMessage::clear() { + for (size_t i = 0; i < mNumItems; ++i) { + Item *item = &mItems[i]; + freeItem(item); + } + mNumItems = 0; +} + +void AMessage::freeItem(Item *item) { + switch (item->mType) { + case kTypeString: + { + delete item->u.stringValue; + break; + } + + case kTypeObject: + case kTypeMessage: + { + if (item->u.refValue != NULL) { + item->u.refValue->decStrong(this); + } + break; + } + + default: + break; + } +} + +AMessage::Item *AMessage::allocateItem(const char *name) { + name = AAtomizer::Atomize(name); + + size_t i = 0; + while (i < mNumItems && mItems[i].mName != name) { + ++i; + } + + Item *item; + + if (i < mNumItems) { + item = &mItems[i]; + freeItem(item); + } else { + CHECK(mNumItems < kMaxNumItems); + i = mNumItems++; + item = &mItems[i]; + + item->mName = name; + } + + return item; +} + +const AMessage::Item *AMessage::findItem( + const char *name, Type type) const { + name = AAtomizer::Atomize(name); + + for (size_t i = 0; i < mNumItems; ++i) { + const Item *item = &mItems[i]; + + if (item->mName == name) { + return item->mType == type ? item : NULL; + } + } + + return NULL; +} + +#define BASIC_TYPE(NAME,FIELDNAME,TYPENAME) \ +void AMessage::set##NAME(const char *name, TYPENAME value) { \ + Item *item = allocateItem(name); \ + \ + item->mType = kType##NAME; \ + item->u.FIELDNAME = value; \ +} \ + \ +bool AMessage::find##NAME(const char *name, TYPENAME *value) const { \ + const Item *item = findItem(name, kType##NAME); \ + if (item) { \ + *value = item->u.FIELDNAME; \ + return true; \ + } \ + return false; \ +} + +BASIC_TYPE(Int32,int32Value,int32_t) +BASIC_TYPE(Int64,int64Value,int64_t) +BASIC_TYPE(Size,sizeValue,size_t) +BASIC_TYPE(Float,floatValue,float) +BASIC_TYPE(Double,doubleValue,double) +BASIC_TYPE(Pointer,ptrValue,void *) + +#undef BASIC_TYPE + +void AMessage::setString( + const char *name, const char *s, ssize_t len) { + Item *item = allocateItem(name); + item->mType = kTypeString; + item->u.stringValue = new AString(s, len < 0 ? strlen(s) : len); +} + +void AMessage::setObject(const char *name, const sp<RefBase> &obj) { + Item *item = allocateItem(name); + item->mType = kTypeObject; + + if (obj != NULL) { obj->incStrong(this); } + item->u.refValue = obj.get(); +} + +void AMessage::setMessage(const char *name, const sp<AMessage> &obj) { + Item *item = allocateItem(name); + item->mType = kTypeMessage; + + if (obj != NULL) { obj->incStrong(this); } + item->u.refValue = obj.get(); +} + +bool AMessage::findString(const char *name, AString *value) const { + const Item *item = findItem(name, kTypeString); + if (item) { + *value = *item->u.stringValue; + return true; + } + return false; +} + +bool AMessage::findObject(const char *name, sp<RefBase> *obj) const { + const Item *item = findItem(name, kTypeObject); + if (item) { + *obj = item->u.refValue; + return true; + } + return false; +} + +bool AMessage::findMessage(const char *name, sp<AMessage> *obj) const { + const Item *item = findItem(name, kTypeMessage); + if (item) { + *obj = static_cast<AMessage *>(item->u.refValue); + return true; + } + return false; +} + +void AMessage::post(int64_t delayUs) { + extern ALooperRoster gLooperRoster; + + gLooperRoster.postMessage(this, delayUs); +} + +sp<AMessage> AMessage::dup() const { + sp<AMessage> msg = new AMessage(mWhat, mTarget); + msg->mNumItems = mNumItems; + + for (size_t i = 0; i < mNumItems; ++i) { + const Item *from = &mItems[i]; + Item *to = &msg->mItems[i]; + + to->mName = from->mName; + to->mType = from->mType; + + switch (from->mType) { + case kTypeString: + { + to->u.stringValue = + new AString(*from->u.stringValue); + break; + } + + case kTypeObject: + case kTypeMessage: + { + to->u.refValue = from->u.refValue; + to->u.refValue->incStrong(msg.get()); + break; + } + + default: + { + to->u = from->u; + break; + } + } + } + + return msg; +} + +} // namespace android diff --git a/media/libstagefright/foundation/AString.cpp b/media/libstagefright/foundation/AString.cpp new file mode 100644 index 0000000..61b76cf --- /dev/null +++ b/media/libstagefright/foundation/AString.cpp @@ -0,0 +1,331 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <ctype.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "ADebug.h" +#include "AString.h" + +namespace android { + +// static +const char *AString::kEmptyString = ""; + +AString::AString() + : mData((char *)kEmptyString), + mSize(0), + mAllocSize(1) { +} + +AString::AString(const char *s) + : mData(NULL), + mSize(0), + mAllocSize(1) { + setTo(s); +} + +AString::AString(const char *s, size_t size) + : mData(NULL), + mSize(0), + mAllocSize(1) { + setTo(s, size); +} + +AString::AString(const AString &from) + : mData(NULL), + mSize(0), + mAllocSize(1) { + setTo(from, 0, from.size()); +} + +AString::AString(const AString &from, size_t offset, size_t n) + : mData(NULL), + mSize(0), + mAllocSize(1) { + setTo(from, offset, n); +} + +AString::~AString() { + clear(); +} + +AString &AString::operator=(const AString &from) { + if (&from != this) { + setTo(from, 0, from.size()); + } + + return *this; +} + +size_t AString::size() const { + return mSize; +} + +const char *AString::c_str() const { + return mData; +} + +bool AString::empty() const { + return mSize == 0; +} + +void AString::setTo(const char *s) { + setTo(s, strlen(s)); +} + +void AString::setTo(const char *s, size_t size) { + clear(); + append(s, size); +} + +void AString::setTo(const AString &from, size_t offset, size_t n) { + CHECK(&from != this); + + clear(); + setTo(from.mData + offset, n); +} + +void AString::clear() { + if (mData && mData != kEmptyString) { + free(mData); + mData = NULL; + } + + mData = (char *)kEmptyString; + mSize = 0; + mAllocSize = 1; +} + +size_t AString::hash() const { + size_t x = 0; + for (size_t i = 0; i < mSize; ++i) { + x = (x * 31) + mData[i]; + } + + return x; +} + +bool AString::operator==(const AString &other) const { + return mSize == other.mSize && !memcmp(mData, other.mData, mSize); +} + +void AString::trim() { + makeMutable(); + + size_t i = 0; + while (i < mSize && isspace(mData[i])) { + ++i; + } + + size_t j = mSize; + while (j > i && isspace(mData[j - 1])) { + --j; + } + + memmove(mData, &mData[i], j - i); + mSize = j - i; + mData[mSize] = '\0'; +} + +void AString::erase(size_t start, size_t n) { + CHECK_LT(start, mSize); + CHECK_LE(start + n, mSize); + + makeMutable(); + + memmove(&mData[start], &mData[start + n], mSize - start - n); + mSize -= n; + mData[mSize] = '\0'; +} + +void AString::makeMutable() { + if (mData == kEmptyString) { + mData = strdup(kEmptyString); + } +} + +void AString::append(const char *s) { + append(s, strlen(s)); +} + +void AString::append(const char *s, size_t size) { + makeMutable(); + + if (mSize + size + 1 > mAllocSize) { + mAllocSize = (mAllocSize + size + 31) & -32; + mData = (char *)realloc(mData, mAllocSize); + CHECK(mData != NULL); + } + + memcpy(&mData[mSize], s, size); + mSize += size; + mData[mSize] = '\0'; +} + +void AString::append(const AString &from) { + append(from.c_str(), from.size()); +} + +void AString::append(const AString &from, size_t offset, size_t n) { + append(from.c_str() + offset, n); +} + +void AString::append(int x) { + char s[16]; + sprintf(s, "%d", x); + + append(s); +} + +void AString::append(unsigned x) { + char s[16]; + sprintf(s, "%u", x); + + append(s); +} + +void AString::append(long x) { + char s[16]; + sprintf(s, "%ld", x); + + append(s); +} + +void AString::append(unsigned long x) { + char s[16]; + sprintf(s, "%lu", x); + + append(s); +} + +void AString::append(long long x) { + char s[32]; + sprintf(s, "%lld", x); + + append(s); +} + +void AString::append(unsigned long long x) { + char s[32]; + sprintf(s, "%llu", x); + + append(s); +} + +void AString::append(float x) { + char s[16]; + sprintf(s, "%f", x); + + append(s); +} + +void AString::append(double x) { + char s[16]; + sprintf(s, "%f", x); + + append(s); +} + +void AString::append(void *x) { + char s[16]; + sprintf(s, "%p", x); + + append(s); +} + +ssize_t AString::find(const char *substring, size_t start) const { + CHECK_LE(start, size()); + + const char *match = strstr(mData + start, substring); + + if (match == NULL) { + return -1; + } + + return match - mData; +} + +void AString::insert(const AString &from, size_t insertionPos) { + insert(from.c_str(), from.size(), insertionPos); +} + +void AString::insert(const char *from, size_t size, size_t insertionPos) { + CHECK_GE(insertionPos, 0u); + CHECK_LE(insertionPos, mSize); + + makeMutable(); + + if (mSize + size + 1 > mAllocSize) { + mAllocSize = (mAllocSize + size + 31) & -32; + mData = (char *)realloc(mData, mAllocSize); + CHECK(mData != NULL); + } + + memmove(&mData[insertionPos + size], + &mData[insertionPos], mSize - insertionPos + 1); + + memcpy(&mData[insertionPos], from, size); + + mSize += size; +} + +bool AString::operator<(const AString &other) const { + return compare(other) < 0; +} + +bool AString::operator>(const AString &other) const { + return compare(other) > 0; +} + +int AString::compare(const AString &other) const { + return strcmp(mData, other.mData); +} + +void AString::tolower() { + makeMutable(); + + for (size_t i = 0; i < mSize; ++i) { + mData[i] = ::tolower(mData[i]); + } +} + +bool AString::startsWith(const char *prefix) const { + return !strncmp(mData, prefix, strlen(prefix)); +} + +AString StringPrintf(const char *format, ...) { + va_list ap; + va_start(ap, format); + + char *buffer; + vasprintf(&buffer, format, ap); + + va_end(ap); + + AString result(buffer); + + free(buffer); + buffer = NULL; + + return result; +} + +} // namespace android + diff --git a/media/libstagefright/foundation/Android.mk b/media/libstagefright/foundation/Android.mk new file mode 100644 index 0000000..73047e7 --- /dev/null +++ b/media/libstagefright/foundation/Android.mk @@ -0,0 +1,35 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + AAtomizer.cpp \ + ABuffer.cpp \ + ADebug.cpp \ + ALooper.cpp \ + ALooperRoster.cpp \ + AMessage.cpp \ + AString.cpp \ + base64.cpp \ + hexdump.cpp + +LOCAL_C_INCLUDES:= \ + frameworks/base/include/media/stagefright/foundation + +LOCAL_SHARED_LIBRARIES := \ + libbinder \ + libmedia \ + libutils \ + libcutils \ + libui \ + libsonivox \ + libvorbisidec \ + libsurfaceflinger_client \ + libcamera_client + +LOCAL_CFLAGS += -Wno-multichar + +LOCAL_MODULE:= libstagefright_foundation + +LOCAL_PRELINK_MODULE:= false + +include $(BUILD_SHARED_LIBRARY) diff --git a/media/libstagefright/foundation/base64.cpp b/media/libstagefright/foundation/base64.cpp new file mode 100644 index 0000000..d5fb4e0 --- /dev/null +++ b/media/libstagefright/foundation/base64.cpp @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "base64.h" + +#include "ABuffer.h" +#include "ADebug.h" + +namespace android { + +sp<ABuffer> decodeBase64(const AString &s) { + if ((s.size() % 4) != 0) { + return NULL; + } + + size_t n = s.size(); + size_t padding = 0; + if (n >= 1 && s.c_str()[n - 1] == '=') { + padding = 1; + + if (n >= 2 && s.c_str()[n - 2] == '=') { + padding = 2; + } + } + + size_t outLen = 3 * s.size() / 4 - padding; + + sp<ABuffer> buffer = new ABuffer(outLen); + + uint8_t *out = buffer->data(); + size_t j = 0; + uint32_t accum = 0; + for (size_t i = 0; i < n; ++i) { + char c = s.c_str()[i]; + unsigned value; + if (c >= 'A' && c <= 'Z') { + value = c - 'A'; + } else if (c >= 'a' && c <= 'z') { + value = 26 + c - 'a'; + } else if (c >= '0' && c <= '9') { + value = 52 + c - '0'; + } else if (c == '+') { + value = 62; + } else if (c == '/') { + value = 63; + } else if (c != '=') { + return NULL; + } else { + if (i < n - padding) { + return NULL; + } + + value = 0; + } + + accum = (accum << 6) | value; + + if (((i + 1) % 4) == 0) { + out[j++] = (accum >> 16); + + if (j < outLen) { out[j++] = (accum >> 8) & 0xff; } + if (j < outLen) { out[j++] = accum & 0xff; } + + accum = 0; + } + } + + return buffer; +} + +static char encode6Bit(unsigned x) { + if (x <= 25) { + return 'A' + x; + } else if (x <= 51) { + return 'a' + x - 26; + } else if (x <= 61) { + return '0' + x - 52; + } else if (x == 62) { + return '+'; + } else { + return '/'; + } +} + +void encodeBase64( + const void *_data, size_t size, AString *out) { + out->clear(); + + const uint8_t *data = (const uint8_t *)_data; + + size_t i; + for (i = 0; i < (size / 3) * 3; i += 3) { + uint8_t x1 = data[i]; + uint8_t x2 = data[i + 1]; + uint8_t x3 = data[i + 2]; + + out->append(encode6Bit(x1 >> 2)); + out->append(encode6Bit((x1 << 4 | x2 >> 4) & 0x3f)); + out->append(encode6Bit((x2 << 2 | x3 >> 6) & 0x3f)); + out->append(encode6Bit(x3 & 0x3f)); + } + switch (size % 3) { + case 0: + break; + case 2: + { + uint8_t x1 = data[i]; + uint8_t x2 = data[i + 1]; + out->append(encode6Bit(x1 >> 2)); + out->append(encode6Bit((x1 << 4 | x2 >> 4) & 0x3f)); + out->append(encode6Bit((x2 << 2) & 0x3f)); + out->append('='); + break; + } + default: + { + uint8_t x1 = data[i]; + out->append(encode6Bit(x1 >> 2)); + out->append(encode6Bit((x1 << 4) & 0x3f)); + out->append("=="); + break; + } + } +} + +} // namespace android diff --git a/media/libstagefright/foundation/hexdump.cpp b/media/libstagefright/foundation/hexdump.cpp new file mode 100644 index 0000000..093b587 --- /dev/null +++ b/media/libstagefright/foundation/hexdump.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hexdump.h" + +#include "ADebug.h" +#include "AString.h" + +#include <ctype.h> +#include <stdint.h> +#include <stdio.h> + +namespace android { + +void hexdump(const void *_data, size_t size) { + const uint8_t *data = (const uint8_t *)_data; + + size_t offset = 0; + while (offset < size) { + AString line; + + char tmp[32]; + sprintf(tmp, "%08lx: ", (unsigned long)offset); + + line.append(tmp); + + for (size_t i = 0; i < 16; ++i) { + if (i == 8) { + line.append(' '); + } + if (offset + i >= size) { + line.append(" "); + } else { + sprintf(tmp, "%02x ", data[offset + i]); + line.append(tmp); + } + } + + line.append(' '); + + for (size_t i = 0; i < 16; ++i) { + if (offset + i >= size) { + break; + } + + if (isprint(data[offset + i])) { + line.append((char)data[offset + i]); + } else { + line.append('.'); + } + } + + LOG(INFO) << line; + + offset += 16; + } +} + +} // namespace android + |