Remove RefBase from the extractor API
- Add MetaDataBase base class that MetaData derives from, but which
does not derive from RefBase.
- MediaBuffer::meta_data() now returns a MetaDataBase& rather than an
sp<MetaData>
- Rename MediaSourceBase to MediaTrack.
- MediaSource no longer derives from MediaSourceBase (or MediaTrack)
- MediaTrack::getFormat(), MediaExtractor::getTrackMetaData() and
MediaExtractor::getMetaData() all take a MetaDataBase& parameter that
they fill out, rather than returning a MetaData directly (the
corresponding methods on MediaSource and RemoteMediaExtractor continue
to return MetaData)
Bug: 67908544
Test: CTS MediaPlayerTest, DecoderTest, EncodeDecodeTest, manually record video
Change-Id: Ib531ab309061290be33d40d6100c9a8127e22083
diff --git a/media/libmediaextractor/Android.bp b/media/libmediaextractor/Android.bp
index 79af058..b9b47cd 100644
--- a/media/libmediaextractor/Android.bp
+++ b/media/libmediaextractor/Android.bp
@@ -27,10 +27,12 @@
"MediaBuffer.cpp",
"MediaBufferBase.cpp",
"MediaBufferGroup.cpp",
- "MediaSourceBase.cpp",
"MediaSource.cpp",
+ "MediaTrack.cpp",
"MediaExtractor.cpp",
"MetaData.cpp",
+ "MetaDataBase.cpp",
+ "VorbisComment.cpp",
],
clang: true,
diff --git a/media/libmediaextractor/MediaBuffer.cpp b/media/libmediaextractor/MediaBuffer.cpp
index dac3d50..39f8d6e 100644
--- a/media/libmediaextractor/MediaBuffer.cpp
+++ b/media/libmediaextractor/MediaBuffer.cpp
@@ -145,8 +145,8 @@
mRangeLength = length;
}
-sp<MetaData> MediaBuffer::meta_data() {
- return mMetaData;
+MetaDataBase& MediaBuffer::meta_data() {
+ return *mMetaData;
}
void MediaBuffer::reset() {
@@ -170,6 +170,7 @@
if (mMemory.get() != nullptr) {
getSharedControl()->setDeadObject();
}
+ delete mMetaData;
}
void MediaBuffer::setObserver(MediaBufferObserver *observer) {
@@ -180,7 +181,7 @@
MediaBufferBase *MediaBuffer::clone() {
MediaBuffer *buffer = new MediaBuffer(mData, mSize);
buffer->set_range(mRangeOffset, mRangeLength);
- buffer->mMetaData = new MetaData(*mMetaData.get());
+ buffer->mMetaData = new MetaDataBase(*mMetaData);
add_ref();
buffer->mOriginal = this;
diff --git a/media/libmediaextractor/MediaExtractor.cpp b/media/libmediaextractor/MediaExtractor.cpp
index 2241567..a6b3dc9 100644
--- a/media/libmediaextractor/MediaExtractor.cpp
+++ b/media/libmediaextractor/MediaExtractor.cpp
@@ -35,10 +35,6 @@
MediaExtractor::~MediaExtractor() {}
-sp<MetaData> MediaExtractor::getMetaData() {
- return new MetaData;
-}
-
uint32_t MediaExtractor::flags() const {
return CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_PAUSE | CAN_SEEK;
}
diff --git a/media/libmediaextractor/MediaSourceBase.cpp b/media/libmediaextractor/MediaTrack.cpp
similarity index 69%
rename from media/libmediaextractor/MediaSourceBase.cpp
rename to media/libmediaextractor/MediaTrack.cpp
index 6d45c90..4963f58 100644
--- a/media/libmediaextractor/MediaSourceBase.cpp
+++ b/media/libmediaextractor/MediaTrack.cpp
@@ -14,51 +14,51 @@
* limitations under the License.
*/
-#include <media/MediaSourceBase.h>
+#include <media/MediaTrack.h>
namespace android {
-MediaSourceBase::MediaSourceBase() {}
+MediaTrack::MediaTrack() {}
-MediaSourceBase::~MediaSourceBase() {}
+MediaTrack::~MediaTrack() {}
////////////////////////////////////////////////////////////////////////////////
-MediaSourceBase::ReadOptions::ReadOptions() {
+MediaTrack::ReadOptions::ReadOptions() {
reset();
}
-void MediaSourceBase::ReadOptions::reset() {
+void MediaTrack::ReadOptions::reset() {
mOptions = 0;
mSeekTimeUs = 0;
mNonBlocking = false;
}
-void MediaSourceBase::ReadOptions::setNonBlocking() {
+void MediaTrack::ReadOptions::setNonBlocking() {
mNonBlocking = true;
}
-void MediaSourceBase::ReadOptions::clearNonBlocking() {
+void MediaTrack::ReadOptions::clearNonBlocking() {
mNonBlocking = false;
}
-bool MediaSourceBase::ReadOptions::getNonBlocking() const {
+bool MediaTrack::ReadOptions::getNonBlocking() const {
return mNonBlocking;
}
-void MediaSourceBase::ReadOptions::setSeekTo(int64_t time_us, SeekMode mode) {
+void MediaTrack::ReadOptions::setSeekTo(int64_t time_us, SeekMode mode) {
mOptions |= kSeekTo_Option;
mSeekTimeUs = time_us;
mSeekMode = mode;
}
-void MediaSourceBase::ReadOptions::clearSeekTo() {
+void MediaTrack::ReadOptions::clearSeekTo() {
mOptions &= ~kSeekTo_Option;
mSeekTimeUs = 0;
mSeekMode = SEEK_CLOSEST_SYNC;
}
-bool MediaSourceBase::ReadOptions::getSeekTo(
+bool MediaTrack::ReadOptions::getSeekTo(
int64_t *time_us, SeekMode *mode) const {
*time_us = mSeekTimeUs;
*mode = mSeekMode;
diff --git a/media/libmediaextractor/MetaData.cpp b/media/libmediaextractor/MetaData.cpp
index 69beea1..1d0a607 100644
--- a/media/libmediaextractor/MetaData.cpp
+++ b/media/libmediaextractor/MetaData.cpp
@@ -31,500 +31,20 @@
namespace android {
-struct MetaData::typed_data {
- typed_data();
- ~typed_data();
- typed_data(const MetaData::typed_data &);
- typed_data &operator=(const MetaData::typed_data &);
-
- void clear();
- void setData(uint32_t type, const void *data, size_t size);
- void getData(uint32_t *type, const void **data, size_t *size) const;
- // may include hexdump of binary data if verbose=true
- String8 asString(bool verbose) const;
-
-private:
- uint32_t mType;
- size_t mSize;
-
- union {
- void *ext_data;
- float reservoir;
- } u;
-
- bool usesReservoir() const {
- return mSize <= sizeof(u.reservoir);
- }
-
- void *allocateStorage(size_t size);
- void freeStorage();
-
- void *storage() {
- return usesReservoir() ? &u.reservoir : u.ext_data;
- }
-
- const void *storage() const {
- return usesReservoir() ? &u.reservoir : u.ext_data;
- }
-};
-
-struct MetaData::Rect {
- int32_t mLeft, mTop, mRight, mBottom;
-};
-
-
-struct MetaData::MetaDataInternal {
- KeyedVector<uint32_t, MetaData::typed_data> mItems;
-};
-
-
-MetaData::MetaData()
- : mInternalData(new MetaDataInternal()) {
+MetaData::MetaData() {
}
MetaData::MetaData(const MetaData &from)
- : RefBase(),
- mInternalData(new MetaDataInternal()) {
- mInternalData->mItems = from.mInternalData->mItems;
+ : MetaDataBase(from) {
+}
+MetaData::MetaData(const MetaDataBase &from)
+ : MetaDataBase(from) {
}
MetaData::~MetaData() {
- clear();
- delete mInternalData;
}
-void MetaData::clear() {
- mInternalData->mItems.clear();
-}
-
-bool MetaData::remove(uint32_t key) {
- ssize_t i = mInternalData->mItems.indexOfKey(key);
-
- if (i < 0) {
- return false;
- }
-
- mInternalData->mItems.removeItemsAt(i);
-
- return true;
-}
-
-bool MetaData::setCString(uint32_t key, const char *value) {
- return setData(key, TYPE_C_STRING, value, strlen(value) + 1);
-}
-
-bool MetaData::setInt32(uint32_t key, int32_t value) {
- return setData(key, TYPE_INT32, &value, sizeof(value));
-}
-
-bool MetaData::setInt64(uint32_t key, int64_t value) {
- return setData(key, TYPE_INT64, &value, sizeof(value));
-}
-
-bool MetaData::setFloat(uint32_t key, float value) {
- return setData(key, TYPE_FLOAT, &value, sizeof(value));
-}
-
-bool MetaData::setPointer(uint32_t key, void *value) {
- return setData(key, TYPE_POINTER, &value, sizeof(value));
-}
-
-bool MetaData::setRect(
- uint32_t key,
- int32_t left, int32_t top,
- int32_t right, int32_t bottom) {
- Rect r;
- r.mLeft = left;
- r.mTop = top;
- r.mRight = right;
- r.mBottom = bottom;
-
- return setData(key, TYPE_RECT, &r, sizeof(r));
-}
-
-/**
- * Note that the returned pointer becomes invalid when additional metadata is set.
- */
-bool MetaData::findCString(uint32_t key, const char **value) const {
- uint32_t type;
- const void *data;
- size_t size;
- if (!findData(key, &type, &data, &size) || type != TYPE_C_STRING) {
- return false;
- }
-
- *value = (const char *)data;
-
- return true;
-}
-
-bool MetaData::findInt32(uint32_t key, int32_t *value) const {
- uint32_t type = 0;
- const void *data;
- size_t size;
- if (!findData(key, &type, &data, &size) || type != TYPE_INT32) {
- return false;
- }
-
- CHECK_EQ(size, sizeof(*value));
-
- *value = *(int32_t *)data;
-
- return true;
-}
-
-bool MetaData::findInt64(uint32_t key, int64_t *value) const {
- uint32_t type = 0;
- const void *data;
- size_t size;
- if (!findData(key, &type, &data, &size) || type != TYPE_INT64) {
- return false;
- }
-
- CHECK_EQ(size, sizeof(*value));
-
- *value = *(int64_t *)data;
-
- return true;
-}
-
-bool MetaData::findFloat(uint32_t key, float *value) const {
- uint32_t type = 0;
- const void *data;
- size_t size;
- if (!findData(key, &type, &data, &size) || type != TYPE_FLOAT) {
- return false;
- }
-
- CHECK_EQ(size, sizeof(*value));
-
- *value = *(float *)data;
-
- return true;
-}
-
-bool MetaData::findPointer(uint32_t key, void **value) const {
- uint32_t type = 0;
- const void *data;
- size_t size;
- if (!findData(key, &type, &data, &size) || type != TYPE_POINTER) {
- return false;
- }
-
- CHECK_EQ(size, sizeof(*value));
-
- *value = *(void **)data;
-
- return true;
-}
-
-bool MetaData::findRect(
- uint32_t key,
- int32_t *left, int32_t *top,
- int32_t *right, int32_t *bottom) const {
- uint32_t type = 0;
- const void *data;
- size_t size;
- if (!findData(key, &type, &data, &size) || type != TYPE_RECT) {
- return false;
- }
-
- CHECK_EQ(size, sizeof(Rect));
-
- const Rect *r = (const Rect *)data;
- *left = r->mLeft;
- *top = r->mTop;
- *right = r->mRight;
- *bottom = r->mBottom;
-
- return true;
-}
-
-bool MetaData::setData(
- uint32_t key, uint32_t type, const void *data, size_t size) {
- bool overwrote_existing = true;
-
- ssize_t i = mInternalData->mItems.indexOfKey(key);
- if (i < 0) {
- typed_data item;
- i = mInternalData->mItems.add(key, item);
-
- overwrote_existing = false;
- }
-
- typed_data &item = mInternalData->mItems.editValueAt(i);
-
- item.setData(type, data, size);
-
- return overwrote_existing;
-}
-
-bool MetaData::findData(uint32_t key, uint32_t *type,
- const void **data, size_t *size) const {
- ssize_t i = mInternalData->mItems.indexOfKey(key);
-
- if (i < 0) {
- return false;
- }
-
- const typed_data &item = mInternalData->mItems.valueAt(i);
-
- item.getData(type, data, size);
-
- return true;
-}
-
-bool MetaData::hasData(uint32_t key) const {
- ssize_t i = mInternalData->mItems.indexOfKey(key);
-
- if (i < 0) {
- return false;
- }
-
- return true;
-}
-
-MetaData::typed_data::typed_data()
- : mType(0),
- mSize(0) {
-}
-
-MetaData::typed_data::~typed_data() {
- clear();
-}
-
-MetaData::typed_data::typed_data(const typed_data &from)
- : mType(from.mType),
- mSize(0) {
-
- void *dst = allocateStorage(from.mSize);
- if (dst) {
- memcpy(dst, from.storage(), mSize);
- }
-}
-
-MetaData::typed_data &MetaData::typed_data::operator=(
- const MetaData::typed_data &from) {
- if (this != &from) {
- clear();
- mType = from.mType;
- void *dst = allocateStorage(from.mSize);
- if (dst) {
- memcpy(dst, from.storage(), mSize);
- }
- }
-
- return *this;
-}
-
-void MetaData::typed_data::clear() {
- freeStorage();
-
- mType = 0;
-}
-
-void MetaData::typed_data::setData(
- uint32_t type, const void *data, size_t size) {
- clear();
-
- mType = type;
-
- void *dst = allocateStorage(size);
- if (dst) {
- memcpy(dst, data, size);
- }
-}
-
-void MetaData::typed_data::getData(
- uint32_t *type, const void **data, size_t *size) const {
- *type = mType;
- *size = mSize;
- *data = storage();
-}
-
-void *MetaData::typed_data::allocateStorage(size_t size) {
- mSize = size;
-
- if (usesReservoir()) {
- return &u.reservoir;
- }
-
- u.ext_data = malloc(mSize);
- if (u.ext_data == NULL) {
- ALOGE("Couldn't allocate %zu bytes for item", size);
- mSize = 0;
- }
- return u.ext_data;
-}
-
-void MetaData::typed_data::freeStorage() {
- if (!usesReservoir()) {
- if (u.ext_data) {
- free(u.ext_data);
- u.ext_data = NULL;
- }
- }
-
- mSize = 0;
-}
-
-String8 MetaData::typed_data::asString(bool verbose) const {
- String8 out;
- const void *data = storage();
- switch(mType) {
- case TYPE_NONE:
- out = String8::format("no type, size %zu)", mSize);
- break;
- case TYPE_C_STRING:
- out = String8::format("(char*) %s", (const char *)data);
- break;
- case TYPE_INT32:
- out = String8::format("(int32_t) %d", *(int32_t *)data);
- break;
- case TYPE_INT64:
- out = String8::format("(int64_t) %" PRId64, *(int64_t *)data);
- break;
- case TYPE_FLOAT:
- out = String8::format("(float) %f", *(float *)data);
- break;
- case TYPE_POINTER:
- out = String8::format("(void*) %p", *(void **)data);
- break;
- case TYPE_RECT:
- {
- const Rect *r = (const Rect *)data;
- out = String8::format("Rect(%d, %d, %d, %d)",
- r->mLeft, r->mTop, r->mRight, r->mBottom);
- break;
- }
-
- default:
- out = String8::format("(unknown type %d, size %zu)", mType, mSize);
- if (verbose && mSize <= 48) { // if it's less than three lines of hex data, dump it
- AString foo;
- hexdump(data, mSize, 0, &foo);
- out.append("\n");
- out.append(foo.c_str());
- }
- break;
- }
- return out;
-}
-
-static void MakeFourCCString(uint32_t x, char *s) {
- s[0] = x >> 24;
- s[1] = (x >> 16) & 0xff;
- s[2] = (x >> 8) & 0xff;
- s[3] = x & 0xff;
- s[4] = '\0';
-}
-
-String8 MetaData::toString() const {
- String8 s;
- for (int i = mInternalData->mItems.size(); --i >= 0;) {
- int32_t key = mInternalData->mItems.keyAt(i);
- char cc[5];
- MakeFourCCString(key, cc);
- const typed_data &item = mInternalData->mItems.valueAt(i);
- s.appendFormat("%s: %s", cc, item.asString(false).string());
- if (i != 0) {
- s.append(", ");
- }
- }
- return s;
-}
-void MetaData::dumpToLog() const {
- for (int i = mInternalData->mItems.size(); --i >= 0;) {
- int32_t key = mInternalData->mItems.keyAt(i);
- char cc[5];
- MakeFourCCString(key, cc);
- const typed_data &item = mInternalData->mItems.valueAt(i);
- ALOGI("%s: %s", cc, item.asString(true /* verbose */).string());
- }
-}
-
-status_t MetaData::writeToParcel(Parcel &parcel) {
- status_t ret;
- size_t numItems = mInternalData->mItems.size();
- ret = parcel.writeUint32(uint32_t(numItems));
- if (ret) {
- return ret;
- }
- for (size_t i = 0; i < numItems; i++) {
- int32_t key = mInternalData->mItems.keyAt(i);
- const typed_data &item = mInternalData->mItems.valueAt(i);
- uint32_t type;
- const void *data;
- size_t size;
- item.getData(&type, &data, &size);
- ret = parcel.writeInt32(key);
- if (ret) {
- return ret;
- }
- ret = parcel.writeUint32(type);
- if (ret) {
- return ret;
- }
- if (type == TYPE_NONE) {
- android::Parcel::WritableBlob blob;
- ret = parcel.writeUint32(static_cast<uint32_t>(size));
- if (ret) {
- return ret;
- }
- ret = parcel.writeBlob(size, false, &blob);
- if (ret) {
- return ret;
- }
- memcpy(blob.data(), data, size);
- blob.release();
- } else {
- ret = parcel.writeByteArray(size, (uint8_t*)data);
- if (ret) {
- return ret;
- }
- }
- }
- return OK;
-}
-
-status_t MetaData::updateFromParcel(const Parcel &parcel) {
- uint32_t numItems;
- if (parcel.readUint32(&numItems) == OK) {
-
- for (size_t i = 0; i < numItems; i++) {
- int32_t key;
- uint32_t type;
- uint32_t size;
- status_t ret = parcel.readInt32(&key);
- ret |= parcel.readUint32(&type);
- ret |= parcel.readUint32(&size);
- if (ret != OK) {
- break;
- }
- // copy data from Blob, which may be inline in Parcel storage,
- // then advance position
- if (type == TYPE_NONE) {
- android::Parcel::ReadableBlob blob;
- ret = parcel.readBlob(size, &blob);
- if (ret != OK) {
- break;
- }
- setData(key, type, blob.data(), size);
- blob.release();
- } else {
- // copy data directly from Parcel storage, then advance position
- setData(key, type, parcel.readInplace(size), size);
- }
- }
-
- return OK;
- }
- ALOGW("no metadata in parcel");
- return UNKNOWN_ERROR;
-}
-
-
/* static */
sp<MetaData> MetaData::createFromParcel(const Parcel &parcel) {
@@ -533,7 +53,5 @@
return meta;
}
-
-
} // namespace android
diff --git a/media/libmediaextractor/MetaDataBase.cpp b/media/libmediaextractor/MetaDataBase.cpp
new file mode 100644
index 0000000..bfea6f1
--- /dev/null
+++ b/media/libmediaextractor/MetaDataBase.cpp
@@ -0,0 +1,533 @@
+/*
+ * Copyright (C) 2009 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 "MetaDataBase"
+#include <inttypes.h>
+#include <binder/Parcel.h>
+#include <utils/KeyedVector.h>
+#include <utils/Log.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AString.h>
+#include <media/stagefright/foundation/hexdump.h>
+#include <media/stagefright/MetaDataBase.h>
+
+namespace android {
+
+struct MetaDataBase::typed_data {
+ typed_data();
+ ~typed_data();
+
+ typed_data(const MetaDataBase::typed_data &);
+ typed_data &operator=(const MetaDataBase::typed_data &);
+
+ void clear();
+ void setData(uint32_t type, const void *data, size_t size);
+ void getData(uint32_t *type, const void **data, size_t *size) const;
+ // may include hexdump of binary data if verbose=true
+ String8 asString(bool verbose) const;
+
+private:
+ uint32_t mType;
+ size_t mSize;
+
+ union {
+ void *ext_data;
+ float reservoir;
+ } u;
+
+ bool usesReservoir() const {
+ return mSize <= sizeof(u.reservoir);
+ }
+
+ void *allocateStorage(size_t size);
+ void freeStorage();
+
+ void *storage() {
+ return usesReservoir() ? &u.reservoir : u.ext_data;
+ }
+
+ const void *storage() const {
+ return usesReservoir() ? &u.reservoir : u.ext_data;
+ }
+};
+
+struct MetaDataBase::Rect {
+ int32_t mLeft, mTop, mRight, mBottom;
+};
+
+
+struct MetaDataBase::MetaDataInternal {
+ KeyedVector<uint32_t, MetaDataBase::typed_data> mItems;
+};
+
+
+MetaDataBase::MetaDataBase()
+ : mInternalData(new MetaDataInternal()) {
+}
+
+MetaDataBase::MetaDataBase(const MetaDataBase &from)
+ : mInternalData(new MetaDataInternal()) {
+ mInternalData->mItems = from.mInternalData->mItems;
+}
+
+MetaDataBase& MetaDataBase::operator = (const MetaDataBase &rhs) {
+ this->mInternalData->mItems = rhs.mInternalData->mItems;
+ return *this;
+}
+
+MetaDataBase::~MetaDataBase() {
+ clear();
+ delete mInternalData;
+}
+
+void MetaDataBase::clear() {
+ mInternalData->mItems.clear();
+}
+
+bool MetaDataBase::remove(uint32_t key) {
+ ssize_t i = mInternalData->mItems.indexOfKey(key);
+
+ if (i < 0) {
+ return false;
+ }
+
+ mInternalData->mItems.removeItemsAt(i);
+
+ return true;
+}
+
+bool MetaDataBase::setCString(uint32_t key, const char *value) {
+ return setData(key, TYPE_C_STRING, value, strlen(value) + 1);
+}
+
+bool MetaDataBase::setInt32(uint32_t key, int32_t value) {
+ return setData(key, TYPE_INT32, &value, sizeof(value));
+}
+
+bool MetaDataBase::setInt64(uint32_t key, int64_t value) {
+ return setData(key, TYPE_INT64, &value, sizeof(value));
+}
+
+bool MetaDataBase::setFloat(uint32_t key, float value) {
+ return setData(key, TYPE_FLOAT, &value, sizeof(value));
+}
+
+bool MetaDataBase::setPointer(uint32_t key, void *value) {
+ return setData(key, TYPE_POINTER, &value, sizeof(value));
+}
+
+bool MetaDataBase::setRect(
+ uint32_t key,
+ int32_t left, int32_t top,
+ int32_t right, int32_t bottom) {
+ Rect r;
+ r.mLeft = left;
+ r.mTop = top;
+ r.mRight = right;
+ r.mBottom = bottom;
+
+ return setData(key, TYPE_RECT, &r, sizeof(r));
+}
+
+/**
+ * Note that the returned pointer becomes invalid when additional metadata is set.
+ */
+bool MetaDataBase::findCString(uint32_t key, const char **value) const {
+ uint32_t type;
+ const void *data;
+ size_t size;
+ if (!findData(key, &type, &data, &size) || type != TYPE_C_STRING) {
+ return false;
+ }
+
+ *value = (const char *)data;
+
+ return true;
+}
+
+bool MetaDataBase::findInt32(uint32_t key, int32_t *value) const {
+ uint32_t type = 0;
+ const void *data;
+ size_t size;
+ if (!findData(key, &type, &data, &size) || type != TYPE_INT32) {
+ return false;
+ }
+
+ CHECK_EQ(size, sizeof(*value));
+
+ *value = *(int32_t *)data;
+
+ return true;
+}
+
+bool MetaDataBase::findInt64(uint32_t key, int64_t *value) const {
+ uint32_t type = 0;
+ const void *data;
+ size_t size;
+ if (!findData(key, &type, &data, &size) || type != TYPE_INT64) {
+ return false;
+ }
+
+ CHECK_EQ(size, sizeof(*value));
+
+ *value = *(int64_t *)data;
+
+ return true;
+}
+
+bool MetaDataBase::findFloat(uint32_t key, float *value) const {
+ uint32_t type = 0;
+ const void *data;
+ size_t size;
+ if (!findData(key, &type, &data, &size) || type != TYPE_FLOAT) {
+ return false;
+ }
+
+ CHECK_EQ(size, sizeof(*value));
+
+ *value = *(float *)data;
+
+ return true;
+}
+
+bool MetaDataBase::findPointer(uint32_t key, void **value) const {
+ uint32_t type = 0;
+ const void *data;
+ size_t size;
+ if (!findData(key, &type, &data, &size) || type != TYPE_POINTER) {
+ return false;
+ }
+
+ CHECK_EQ(size, sizeof(*value));
+
+ *value = *(void **)data;
+
+ return true;
+}
+
+bool MetaDataBase::findRect(
+ uint32_t key,
+ int32_t *left, int32_t *top,
+ int32_t *right, int32_t *bottom) const {
+ uint32_t type = 0;
+ const void *data;
+ size_t size;
+ if (!findData(key, &type, &data, &size) || type != TYPE_RECT) {
+ return false;
+ }
+
+ CHECK_EQ(size, sizeof(Rect));
+
+ const Rect *r = (const Rect *)data;
+ *left = r->mLeft;
+ *top = r->mTop;
+ *right = r->mRight;
+ *bottom = r->mBottom;
+
+ return true;
+}
+
+bool MetaDataBase::setData(
+ uint32_t key, uint32_t type, const void *data, size_t size) {
+ bool overwrote_existing = true;
+
+ ssize_t i = mInternalData->mItems.indexOfKey(key);
+ if (i < 0) {
+ typed_data item;
+ i = mInternalData->mItems.add(key, item);
+
+ overwrote_existing = false;
+ }
+
+ typed_data &item = mInternalData->mItems.editValueAt(i);
+
+ item.setData(type, data, size);
+
+ return overwrote_existing;
+}
+
+bool MetaDataBase::findData(uint32_t key, uint32_t *type,
+ const void **data, size_t *size) const {
+ ssize_t i = mInternalData->mItems.indexOfKey(key);
+
+ if (i < 0) {
+ return false;
+ }
+
+ const typed_data &item = mInternalData->mItems.valueAt(i);
+
+ item.getData(type, data, size);
+
+ return true;
+}
+
+bool MetaDataBase::hasData(uint32_t key) const {
+ ssize_t i = mInternalData->mItems.indexOfKey(key);
+
+ if (i < 0) {
+ return false;
+ }
+
+ return true;
+}
+
+MetaDataBase::typed_data::typed_data()
+ : mType(0),
+ mSize(0) {
+}
+
+MetaDataBase::typed_data::~typed_data() {
+ clear();
+}
+
+MetaDataBase::typed_data::typed_data(const typed_data &from)
+ : mType(from.mType),
+ mSize(0) {
+
+ void *dst = allocateStorage(from.mSize);
+ if (dst) {
+ memcpy(dst, from.storage(), mSize);
+ }
+}
+
+MetaDataBase::typed_data &MetaDataBase::typed_data::operator=(
+ const MetaDataBase::typed_data &from) {
+ if (this != &from) {
+ clear();
+ mType = from.mType;
+ void *dst = allocateStorage(from.mSize);
+ if (dst) {
+ memcpy(dst, from.storage(), mSize);
+ }
+ }
+
+ return *this;
+}
+
+void MetaDataBase::typed_data::clear() {
+ freeStorage();
+
+ mType = 0;
+}
+
+void MetaDataBase::typed_data::setData(
+ uint32_t type, const void *data, size_t size) {
+ clear();
+
+ mType = type;
+
+ void *dst = allocateStorage(size);
+ if (dst) {
+ memcpy(dst, data, size);
+ }
+}
+
+void MetaDataBase::typed_data::getData(
+ uint32_t *type, const void **data, size_t *size) const {
+ *type = mType;
+ *size = mSize;
+ *data = storage();
+}
+
+void *MetaDataBase::typed_data::allocateStorage(size_t size) {
+ mSize = size;
+
+ if (usesReservoir()) {
+ return &u.reservoir;
+ }
+
+ u.ext_data = malloc(mSize);
+ if (u.ext_data == NULL) {
+ ALOGE("Couldn't allocate %zu bytes for item", size);
+ mSize = 0;
+ }
+ return u.ext_data;
+}
+
+void MetaDataBase::typed_data::freeStorage() {
+ if (!usesReservoir()) {
+ if (u.ext_data) {
+ free(u.ext_data);
+ u.ext_data = NULL;
+ }
+ }
+
+ mSize = 0;
+}
+
+String8 MetaDataBase::typed_data::asString(bool verbose) const {
+ String8 out;
+ const void *data = storage();
+ switch(mType) {
+ case TYPE_NONE:
+ out = String8::format("no type, size %zu)", mSize);
+ break;
+ case TYPE_C_STRING:
+ out = String8::format("(char*) %s", (const char *)data);
+ break;
+ case TYPE_INT32:
+ out = String8::format("(int32_t) %d", *(int32_t *)data);
+ break;
+ case TYPE_INT64:
+ out = String8::format("(int64_t) %" PRId64, *(int64_t *)data);
+ break;
+ case TYPE_FLOAT:
+ out = String8::format("(float) %f", *(float *)data);
+ break;
+ case TYPE_POINTER:
+ out = String8::format("(void*) %p", *(void **)data);
+ break;
+ case TYPE_RECT:
+ {
+ const Rect *r = (const Rect *)data;
+ out = String8::format("Rect(%d, %d, %d, %d)",
+ r->mLeft, r->mTop, r->mRight, r->mBottom);
+ break;
+ }
+
+ default:
+ out = String8::format("(unknown type %d, size %zu)", mType, mSize);
+ if (verbose && mSize <= 48) { // if it's less than three lines of hex data, dump it
+ AString foo;
+ hexdump(data, mSize, 0, &foo);
+ out.append("\n");
+ out.append(foo.c_str());
+ }
+ break;
+ }
+ return out;
+}
+
+static void MakeFourCCString(uint32_t x, char *s) {
+ s[0] = x >> 24;
+ s[1] = (x >> 16) & 0xff;
+ s[2] = (x >> 8) & 0xff;
+ s[3] = x & 0xff;
+ s[4] = '\0';
+}
+
+String8 MetaDataBase::toString() const {
+ String8 s;
+ for (int i = mInternalData->mItems.size(); --i >= 0;) {
+ int32_t key = mInternalData->mItems.keyAt(i);
+ char cc[5];
+ MakeFourCCString(key, cc);
+ const typed_data &item = mInternalData->mItems.valueAt(i);
+ s.appendFormat("%s: %s", cc, item.asString(false).string());
+ if (i != 0) {
+ s.append(", ");
+ }
+ }
+ return s;
+}
+
+void MetaDataBase::dumpToLog() const {
+ for (int i = mInternalData->mItems.size(); --i >= 0;) {
+ int32_t key = mInternalData->mItems.keyAt(i);
+ char cc[5];
+ MakeFourCCString(key, cc);
+ const typed_data &item = mInternalData->mItems.valueAt(i);
+ ALOGI("%s: %s", cc, item.asString(true /* verbose */).string());
+ }
+}
+
+status_t MetaDataBase::writeToParcel(Parcel &parcel) {
+ status_t ret;
+ size_t numItems = mInternalData->mItems.size();
+ ret = parcel.writeUint32(uint32_t(numItems));
+ if (ret) {
+ return ret;
+ }
+ for (size_t i = 0; i < numItems; i++) {
+ int32_t key = mInternalData->mItems.keyAt(i);
+ const typed_data &item = mInternalData->mItems.valueAt(i);
+ uint32_t type;
+ const void *data;
+ size_t size;
+ item.getData(&type, &data, &size);
+ ret = parcel.writeInt32(key);
+ if (ret) {
+ return ret;
+ }
+ ret = parcel.writeUint32(type);
+ if (ret) {
+ return ret;
+ }
+ if (type == TYPE_NONE) {
+ android::Parcel::WritableBlob blob;
+ ret = parcel.writeUint32(static_cast<uint32_t>(size));
+ if (ret) {
+ return ret;
+ }
+ ret = parcel.writeBlob(size, false, &blob);
+ if (ret) {
+ return ret;
+ }
+ memcpy(blob.data(), data, size);
+ blob.release();
+ } else {
+ ret = parcel.writeByteArray(size, (uint8_t*)data);
+ if (ret) {
+ return ret;
+ }
+ }
+ }
+ return OK;
+}
+
+status_t MetaDataBase::updateFromParcel(const Parcel &parcel) {
+ uint32_t numItems;
+ if (parcel.readUint32(&numItems) == OK) {
+
+ for (size_t i = 0; i < numItems; i++) {
+ int32_t key;
+ uint32_t type;
+ uint32_t size;
+ status_t ret = parcel.readInt32(&key);
+ ret |= parcel.readUint32(&type);
+ ret |= parcel.readUint32(&size);
+ if (ret != OK) {
+ break;
+ }
+ // copy data from Blob, which may be inline in Parcel storage,
+ // then advance position
+ if (type == TYPE_NONE) {
+ android::Parcel::ReadableBlob blob;
+ ret = parcel.readBlob(size, &blob);
+ if (ret != OK) {
+ break;
+ }
+ setData(key, type, blob.data(), size);
+ blob.release();
+ } else {
+ // copy data directly from Parcel storage, then advance position
+ setData(key, type, parcel.readInplace(size), size);
+ }
+ }
+
+ return OK;
+ }
+ ALOGW("no metadata in parcel");
+ return UNKNOWN_ERROR;
+}
+
+} // namespace android
+
diff --git a/media/libmediaextractor/VorbisComment.cpp b/media/libmediaextractor/VorbisComment.cpp
new file mode 100644
index 0000000..fabaf51
--- /dev/null
+++ b/media/libmediaextractor/VorbisComment.cpp
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2018 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 "VorbisComment"
+#include <utils/Log.h>
+
+#include "media/VorbisComment.h"
+
+#include <media/stagefright/foundation/base64.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/AString.h>
+#include <media/stagefright/foundation/ByteUtils.h>
+#include <media/stagefright/MetaDataBase.h>
+
+namespace android {
+
+static void extractAlbumArt(
+ MetaDataBase *fileMeta, const void *data, size_t size) {
+ ALOGV("extractAlbumArt from '%s'", (const char *)data);
+
+ sp<ABuffer> flacBuffer = decodeBase64(AString((const char *)data, size));
+ if (flacBuffer == NULL) {
+ ALOGE("malformed base64 encoded data.");
+ return;
+ }
+
+ size_t flacSize = flacBuffer->size();
+ uint8_t *flac = flacBuffer->data();
+ ALOGV("got flac of size %zu", flacSize);
+
+ uint32_t picType;
+ uint32_t typeLen;
+ uint32_t descLen;
+ uint32_t dataLen;
+ char type[128];
+
+ if (flacSize < 8) {
+ return;
+ }
+
+ picType = U32_AT(flac);
+
+ if (picType != 3) {
+ // This is not a front cover.
+ return;
+ }
+
+ typeLen = U32_AT(&flac[4]);
+ if (typeLen > sizeof(type) - 1) {
+ return;
+ }
+
+ // we've already checked above that flacSize >= 8
+ if (flacSize - 8 < typeLen) {
+ return;
+ }
+
+ memcpy(type, &flac[8], typeLen);
+ type[typeLen] = '\0';
+
+ ALOGV("picType = %d, type = '%s'", picType, type);
+
+ if (!strcmp(type, "-->")) {
+ // This is not inline cover art, but an external url instead.
+ return;
+ }
+
+ if (flacSize < 32 || flacSize - 32 < typeLen) {
+ return;
+ }
+
+ descLen = U32_AT(&flac[8 + typeLen]);
+ if (flacSize - 32 - typeLen < descLen) {
+ return;
+ }
+
+ dataLen = U32_AT(&flac[8 + typeLen + 4 + descLen + 16]);
+
+ // we've already checked above that (flacSize - 32 - typeLen - descLen) >= 0
+ if (flacSize - 32 - typeLen - descLen < dataLen) {
+ return;
+ }
+
+ ALOGV("got image data, %zu trailing bytes",
+ flacSize - 32 - typeLen - descLen - dataLen);
+
+ fileMeta->setData(
+ kKeyAlbumArt, 0, &flac[8 + typeLen + 4 + descLen + 20], dataLen);
+
+ fileMeta->setCString(kKeyAlbumArtMIME, type);
+}
+
+void parseVorbisComment(
+ MetaDataBase *fileMeta, const char *comment, size_t commentLength)
+{
+ struct {
+ const char *const mTag;
+ uint32_t mKey;
+ } kMap[] = {
+ { "TITLE", kKeyTitle },
+ { "ARTIST", kKeyArtist },
+ { "ALBUMARTIST", kKeyAlbumArtist },
+ { "ALBUM ARTIST", kKeyAlbumArtist },
+ { "COMPILATION", kKeyCompilation },
+ { "ALBUM", kKeyAlbum },
+ { "COMPOSER", kKeyComposer },
+ { "GENRE", kKeyGenre },
+ { "AUTHOR", kKeyAuthor },
+ { "TRACKNUMBER", kKeyCDTrackNumber },
+ { "DISCNUMBER", kKeyDiscNumber },
+ { "DATE", kKeyDate },
+ { "YEAR", kKeyYear },
+ { "LYRICIST", kKeyWriter },
+ { "METADATA_BLOCK_PICTURE", kKeyAlbumArt },
+ { "ANDROID_LOOP", kKeyAutoLoop },
+ };
+
+ for (size_t j = 0; j < sizeof(kMap) / sizeof(kMap[0]); ++j) {
+ size_t tagLen = strlen(kMap[j].mTag);
+ if (!strncasecmp(kMap[j].mTag, comment, tagLen)
+ && comment[tagLen] == '=') {
+ if (kMap[j].mKey == kKeyAlbumArt) {
+ extractAlbumArt(
+ fileMeta,
+ &comment[tagLen + 1],
+ commentLength - tagLen - 1);
+ } else if (kMap[j].mKey == kKeyAutoLoop) {
+ if (!strcasecmp(&comment[tagLen + 1], "true")) {
+ fileMeta->setInt32(kKeyAutoLoop, true);
+ }
+ } else {
+ fileMeta->setCString(kMap[j].mKey, &comment[tagLen + 1]);
+ }
+ }
+ }
+
+}
+
+} // namespace android
diff --git a/media/libmediaextractor/include/media/MediaExtractor.h b/media/libmediaextractor/include/media/MediaExtractor.h
index c329903..4ba98da 100644
--- a/media/libmediaextractor/include/media/MediaExtractor.h
+++ b/media/libmediaextractor/include/media/MediaExtractor.h
@@ -28,8 +28,8 @@
namespace android {
class DataSourceBase;
-class MetaData;
-struct MediaSourceBase;
+class MetaDataBase;
+struct MediaTrack;
class ExtractorAllocTracker {
@@ -49,17 +49,18 @@
public:
virtual ~MediaExtractor();
virtual size_t countTracks() = 0;
- virtual MediaSourceBase *getTrack(size_t index) = 0;
+ virtual MediaTrack *getTrack(size_t index) = 0;
enum GetTrackMetaDataFlags {
kIncludeExtensiveMetaData = 1
};
- virtual sp<MetaData> getTrackMetaData(
+ virtual status_t getTrackMetaData(
+ MetaDataBase& meta,
size_t index, uint32_t flags = 0) = 0;
// Return container specific meta-data. The default implementation
// returns an empty metadata object.
- virtual sp<MetaData> getMetaData();
+ virtual status_t getMetaData(MetaDataBase& meta) = 0;
enum Flags {
CAN_SEEK_BACKWARD = 1, // the "seek 10secs back button"
diff --git a/media/libmediaextractor/include/media/MediaSource.h b/media/libmediaextractor/include/media/MediaSource.h
index 45070d6..73c4703 100644
--- a/media/libmediaextractor/include/media/MediaSource.h
+++ b/media/libmediaextractor/include/media/MediaSource.h
@@ -1,4 +1,5 @@
/*
+
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -24,15 +25,71 @@
#include <media/stagefright/MetaData.h>
#include <utils/RefBase.h>
-#include "media/MediaSourceBase.h"
+#include <media/MediaTrack.h>
namespace android {
class MediaBuffer;
-struct MediaSource : public MediaSourceBase, public virtual RefBase {
+struct MediaSource : public virtual RefBase {
MediaSource();
+ // To be called before any other methods on this object, except
+ // getFormat().
+ virtual status_t start(MetaData *params = NULL) = 0;
+
+ // Any blocking read call returns immediately with a result of NO_INIT.
+ // It is an error to call any methods other than start after this call
+ // returns. Any buffers the object may be holding onto at the time of
+ // the stop() call are released.
+ // Also, it is imperative that any buffers output by this object and
+ // held onto by callers be released before a call to stop() !!!
+ virtual status_t stop() = 0;
+
+ // Returns the format of the data output by this media source.
+ virtual sp<MetaData> getFormat() = 0;
+
+ // Options that modify read() behaviour. The default is to
+ // a) not request a seek
+ // b) not be late, i.e. lateness_us = 0
+ typedef MediaTrack::ReadOptions ReadOptions;
+
+ // Returns a new buffer of data. Call blocks until a
+ // buffer is available, an error is encountered of the end of the stream
+ // is reached.
+ // End of stream is signalled by a result of ERROR_END_OF_STREAM.
+ // A result of INFO_FORMAT_CHANGED indicates that the format of this
+ // MediaSource has changed mid-stream, the client can continue reading
+ // but should be prepared for buffers of the new configuration.
+ virtual status_t read(
+ MediaBufferBase **buffer, const ReadOptions *options = NULL) = 0;
+
+ // Causes this source to suspend pulling data from its upstream source
+ // until a subsequent read-with-seek. This is currently not supported
+ // as such by any source. E.g. MediaCodecSource does not suspend its
+ // upstream source, and instead discard upstream data while paused.
+ virtual status_t pause() {
+ return ERROR_UNSUPPORTED;
+ }
+
+ // The consumer of this media source requests the source stops sending
+ // buffers with timestamp larger than or equal to stopTimeUs. stopTimeUs
+ // must be in the same time base as the startTime passed in start(). If
+ // source does not support this request, ERROR_UNSUPPORTED will be returned.
+ // If stopTimeUs is invalid, BAD_VALUE will be returned. This could be
+ // called at any time even before source starts and it could be called
+ // multiple times. Setting stopTimeUs to be -1 will effectively cancel the stopTimeUs
+ // set previously. If stopTimeUs is larger than or equal to last buffer's timestamp,
+ // source will start to drop buffer when it gets a buffer with timestamp larger
+ // than or equal to stopTimeUs. If stopTimeUs is smaller than or equal to last
+ // buffer's timestamp, source will drop all the incoming buffers immediately.
+ // After setting stopTimeUs, source may still stop sending buffers with timestamp
+ // less than stopTimeUs if it is stopped by the consumer.
+ virtual status_t setStopTimeUs(int64_t /* stopTimeUs */) {
+ return ERROR_UNSUPPORTED;
+ }
+
+protected:
virtual ~MediaSource();
private:
diff --git a/media/libmediaextractor/include/media/MediaSourceBase.h b/media/libmediaextractor/include/media/MediaTrack.h
similarity index 65%
rename from media/libmediaextractor/include/media/MediaSourceBase.h
rename to media/libmediaextractor/include/media/MediaTrack.h
index ab56613..adea61a 100644
--- a/media/libmediaextractor/include/media/MediaSourceBase.h
+++ b/media/libmediaextractor/include/media/MediaTrack.h
@@ -42,14 +42,14 @@
}
};
-struct MediaSourceBase
+struct MediaTrack
// : public SourceBaseAllocTracker
{
- MediaSourceBase();
+ MediaTrack();
// To be called before any other methods on this object, except
// getFormat().
- virtual status_t start(MetaData *params = NULL) = 0;
+ virtual status_t start(MetaDataBase *params = NULL) = 0;
// Any blocking read call returns immediately with a result of NO_INIT.
// It is an error to call any methods other than start after this call
@@ -59,8 +59,8 @@
// held onto by callers be released before a call to stop() !!!
virtual status_t stop() = 0;
- // Returns the format of the data output by this media source.
- virtual sp<MetaData> getFormat() = 0;
+ // Returns the format of the data output by this media track.
+ virtual status_t getFormat(MetaDataBase& format) = 0;
// Options that modify read() behaviour. The default is to
// a) not request a seek
@@ -113,36 +113,11 @@
virtual status_t read(
MediaBufferBase **buffer, const ReadOptions *options = NULL) = 0;
- // Causes this source to suspend pulling data from its upstream source
- // until a subsequent read-with-seek. This is currently not supported
- // as such by any source. E.g. MediaCodecSource does not suspend its
- // upstream source, and instead discard upstream data while paused.
- virtual status_t pause() {
- return ERROR_UNSUPPORTED;
- }
-
- // The consumer of this media source requests the source stops sending
- // buffers with timestamp larger than or equal to stopTimeUs. stopTimeUs
- // must be in the same time base as the startTime passed in start(). If
- // source does not support this request, ERROR_UNSUPPORTED will be returned.
- // If stopTimeUs is invalid, BAD_VALUE will be returned. This could be
- // called at any time even before source starts and it could be called
- // multiple times. Setting stopTimeUs to be -1 will effectively cancel the stopTimeUs
- // set previously. If stopTimeUs is larger than or equal to last buffer's timestamp,
- // source will start to drop buffer when it gets a buffer with timestamp larger
- // than or equal to stopTimeUs. If stopTimeUs is smaller than or equal to last
- // buffer's timestamp, source will drop all the incoming buffers immediately.
- // After setting stopTimeUs, source may still stop sending buffers with timestamp
- // less than stopTimeUs if it is stopped by the consumer.
- virtual status_t setStopTimeUs(int64_t /* stopTimeUs */) {
- return ERROR_UNSUPPORTED;
- }
-
- virtual ~MediaSourceBase();
+ virtual ~MediaTrack();
private:
- MediaSourceBase(const MediaSourceBase &);
- MediaSourceBase &operator=(const MediaSourceBase &);
+ MediaTrack(const MediaTrack &);
+ MediaTrack &operator=(const MediaTrack &);
};
} // namespace android
diff --git a/media/libmediaextractor/include/media/VorbisComment.h b/media/libmediaextractor/include/media/VorbisComment.h
new file mode 100644
index 0000000..8ba3295
--- /dev/null
+++ b/media/libmediaextractor/include/media/VorbisComment.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2018 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 VORBIS_COMMENT_H_
+#define VORBIS_COMMENT_H_
+
+namespace android {
+
+class MetaDataBase;
+
+void parseVorbisComment(
+ MetaDataBase *fileMeta, const char *comment, size_t commentLength);
+
+} // namespace android
+
+#endif // VORBIS_COMMENT_H_
diff --git a/media/libmediaextractor/include/media/stagefright/MediaBuffer.h b/media/libmediaextractor/include/media/stagefright/MediaBuffer.h
index 85b4521..f944d51 100644
--- a/media/libmediaextractor/include/media/stagefright/MediaBuffer.h
+++ b/media/libmediaextractor/include/media/stagefright/MediaBuffer.h
@@ -33,7 +33,7 @@
struct ABuffer;
class MediaBuffer;
class MediaBufferObserver;
-class MetaData;
+class MetaDataBase;
class MediaBuffer : public MediaBufferBase {
public:
@@ -73,7 +73,7 @@
virtual void set_range(size_t offset, size_t length);
- virtual sp<MetaData> meta_data();
+ MetaDataBase& meta_data();
// Clears meta data and resets the range to the full extent.
virtual void reset();
@@ -154,7 +154,7 @@
bool mOwnsData;
- sp<MetaData> mMetaData;
+ MetaDataBase* mMetaData;
MediaBuffer *mOriginal;
diff --git a/media/libmediaextractor/include/media/stagefright/MediaBufferBase.h b/media/libmediaextractor/include/media/stagefright/MediaBufferBase.h
index 81dd7d9..6c8d94a 100644
--- a/media/libmediaextractor/include/media/stagefright/MediaBufferBase.h
+++ b/media/libmediaextractor/include/media/stagefright/MediaBufferBase.h
@@ -18,12 +18,10 @@
#define MEDIA_BUFFER_BASE_H_
-#include <utils/RefBase.h>
-
namespace android {
class MediaBufferBase;
-class MetaData;
+class MetaDataBase;
class MediaBufferObserver {
public:
@@ -61,7 +59,7 @@
virtual void set_range(size_t offset, size_t length) = 0;
- virtual sp<MetaData> meta_data() = 0;
+ virtual MetaDataBase& meta_data() = 0;
// Clears meta data and resets the range to the full extent.
virtual void reset() = 0;
diff --git a/media/libmediaextractor/include/media/stagefright/MetaData.h b/media/libmediaextractor/include/media/stagefright/MetaData.h
index 7562a72..f625358 100644
--- a/media/libmediaextractor/include/media/stagefright/MetaData.h
+++ b/media/libmediaextractor/include/media/stagefright/MetaData.h
@@ -24,275 +24,24 @@
#include <utils/RefBase.h>
#include <utils/String8.h>
+#include <media/stagefright/MetaDataBase.h>
namespace android {
-class Parcel;
-
-// The following keys map to int32_t data unless indicated otherwise.
-enum {
- kKeyMIMEType = 'mime', // cstring
- kKeyWidth = 'widt', // int32_t, image pixel
- kKeyHeight = 'heig', // int32_t, image pixel
- kKeyDisplayWidth = 'dWid', // int32_t, display/presentation
- kKeyDisplayHeight = 'dHgt', // int32_t, display/presentation
- kKeySARWidth = 'sarW', // int32_t, sampleAspectRatio width
- kKeySARHeight = 'sarH', // int32_t, sampleAspectRatio height
- kKeyThumbnailWidth = 'thbW', // int32_t, thumbnail width
- kKeyThumbnailHeight = 'thbH', // int32_t, thumbnail height
-
- // a rectangle, if absent assumed to be (0, 0, width - 1, height - 1)
- kKeyCropRect = 'crop',
-
- kKeyRotation = 'rotA', // int32_t (angle in degrees)
- kKeyIFramesInterval = 'ifiv', // int32_t
- kKeyStride = 'strd', // int32_t
- kKeySliceHeight = 'slht', // int32_t
- kKeyChannelCount = '#chn', // int32_t
- kKeyChannelMask = 'chnm', // int32_t
- kKeySampleRate = 'srte', // int32_t (audio sampling rate Hz)
- kKeyPcmEncoding = 'PCMe', // int32_t (audio encoding enum)
- kKeyFrameRate = 'frmR', // int32_t (video frame rate fps)
- kKeyBitRate = 'brte', // int32_t (bps)
- kKeyMaxBitRate = 'mxBr', // int32_t (bps)
- kKeyStreamHeader = 'stHd', // raw data
- kKeyESDS = 'esds', // raw data
- kKeyAACProfile = 'aacp', // int32_t
- kKeyAVCC = 'avcc', // raw data
- kKeyHVCC = 'hvcc', // raw data
- kKeyThumbnailHVCC = 'thvc', // raw data
- kKeyD263 = 'd263', // raw data
- kKeyVorbisInfo = 'vinf', // raw data
- kKeyVorbisBooks = 'vboo', // raw data
- kKeyOpusHeader = 'ohdr', // raw data
- kKeyOpusCodecDelay = 'ocod', // uint64_t (codec delay in ns)
- kKeyOpusSeekPreRoll = 'ospr', // uint64_t (seek preroll in ns)
- kKeyFlacMetadata = 'flMd', // raw data
- kKeyVp9CodecPrivate = 'vp9p', // raw data (vp9 csd information)
- kKeyWantsNALFragments = 'NALf',
- kKeyIsSyncFrame = 'sync', // int32_t (bool)
- kKeyIsCodecConfig = 'conf', // int32_t (bool)
- kKeyTime = 'time', // int64_t (usecs)
- kKeyDecodingTime = 'decT', // int64_t (decoding timestamp in usecs)
- kKeyNTPTime = 'ntpT', // uint64_t (ntp-timestamp)
- kKeyTargetTime = 'tarT', // int64_t (usecs)
- kKeyDriftTime = 'dftT', // int64_t (usecs)
- kKeyAnchorTime = 'ancT', // int64_t (usecs)
- kKeyDuration = 'dura', // int64_t (usecs)
- kKeyPixelFormat = 'pixf', // int32_t
- kKeyColorFormat = 'colf', // int32_t
- kKeyColorSpace = 'cols', // int32_t
- kKeyPlatformPrivate = 'priv', // pointer
- kKeyDecoderComponent = 'decC', // cstring
- kKeyBufferID = 'bfID',
- kKeyMaxInputSize = 'inpS',
- kKeyMaxWidth = 'maxW',
- kKeyMaxHeight = 'maxH',
- kKeyThumbnailTime = 'thbT', // int64_t (usecs)
- kKeyTrackID = 'trID',
- kKeyIsDRM = 'idrm', // int32_t (bool)
- kKeyEncoderDelay = 'encd', // int32_t (frames)
- kKeyEncoderPadding = 'encp', // int32_t (frames)
-
- kKeyAlbum = 'albu', // cstring
- kKeyArtist = 'arti', // cstring
- kKeyAlbumArtist = 'aart', // cstring
- kKeyComposer = 'comp', // cstring
- kKeyGenre = 'genr', // cstring
- kKeyTitle = 'titl', // cstring
- kKeyYear = 'year', // cstring
- kKeyAlbumArt = 'albA', // compressed image data
- kKeyAlbumArtMIME = 'alAM', // cstring
- kKeyAuthor = 'auth', // cstring
- kKeyCDTrackNumber = 'cdtr', // cstring
- kKeyDiscNumber = 'dnum', // cstring
- kKeyDate = 'date', // cstring
- kKeyWriter = 'writ', // cstring
- kKeyCompilation = 'cpil', // cstring
- kKeyLocation = 'loc ', // cstring
- kKeyTimeScale = 'tmsl', // int32_t
- kKeyCaptureFramerate = 'capF', // float (capture fps)
-
- // video profile and level
- kKeyVideoProfile = 'vprf', // int32_t
- kKeyVideoLevel = 'vlev', // int32_t
-
- // Set this key to enable authoring files in 64-bit offset
- kKey64BitFileOffset = 'fobt', // int32_t (bool)
- kKey2ByteNalLength = '2NAL', // int32_t (bool)
-
- // Identify the file output format for authoring
- // Please see <media/mediarecorder.h> for the supported
- // file output formats.
- kKeyFileType = 'ftyp', // int32_t
-
- // Track authoring progress status
- // kKeyTrackTimeStatus is used to track progress in elapsed time
- kKeyTrackTimeStatus = 'tktm', // int64_t
-
- kKeyRealTimeRecording = 'rtrc', // bool (int32_t)
- kKeyNumBuffers = 'nbbf', // int32_t
-
- // Ogg files can be tagged to be automatically looping...
- kKeyAutoLoop = 'autL', // bool (int32_t)
-
- kKeyValidSamples = 'valD', // int32_t
-
- kKeyIsUnreadable = 'unre', // bool (int32_t)
-
- // An indication that a video buffer has been rendered.
- kKeyRendered = 'rend', // bool (int32_t)
-
- // The language code for this media
- kKeyMediaLanguage = 'lang', // cstring
-
- // To store the timed text format data
- kKeyTextFormatData = 'text', // raw data
-
- kKeyIsADTS = 'adts', // bool (int32_t)
- kKeyAACAOT = 'aaot', // int32_t
-
- // If a MediaBuffer's data represents (at least partially) encrypted
- // data, the following fields aid in decryption.
- // The data can be thought of as pairs of plain and encrypted data
- // fragments, i.e. plain and encrypted data alternate.
- // The first fragment is by convention plain data (if that's not the
- // case, simply specify plain fragment size of 0).
- // kKeyEncryptedSizes and kKeyPlainSizes each map to an array of
- // size_t values. The sum total of all size_t values of both arrays
- // must equal the amount of data (i.e. MediaBuffer's range_length()).
- // If both arrays are present, they must be of the same size.
- // If only encrypted sizes are present it is assumed that all
- // plain sizes are 0, i.e. all fragments are encrypted.
- // To programmatically set these array, use the MetaData::setData API, i.e.
- // const size_t encSizes[];
- // meta->setData(
- // kKeyEncryptedSizes, 0 /* type */, encSizes, sizeof(encSizes));
- // A plain sizes array by itself makes no sense.
- kKeyEncryptedSizes = 'encr', // size_t[]
- kKeyPlainSizes = 'plai', // size_t[]
- kKeyCryptoKey = 'cryK', // uint8_t[16]
- kKeyCryptoIV = 'cryI', // uint8_t[16]
- kKeyCryptoMode = 'cryM', // int32_t
-
- kKeyCryptoDefaultIVSize = 'cryS', // int32_t
-
- kKeyPssh = 'pssh', // raw data
- kKeyCASystemID = 'caid', // int32_t
- kKeyCASessionID = 'seid', // raw data
-
- // Please see MediaFormat.KEY_IS_AUTOSELECT.
- kKeyTrackIsAutoselect = 'auto', // bool (int32_t)
- // Please see MediaFormat.KEY_IS_DEFAULT.
- kKeyTrackIsDefault = 'dflt', // bool (int32_t)
- // Similar to MediaFormat.KEY_IS_FORCED_SUBTITLE but pertains to av tracks as well.
- kKeyTrackIsForced = 'frcd', // bool (int32_t)
-
- // H264 supplemental enhancement information offsets/sizes
- kKeySEI = 'sei ', // raw data
-
- // MPEG user data offsets
- kKeyMpegUserData = 'mpud', // size_t[]
-
- // Size of NALU length in mkv/mp4
- kKeyNalLengthSize = 'nals', // int32_t
-
- // HDR related
- kKeyHdrStaticInfo = 'hdrS', // HDRStaticInfo
-
- // color aspects
- kKeyColorRange = 'cRng', // int32_t, color range, value defined by ColorAspects.Range
- kKeyColorPrimaries = 'cPrm', // int32_t,
- // color Primaries, value defined by ColorAspects.Primaries
- kKeyTransferFunction = 'tFun', // int32_t,
- // transfer Function, value defined by ColorAspects.Transfer.
- kKeyColorMatrix = 'cMtx', // int32_t,
- // color Matrix, value defined by ColorAspects.MatrixCoeffs.
- kKeyTemporalLayerId = 'iLyr', // int32_t, temporal layer-id. 0-based (0 => base layer)
- kKeyTemporalLayerCount = 'cLyr', // int32_t, number of temporal layers encoded
-
- kKeyGridWidth = 'grdW', // int32_t, HEIF grid width
- kKeyGridHeight = 'grdH', // int32_t, HEIF grid height
- kKeyGridRows = 'grdR', // int32_t, HEIF grid rows
- kKeyGridCols = 'grdC', // int32_t, HEIF grid columns
- kKeyIccProfile = 'prof', // raw data, ICC prifile data
- kKeyIsPrimaryImage = 'prim', // bool (int32_t), image track is the primary image
- kKeyFrameCount = 'nfrm', // int32_t, total number of frame in video track
-};
-
-enum {
- kTypeESDS = 'esds',
- kTypeAVCC = 'avcc',
- kTypeHVCC = 'hvcc',
- kTypeD263 = 'd263',
-};
-
-class MetaData final : public RefBase {
+class MetaData final : public MetaDataBase, public RefBase {
public:
MetaData();
MetaData(const MetaData &from);
-
- enum Type {
- TYPE_NONE = 'none',
- TYPE_C_STRING = 'cstr',
- TYPE_INT32 = 'in32',
- TYPE_INT64 = 'in64',
- TYPE_FLOAT = 'floa',
- TYPE_POINTER = 'ptr ',
- TYPE_RECT = 'rect',
- };
-
- void clear();
- bool remove(uint32_t key);
-
- bool setCString(uint32_t key, const char *value);
- bool setInt32(uint32_t key, int32_t value);
- bool setInt64(uint32_t key, int64_t value);
- bool setFloat(uint32_t key, float value);
- bool setPointer(uint32_t key, void *value);
-
- bool setRect(
- uint32_t key,
- int32_t left, int32_t top,
- int32_t right, int32_t bottom);
-
- bool findCString(uint32_t key, const char **value) const;
- bool findInt32(uint32_t key, int32_t *value) const;
- bool findInt64(uint32_t key, int64_t *value) const;
- bool findFloat(uint32_t key, float *value) const;
- bool findPointer(uint32_t key, void **value) const;
-
- bool findRect(
- uint32_t key,
- int32_t *left, int32_t *top,
- int32_t *right, int32_t *bottom) const;
-
- bool setData(uint32_t key, uint32_t type, const void *data, size_t size);
-
- bool findData(uint32_t key, uint32_t *type,
- const void **data, size_t *size) const;
-
- bool hasData(uint32_t key) const;
-
- String8 toString() const;
- void dumpToLog() const;
+ MetaData(const MetaDataBase &from);
protected:
virtual ~MetaData();
private:
- friend class BpMediaSource;
friend class BnMediaSource;
+ friend class BpMediaSource;
friend class BpMediaExtractor;
- friend class BnMediaExtractor;
-
- status_t writeToParcel(Parcel &parcel);
- status_t updateFromParcel(const Parcel &parcel);
static sp<MetaData> createFromParcel(const Parcel &parcel);
- struct typed_data;
- struct Rect;
- struct MetaDataInternal;
- MetaDataInternal *mInternalData;
};
} // namespace android
diff --git a/media/libmediaextractor/include/media/stagefright/MetaDataBase.h b/media/libmediaextractor/include/media/stagefright/MetaDataBase.h
new file mode 100644
index 0000000..6010af4
--- /dev/null
+++ b/media/libmediaextractor/include/media/stagefright/MetaDataBase.h
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2009 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 META_DATA_BASE_H_
+
+#define META_DATA_BASE_H_
+
+#include <sys/types.h>
+
+#include <stdint.h>
+
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+
+namespace android {
+
+// The following keys map to int32_t data unless indicated otherwise.
+enum {
+ kKeyMIMEType = 'mime', // cstring
+ kKeyWidth = 'widt', // int32_t, image pixel
+ kKeyHeight = 'heig', // int32_t, image pixel
+ kKeyDisplayWidth = 'dWid', // int32_t, display/presentation
+ kKeyDisplayHeight = 'dHgt', // int32_t, display/presentation
+ kKeySARWidth = 'sarW', // int32_t, sampleAspectRatio width
+ kKeySARHeight = 'sarH', // int32_t, sampleAspectRatio height
+ kKeyThumbnailWidth = 'thbW', // int32_t, thumbnail width
+ kKeyThumbnailHeight = 'thbH', // int32_t, thumbnail height
+
+ // a rectangle, if absent assumed to be (0, 0, width - 1, height - 1)
+ kKeyCropRect = 'crop',
+
+ kKeyRotation = 'rotA', // int32_t (angle in degrees)
+ kKeyIFramesInterval = 'ifiv', // int32_t
+ kKeyStride = 'strd', // int32_t
+ kKeySliceHeight = 'slht', // int32_t
+ kKeyChannelCount = '#chn', // int32_t
+ kKeyChannelMask = 'chnm', // int32_t
+ kKeySampleRate = 'srte', // int32_t (audio sampling rate Hz)
+ kKeyPcmEncoding = 'PCMe', // int32_t (audio encoding enum)
+ kKeyFrameRate = 'frmR', // int32_t (video frame rate fps)
+ kKeyBitRate = 'brte', // int32_t (bps)
+ kKeyMaxBitRate = 'mxBr', // int32_t (bps)
+ kKeyStreamHeader = 'stHd', // raw data
+ kKeyESDS = 'esds', // raw data
+ kKeyAACProfile = 'aacp', // int32_t
+ kKeyAVCC = 'avcc', // raw data
+ kKeyHVCC = 'hvcc', // raw data
+ kKeyThumbnailHVCC = 'thvc', // raw data
+ kKeyD263 = 'd263', // raw data
+ kKeyVorbisInfo = 'vinf', // raw data
+ kKeyVorbisBooks = 'vboo', // raw data
+ kKeyOpusHeader = 'ohdr', // raw data
+ kKeyOpusCodecDelay = 'ocod', // uint64_t (codec delay in ns)
+ kKeyOpusSeekPreRoll = 'ospr', // uint64_t (seek preroll in ns)
+ kKeyFlacMetadata = 'flMd', // raw data
+ kKeyVp9CodecPrivate = 'vp9p', // raw data (vp9 csd information)
+ kKeyWantsNALFragments = 'NALf',
+ kKeyIsSyncFrame = 'sync', // int32_t (bool)
+ kKeyIsCodecConfig = 'conf', // int32_t (bool)
+ kKeyTime = 'time', // int64_t (usecs)
+ kKeyDecodingTime = 'decT', // int64_t (decoding timestamp in usecs)
+ kKeyNTPTime = 'ntpT', // uint64_t (ntp-timestamp)
+ kKeyTargetTime = 'tarT', // int64_t (usecs)
+ kKeyDriftTime = 'dftT', // int64_t (usecs)
+ kKeyAnchorTime = 'ancT', // int64_t (usecs)
+ kKeyDuration = 'dura', // int64_t (usecs)
+ kKeyPixelFormat = 'pixf', // int32_t
+ kKeyColorFormat = 'colf', // int32_t
+ kKeyColorSpace = 'cols', // int32_t
+ kKeyPlatformPrivate = 'priv', // pointer
+ kKeyDecoderComponent = 'decC', // cstring
+ kKeyBufferID = 'bfID',
+ kKeyMaxInputSize = 'inpS',
+ kKeyMaxWidth = 'maxW',
+ kKeyMaxHeight = 'maxH',
+ kKeyThumbnailTime = 'thbT', // int64_t (usecs)
+ kKeyTrackID = 'trID',
+ kKeyIsDRM = 'idrm', // int32_t (bool)
+ kKeyEncoderDelay = 'encd', // int32_t (frames)
+ kKeyEncoderPadding = 'encp', // int32_t (frames)
+
+ kKeyAlbum = 'albu', // cstring
+ kKeyArtist = 'arti', // cstring
+ kKeyAlbumArtist = 'aart', // cstring
+ kKeyComposer = 'comp', // cstring
+ kKeyGenre = 'genr', // cstring
+ kKeyTitle = 'titl', // cstring
+ kKeyYear = 'year', // cstring
+ kKeyAlbumArt = 'albA', // compressed image data
+ kKeyAlbumArtMIME = 'alAM', // cstring
+ kKeyAuthor = 'auth', // cstring
+ kKeyCDTrackNumber = 'cdtr', // cstring
+ kKeyDiscNumber = 'dnum', // cstring
+ kKeyDate = 'date', // cstring
+ kKeyWriter = 'writ', // cstring
+ kKeyCompilation = 'cpil', // cstring
+ kKeyLocation = 'loc ', // cstring
+ kKeyTimeScale = 'tmsl', // int32_t
+ kKeyCaptureFramerate = 'capF', // float (capture fps)
+
+ // video profile and level
+ kKeyVideoProfile = 'vprf', // int32_t
+ kKeyVideoLevel = 'vlev', // int32_t
+
+ // Set this key to enable authoring files in 64-bit offset
+ kKey64BitFileOffset = 'fobt', // int32_t (bool)
+ kKey2ByteNalLength = '2NAL', // int32_t (bool)
+
+ // Identify the file output format for authoring
+ // Please see <media/mediarecorder.h> for the supported
+ // file output formats.
+ kKeyFileType = 'ftyp', // int32_t
+
+ // Track authoring progress status
+ // kKeyTrackTimeStatus is used to track progress in elapsed time
+ kKeyTrackTimeStatus = 'tktm', // int64_t
+
+ kKeyRealTimeRecording = 'rtrc', // bool (int32_t)
+ kKeyNumBuffers = 'nbbf', // int32_t
+
+ // Ogg files can be tagged to be automatically looping...
+ kKeyAutoLoop = 'autL', // bool (int32_t)
+
+ kKeyValidSamples = 'valD', // int32_t
+
+ kKeyIsUnreadable = 'unre', // bool (int32_t)
+
+ // An indication that a video buffer has been rendered.
+ kKeyRendered = 'rend', // bool (int32_t)
+
+ // The language code for this media
+ kKeyMediaLanguage = 'lang', // cstring
+
+ // To store the timed text format data
+ kKeyTextFormatData = 'text', // raw data
+
+ kKeyRequiresSecureBuffers = 'secu', // bool (int32_t)
+
+ kKeyIsADTS = 'adts', // bool (int32_t)
+ kKeyAACAOT = 'aaot', // int32_t
+
+ // If a MediaBuffer's data represents (at least partially) encrypted
+ // data, the following fields aid in decryption.
+ // The data can be thought of as pairs of plain and encrypted data
+ // fragments, i.e. plain and encrypted data alternate.
+ // The first fragment is by convention plain data (if that's not the
+ // case, simply specify plain fragment size of 0).
+ // kKeyEncryptedSizes and kKeyPlainSizes each map to an array of
+ // size_t values. The sum total of all size_t values of both arrays
+ // must equal the amount of data (i.e. MediaBuffer's range_length()).
+ // If both arrays are present, they must be of the same size.
+ // If only encrypted sizes are present it is assumed that all
+ // plain sizes are 0, i.e. all fragments are encrypted.
+ // To programmatically set these array, use the MetaDataBase::setData API, i.e.
+ // const size_t encSizes[];
+ // meta->setData(
+ // kKeyEncryptedSizes, 0 /* type */, encSizes, sizeof(encSizes));
+ // A plain sizes array by itself makes no sense.
+ kKeyEncryptedSizes = 'encr', // size_t[]
+ kKeyPlainSizes = 'plai', // size_t[]
+ kKeyCryptoKey = 'cryK', // uint8_t[16]
+ kKeyCryptoIV = 'cryI', // uint8_t[16]
+ kKeyCryptoMode = 'cryM', // int32_t
+
+ kKeyCryptoDefaultIVSize = 'cryS', // int32_t
+
+ kKeyPssh = 'pssh', // raw data
+ kKeyCASystemID = 'caid', // int32_t
+ kKeyCASessionID = 'seid', // raw data
+
+ // Please see MediaFormat.KEY_IS_AUTOSELECT.
+ kKeyTrackIsAutoselect = 'auto', // bool (int32_t)
+ // Please see MediaFormat.KEY_IS_DEFAULT.
+ kKeyTrackIsDefault = 'dflt', // bool (int32_t)
+ // Similar to MediaFormat.KEY_IS_FORCED_SUBTITLE but pertains to av tracks as well.
+ kKeyTrackIsForced = 'frcd', // bool (int32_t)
+
+ // H264 supplemental enhancement information offsets/sizes
+ kKeySEI = 'sei ', // raw data
+
+ // MPEG user data offsets
+ kKeyMpegUserData = 'mpud', // size_t[]
+
+ // Size of NALU length in mkv/mp4
+ kKeyNalLengthSize = 'nals', // int32_t
+
+ // HDR related
+ kKeyHdrStaticInfo = 'hdrS', // HDRStaticInfo
+
+ // color aspects
+ kKeyColorRange = 'cRng', // int32_t, color range, value defined by ColorAspects.Range
+ kKeyColorPrimaries = 'cPrm', // int32_t,
+ // color Primaries, value defined by ColorAspects.Primaries
+ kKeyTransferFunction = 'tFun', // int32_t,
+ // transfer Function, value defined by ColorAspects.Transfer.
+ kKeyColorMatrix = 'cMtx', // int32_t,
+ // color Matrix, value defined by ColorAspects.MatrixCoeffs.
+ kKeyTemporalLayerId = 'iLyr', // int32_t, temporal layer-id. 0-based (0 => base layer)
+ kKeyTemporalLayerCount = 'cLyr', // int32_t, number of temporal layers encoded
+
+ kKeyGridWidth = 'grdW', // int32_t, HEIF grid width
+ kKeyGridHeight = 'grdH', // int32_t, HEIF grid height
+ kKeyGridRows = 'grdR', // int32_t, HEIF grid rows
+ kKeyGridCols = 'grdC', // int32_t, HEIF grid columns
+ kKeyIccProfile = 'prof', // raw data, ICC prifile data
+ kKeyIsPrimaryImage = 'prim', // bool (int32_t), image track is the primary image
+ kKeyFrameCount = 'nfrm', // int32_t, total number of frame in video track
+};
+
+enum {
+ kTypeESDS = 'esds',
+ kTypeAVCC = 'avcc',
+ kTypeHVCC = 'hvcc',
+ kTypeD263 = 'd263',
+};
+
+class Parcel;
+
+class MetaDataBase {
+public:
+ MetaDataBase();
+ MetaDataBase(const MetaDataBase &from);
+ MetaDataBase& operator = (const MetaDataBase &);
+
+ virtual ~MetaDataBase();
+
+ enum Type {
+ TYPE_NONE = 'none',
+ TYPE_C_STRING = 'cstr',
+ TYPE_INT32 = 'in32',
+ TYPE_INT64 = 'in64',
+ TYPE_FLOAT = 'floa',
+ TYPE_POINTER = 'ptr ',
+ TYPE_RECT = 'rect',
+ };
+
+ void clear();
+ bool remove(uint32_t key);
+
+ bool setCString(uint32_t key, const char *value);
+ bool setInt32(uint32_t key, int32_t value);
+ bool setInt64(uint32_t key, int64_t value);
+ bool setFloat(uint32_t key, float value);
+ bool setPointer(uint32_t key, void *value);
+
+ bool setRect(
+ uint32_t key,
+ int32_t left, int32_t top,
+ int32_t right, int32_t bottom);
+
+ bool findCString(uint32_t key, const char **value) const;
+ bool findInt32(uint32_t key, int32_t *value) const;
+ bool findInt64(uint32_t key, int64_t *value) const;
+ bool findFloat(uint32_t key, float *value) const;
+ bool findPointer(uint32_t key, void **value) const;
+
+ bool findRect(
+ uint32_t key,
+ int32_t *left, int32_t *top,
+ int32_t *right, int32_t *bottom) const;
+
+ bool setData(uint32_t key, uint32_t type, const void *data, size_t size);
+
+ bool findData(uint32_t key, uint32_t *type,
+ const void **data, size_t *size) const;
+
+ bool hasData(uint32_t key) const;
+
+ String8 toString() const;
+ void dumpToLog() const;
+
+private:
+ friend class BpMediaSource;
+ friend class BnMediaSource;
+ friend class BnMediaExtractor;
+ friend class MetaData;
+
+ struct typed_data;
+ struct Rect;
+ struct MetaDataInternal;
+ MetaDataInternal *mInternalData;
+ status_t writeToParcel(Parcel &parcel);
+ status_t updateFromParcel(const Parcel &parcel);
+};
+
+} // namespace android
+
+#endif // META_DATA_H_