summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorAndreas Huber <andih@google.com>2010-06-07 10:18:57 -0700
committerAndreas Huber <andih@google.com>2010-06-07 10:22:07 -0700
commit72961230a5890071bcca436eb5630172ce84ec41 (patch)
treea699be99c292a92bda91f7eca5671a5817488447 /media
parentcbbf27f76b4798cbd91feb70d7555dac0cbf85cb (diff)
downloadframeworks_av-72961230a5890071bcca436eb5630172ce84ec41.zip
frameworks_av-72961230a5890071bcca436eb5630172ce84ec41.tar.gz
frameworks_av-72961230a5890071bcca436eb5630172ce84ec41.tar.bz2
Initial checkin of "foundation" library for future stagefright development.
Change-Id: I11714dcaa647d0437a13e4c5b953b35e712da8f3
Diffstat (limited to 'media')
-rw-r--r--media/libstagefright/foundation/AAtomizer.cpp67
-rw-r--r--media/libstagefright/foundation/ABuffer.cpp76
-rw-r--r--media/libstagefright/foundation/ADebug.cpp76
-rw-r--r--media/libstagefright/foundation/ALooper.cpp196
-rw-r--r--media/libstagefright/foundation/ALooperRoster.cpp100
-rw-r--r--media/libstagefright/foundation/AMessage.cpp241
-rw-r--r--media/libstagefright/foundation/AString.cpp331
-rw-r--r--media/libstagefright/foundation/Android.mk35
-rw-r--r--media/libstagefright/foundation/base64.cpp139
-rw-r--r--media/libstagefright/foundation/hexdump.cpp73
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
+