diff options
21 files changed, 2036 insertions, 0 deletions
diff --git a/include/media/stagefright/foundation/AAtomizer.h b/include/media/stagefright/foundation/AAtomizer.h new file mode 100644 index 0000000..5f3a678 --- /dev/null +++ b/include/media/stagefright/foundation/AAtomizer.h @@ -0,0 +1,51 @@ +/* + * 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. + */ + +#ifndef A_ATOMIZER_H_ + +#define A_ATOMIZER_H_ + +#include <stdint.h> + +#include <media/stagefright/foundation/ABase.h> +#include <media/stagefright/foundation/AString.h> +#include <utils/List.h> +#include <utils/Vector.h> +#include <utils/threads.h> + +namespace android { + +struct AAtomizer { + static const char *Atomize(const char *name); + +private: + static AAtomizer gAtomizer; + + Mutex mLock; + Vector<List<AString> > mAtoms; + + AAtomizer(); + + const char *atomize(const char *name); + + static uint32_t Hash(const char *s); + + DISALLOW_EVIL_CONSTRUCTORS(AAtomizer); +}; + +} // namespace android + +#endif // A_ATOMIZER_H_ diff --git a/include/media/stagefright/foundation/ABase.h b/include/media/stagefright/foundation/ABase.h new file mode 100644 index 0000000..9eceea3 --- /dev/null +++ b/include/media/stagefright/foundation/ABase.h @@ -0,0 +1,25 @@ +/* + * 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. + */ + +#ifndef A_BASE_H_ + +#define A_BASE_H_ + +#define DISALLOW_EVIL_CONSTRUCTORS(name) \ + name(const name &); \ + name &operator=(const name &) + +#endif // A_BASE_H_ diff --git a/include/media/stagefright/foundation/ABuffer.h b/include/media/stagefright/foundation/ABuffer.h new file mode 100644 index 0000000..28f0aed --- /dev/null +++ b/include/media/stagefright/foundation/ABuffer.h @@ -0,0 +1,71 @@ +/* + * 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. + */ + +#ifndef A_BUFFER_H_ + +#define A_BUFFER_H_ + +#include <sys/types.h> +#include <stdint.h> + +#include <media/stagefright/foundation/ABase.h> +#include <utils/RefBase.h> + +namespace android { + +struct AMessage; + +struct ABuffer : public RefBase { + ABuffer(size_t capacity); + ABuffer(void *data, size_t capacity); + + void setFarewellMessage(const sp<AMessage> msg); + + uint8_t *base() { return (uint8_t *)mData; } + uint8_t *data() { return (uint8_t *)mData + mRangeOffset; } + size_t capacity() const { return mCapacity; } + size_t size() const { return mRangeLength; } + size_t offset() const { return mRangeOffset; } + + void setRange(size_t offset, size_t size); + + void setInt32Data(int32_t data) { mInt32Data = data; } + int32_t int32Data() const { return mInt32Data; } + + sp<AMessage> meta(); + +protected: + virtual ~ABuffer(); + +private: + sp<AMessage> mFarewell; + sp<AMessage> mMeta; + + void *mData; + size_t mCapacity; + size_t mRangeOffset; + size_t mRangeLength; + + int32_t mInt32Data; + + bool mOwnsData; + + DISALLOW_EVIL_CONSTRUCTORS(ABuffer); +}; + +} // namespace android + +#endif // A_BUFFER_H_ diff --git a/include/media/stagefright/foundation/ADebug.h b/include/media/stagefright/foundation/ADebug.h new file mode 100644 index 0000000..0f986a0 --- /dev/null +++ b/include/media/stagefright/foundation/ADebug.h @@ -0,0 +1,105 @@ +/* + * 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. + */ + +#ifndef A_DEBUG_H_ + +#define A_DEBUG_H_ + +#include <string.h> + +#include <media/stagefright/foundation/ABase.h> +#include <media/stagefright/foundation/AString.h> + +namespace android { + +enum LogType { + VERBOSE, + INFO, + WARNING, + ERROR, + FATAL, +}; + +struct Logger { + Logger(LogType type); + virtual ~Logger(); + + template<class T> Logger &operator<<(const T &x) { + mMessage.append(x); + + return *this; + } + +private: + android::AString mMessage; + LogType mLogType; + + DISALLOW_EVIL_CONSTRUCTORS(Logger); +}; + +const char *LeafName(const char *s); + +#undef LOG +#define LOG(type) Logger(type) << LeafName(__FILE__) << ":" << __LINE__ << " " + +#define CHECK(condition) \ + do { \ + if (!(condition)) { \ + LOG(FATAL) << "CHECK(" #condition ") failed."; \ + } \ + } while (false) + +#define MAKE_COMPARATOR(suffix,op) \ + template<class A, class B> \ + AString Compare_##suffix(const A &a, const B &b) { \ + AString res; \ + if (!(a op b)) { \ + res.append(a); \ + res.append(" vs. "); \ + res.append(b); \ + } \ + return res; \ + } + +MAKE_COMPARATOR(EQ,==) +MAKE_COMPARATOR(NE,!=) +MAKE_COMPARATOR(LE,<=) +MAKE_COMPARATOR(GE,>=) +MAKE_COMPARATOR(LT,<) +MAKE_COMPARATOR(GT,>) + +#define CHECK_OP(x,y,suffix,op) \ + do { \ + AString ___res = Compare_##suffix(x, y); \ + if (!___res.empty()) { \ + LOG(FATAL) << "CHECK_" #suffix "(" #x "," #y ") failed: " \ + << ___res; \ + } \ + } while (false) + +#define CHECK_EQ(x,y) CHECK_OP(x,y,EQ,==) +#define CHECK_NE(x,y) CHECK_OP(x,y,NE,!=) +#define CHECK_LE(x,y) CHECK_OP(x,y,LE,<=) +#define CHECK_LT(x,y) CHECK_OP(x,y,LT,<) +#define CHECK_GE(x,y) CHECK_OP(x,y,GE,>=) +#define CHECK_GT(x,y) CHECK_OP(x,y,GT,>) + +#define TRESPASS() LOG(FATAL) << "Should not be here." + +} // namespace android + +#endif // A_DEBUG_H_ + diff --git a/include/media/stagefright/foundation/AHandler.h b/include/media/stagefright/foundation/AHandler.h new file mode 100644 index 0000000..9fccead --- /dev/null +++ b/include/media/stagefright/foundation/AHandler.h @@ -0,0 +1,54 @@ +/* + * 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. + */ + +#ifndef A_HANDLER_H_ + +#define A_HANDLER_H_ + +#include <media/stagefright/foundation/ALooper.h> +#include <utils/RefBase.h> + +namespace android { + +struct AMessage; + +struct AHandler : public RefBase { + AHandler() + : mID(0) { + } + + ALooper::handler_id id() const { + return mID; + } + +protected: + virtual void onMessageReceived(const sp<AMessage> &msg) = 0; + +private: + friend struct ALooperRoster; + + ALooper::handler_id mID; + + void setID(ALooper::handler_id id) { + mID = id; + } + + DISALLOW_EVIL_CONSTRUCTORS(AHandler); +}; + +} // namespace android + +#endif // A_HANDLER_H_ diff --git a/include/media/stagefright/foundation/ALooper.h b/include/media/stagefright/foundation/ALooper.h new file mode 100644 index 0000000..69ad837 --- /dev/null +++ b/include/media/stagefright/foundation/ALooper.h @@ -0,0 +1,75 @@ +/* + * 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. + */ + +#ifndef A_LOOPER_H_ + +#define A_LOOPER_H_ + +#include <media/stagefright/foundation/ABase.h> +#include <utils/Errors.h> +#include <utils/KeyedVector.h> +#include <utils/List.h> +#include <utils/RefBase.h> +#include <utils/threads.h> + +namespace android { + +struct AHandler; +struct AMessage; + +struct ALooper : public RefBase { + typedef int32_t event_id; + typedef int32_t handler_id; + + ALooper(); + + handler_id registerHandler(const sp<AHandler> &handler); + void unregisterHandler(handler_id handlerID); + + status_t start(bool runOnCallingThread = false); + status_t stop(); + + static int64_t GetNowUs(); + +protected: + virtual ~ALooper(); + +private: + friend struct ALooperRoster; + + struct Event { + int64_t mWhenUs; + sp<AMessage> mMessage; + }; + + Mutex mLock; + Condition mQueueChangedCondition; + + List<Event> mEventQueue; + + struct LooperThread; + sp<LooperThread> mThread; + bool mRunningLocally; + + void post(const sp<AMessage> &msg, int64_t delayUs); + bool loop(); + + DISALLOW_EVIL_CONSTRUCTORS(ALooper); +}; + +} // namespace android + +#endif // A_LOOPER_H_ diff --git a/include/media/stagefright/foundation/ALooperRoster.h b/include/media/stagefright/foundation/ALooperRoster.h new file mode 100644 index 0000000..1c6869c --- /dev/null +++ b/include/media/stagefright/foundation/ALooperRoster.h @@ -0,0 +1,52 @@ +/* + * 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. + */ + +#ifndef A_LOOPER_ROSTER_H_ + +#define A_LOOPER_ROSTER_H_ + +#include <media/stagefright/foundation/ALooper.h> +#include <utils/KeyedVector.h> + +namespace android { + +struct ALooperRoster { + ALooperRoster(); + + ALooper::handler_id registerHandler( + const sp<ALooper> looper, const sp<AHandler> &handler); + + void unregisterHandler(ALooper::handler_id handlerID); + + void postMessage(const sp<AMessage> &msg, int64_t delayUs = 0); + void deliverMessage(const sp<AMessage> &msg); + +private: + struct HandlerInfo { + sp<ALooper> mLooper; + sp<AHandler> mHandler; + }; + + Mutex mLock; + KeyedVector<ALooper::handler_id, HandlerInfo> mHandlers; + ALooper::handler_id mNextHandlerID; + + DISALLOW_EVIL_CONSTRUCTORS(ALooperRoster); +}; + +} // namespace android + +#endif // A_LOOPER_ROSTER_H_ diff --git a/include/media/stagefright/foundation/AMessage.h b/include/media/stagefright/foundation/AMessage.h new file mode 100644 index 0000000..139c620 --- /dev/null +++ b/include/media/stagefright/foundation/AMessage.h @@ -0,0 +1,113 @@ +/* + * 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. + */ + +#ifndef A_MESSAGE_H_ + +#define A_MESSAGE_H_ + +#include <media/stagefright/foundation/ABase.h> +#include <media/stagefright/foundation/ALooper.h> +#include <utils/KeyedVector.h> +#include <utils/RefBase.h> + +namespace android { + +struct AString; + +struct AMessage : public RefBase { + AMessage(uint32_t what = 0, ALooper::handler_id target = 0); + + void setWhat(uint32_t what); + uint32_t what() const; + + void setTarget(ALooper::handler_id target); + ALooper::handler_id target() const; + + void setInt32(const char *name, int32_t value); + void setInt64(const char *name, int64_t value); + void setSize(const char *name, size_t value); + void setFloat(const char *name, float value); + void setDouble(const char *name, double value); + void setPointer(const char *name, void *value); + void setString(const char *name, const char *s, ssize_t len = -1); + void setObject(const char *name, const sp<RefBase> &obj); + void setMessage(const char *name, const sp<AMessage> &obj); + + bool findInt32(const char *name, int32_t *value) const; + bool findInt64(const char *name, int64_t *value) const; + bool findSize(const char *name, size_t *value) const; + bool findFloat(const char *name, float *value) const; + bool findDouble(const char *name, double *value) const; + bool findPointer(const char *name, void **value) const; + bool findString(const char *name, AString *value) const; + bool findObject(const char *name, sp<RefBase> *obj) const; + bool findMessage(const char *name, sp<AMessage> *obj) const; + + void post(int64_t delayUs = 0); + + sp<AMessage> dup() const; + +protected: + virtual ~AMessage(); + +private: + enum Type { + kTypeInt32, + kTypeInt64, + kTypeSize, + kTypeFloat, + kTypeDouble, + kTypePointer, + kTypeString, + kTypeObject, + kTypeMessage, + }; + + uint32_t mWhat; + ALooper::handler_id mTarget; + + struct Item { + union { + int32_t int32Value; + int64_t int64Value; + size_t sizeValue; + float floatValue; + double doubleValue; + void *ptrValue; + RefBase *refValue; + AString *stringValue; + } u; + const char *mName; + Type mType; + }; + + enum { + kMaxNumItems = 16 + }; + Item mItems[kMaxNumItems]; + size_t mNumItems; + + void clear(); + Item *allocateItem(const char *name); + void freeItem(Item *item); + const Item *findItem(const char *name, Type type) const; + + DISALLOW_EVIL_CONSTRUCTORS(AMessage); +}; + +} // namespace android + +#endif // A_MESSAGE_H_ diff --git a/include/media/stagefright/foundation/AString.h b/include/media/stagefright/foundation/AString.h new file mode 100644 index 0000000..55ade64 --- /dev/null +++ b/include/media/stagefright/foundation/AString.h @@ -0,0 +1,94 @@ +/* + * 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. + */ + +#ifndef A_STRING_H_ + +#define A_STRING_H_ + +#include <sys/types.h> + +namespace android { + +struct AString { + AString(); + AString(const char *s); + AString(const char *s, size_t size); + AString(const AString &from); + AString(const AString &from, size_t offset, size_t n); + ~AString(); + + AString &operator=(const AString &from); + void setTo(const char *s); + void setTo(const char *s, size_t size); + void setTo(const AString &from, size_t offset, size_t n); + + size_t size() const; + const char *c_str() const; + + bool empty() const; + + void clear(); + void trim(); + void erase(size_t start, size_t n); + + void append(char c) { append(&c, 1); } + void append(const char *s); + void append(const char *s, size_t size); + void append(const AString &from); + void append(const AString &from, size_t offset, size_t n); + void append(int x); + void append(unsigned x); + void append(long x); + void append(unsigned long x); + void append(long long x); + void append(unsigned long long x); + void append(float x); + void append(double x); + void append(void *x); + + void insert(const AString &from, size_t insertionPos); + void insert(const char *from, size_t size, size_t insertionPos); + + ssize_t find(const char *substring, size_t start = 0) const; + + size_t hash() const; + + bool operator==(const AString &other) const; + bool operator<(const AString &other) const; + bool operator>(const AString &other) const; + + int compare(const AString &other) const; + + bool startsWith(const char *prefix) const; + + void tolower(); + +private: + static const char *kEmptyString; + + char *mData; + size_t mSize; + size_t mAllocSize; + + void makeMutable(); +}; + +AString StringPrintf(const char *format, ...); + +} // namespace android + +#endif // A_STRING_H_ + diff --git a/include/media/stagefright/foundation/base64.h b/include/media/stagefright/foundation/base64.h new file mode 100644 index 0000000..e340b89 --- /dev/null +++ b/include/media/stagefright/foundation/base64.h @@ -0,0 +1,33 @@ +/* + * 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. + */ + +#ifndef BASE_64_H_ + +#define BASE_64_H_ + +#include <utils/RefBase.h> + +namespace android { + +struct ABuffer; +struct AString; + +sp<ABuffer> decodeBase64(const AString &s); +void encodeBase64(const void *data, size_t size, AString *out); + +} // namespace android + +#endif // BASE_64_H_ diff --git a/include/media/stagefright/foundation/hexdump.h b/include/media/stagefright/foundation/hexdump.h new file mode 100644 index 0000000..f6083a9 --- /dev/null +++ b/include/media/stagefright/foundation/hexdump.h @@ -0,0 +1,29 @@ +/* + * 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. + */ + +#ifndef HEXDUMP_H_ + +#define HEXDUMP_H_ + +#include <sys/types.h> + +namespace android { + +void hexdump(const void *_data, size_t size); + +} // namespace android + +#endif // HEXDUMP_H_ 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 + |