Skip to content

Instantly share code, notes, and snippets.

@invisiblek
Created December 6, 2016 19:21
Show Gist options
  • Save invisiblek/6ac5e56cebe7db75fbfd183c9a814600 to your computer and use it in GitHub Desktop.
Save invisiblek/6ac5e56cebe7db75fbfd183c9a814600 to your computer and use it in GitHub Desktop.
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index 7c50638..090ca51 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -283,6 +283,14 @@ public:
TYPE_RECT = 'rect',
};
+ static const size_t kSharedMemThreshold = 10 * 1024;
+
+ enum ParcelAllocationType {
+ NULL_ALLOCATION,
+ SHARED_ALLOCATION,
+ INLINE_ALLOCATION
+ };
+
void clear();
bool remove(uint32_t key);
diff --git a/media/libstagefright/foundation/MetaData.cpp b/media/libstagefright/foundation/MetaData.cpp
index d9d614c..8cc9d22 100644
--- a/media/libstagefright/foundation/MetaData.cpp
+++ b/media/libstagefright/foundation/MetaData.cpp
@@ -22,6 +22,10 @@
#include <stdlib.h>
#include <string.h>
+#include <binder/MemoryBase.h>
+#include <binder/MemoryHeapBase.h>
+#include <binder/IPCThreadState.h>
+
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AString.h>
#include <media/stagefright/foundation/hexdump.h>
@@ -392,7 +396,7 @@ void MetaData::dumpToLog() const {
}
status_t MetaData::writeToParcel(Parcel &parcel) {
- status_t ret;
+ status_t ret, status = OK;
size_t numItems = mItems.size();
ret = parcel.writeUint32(uint32_t(numItems));
if (ret) {
@@ -426,16 +430,50 @@ status_t MetaData::writeToParcel(Parcel &parcel) {
memcpy(blob.data(), data, size);
blob.release();
} else {
- ret = parcel.writeByteArray(size, (uint8_t*)data);
- if (ret) {
- return ret;
+ if (size < SIZE_MAX && size >= kSharedMemThreshold) {
+ sp<MemoryHeapBase> heap =
+ new MemoryHeapBase(size, 0, "Metadata::writeToParcel");
+ if (heap == NULL) {
+ ALOGE("cannot create HeapBase for shared allocation");
+ status = UNKNOWN_ERROR;
+ break;
+ }
+ sp<IMemory> mem = new MemoryBase(heap, 0, size);
+ if (mem == NULL || mem->pointer() == NULL) {
+ ALOGE("cannot create MemoryBase for shared allocation");
+ status = UNKNOWN_ERROR;
+ break;
+ }
+ ret = parcel.writeInt32(SHARED_ALLOCATION);
+ if (ret) {
+ return ret;
+ }
+ ret = parcel.writeUint32(size);
+ if (ret) {
+ return ret;
+ }
+ memcpy(mem->pointer(), data, size);
+ ret = parcel.writeStrongBinder(IInterface::asBinder(mem));
+ if (ret) {
+ return ret;
+ }
+ } else {
+ ret = parcel.writeInt32(INLINE_ALLOCATION);
+ if (ret) {
+ return ret;
+ }
+ ret = parcel.writeByteArray(size, (uint8_t*)data);
+ if (ret) {
+ return ret;
+ }
}
}
}
- return ret;
+ return status;
}
status_t MetaData::updateFromParcel(const Parcel &parcel) {
+ status_t status = OK;
uint32_t numItems;
if (parcel.readUint32(&numItems) == OK) {
@@ -443,8 +481,10 @@ status_t MetaData::updateFromParcel(const Parcel &parcel) {
int32_t key;
uint32_t type;
uint32_t size;
+ int32_t allocationType;
status_t ret = parcel.readInt32(&key);
ret |= parcel.readUint32(&type);
+ ret |= parcel.readInt32(&allocationType);
ret |= parcel.readUint32(&size);
if (ret != OK) {
break;
@@ -460,12 +500,27 @@ status_t MetaData::updateFromParcel(const Parcel &parcel) {
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);
+ if (allocationType == SHARED_ALLOCATION) {
+ sp<IBinder> binder = parcel.readStrongBinder();
+ sp<IMemory> mem = interface_cast<IMemory>(binder);
+ if (mem == NULL || mem->pointer() == NULL) {
+ ALOGE("received NULL IMemory for shared allocation");
+ status = UNKNOWN_ERROR;
+ break;
+ }
+ setData(key, type, mem->pointer(), size);
+ } else if (allocationType == INLINE_ALLOCATION) {
+ // copy data directly from Parcel storage, then advance position
+ setData(key, type, parcel.readInplace(size), size);
+ } else {
+ ALOGE("unknown allocation");
+ status = UNKNOWN_ERROR;
+ break;
+ }
}
- }
+ }
- return OK;
+ return status;
}
ALOGW("no metadata in parcel");
return UNKNOWN_ERROR;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment