Loading media/extractors/mp4/ItemTable.cpp +111 −16 Original line number Diff line number Diff line Loading @@ -76,9 +76,14 @@ struct ImageItem { Vector<uint32_t> thumbnails; Vector<uint32_t> dimgRefs; Vector<uint32_t> cdscRefs; size_t nextTileIndex; }; struct ExifItem { off64_t offset; size_t size; }; ///////////////////////////////////////////////////////////////////// // Loading Loading @@ -473,7 +478,9 @@ struct ItemReference : public Box, public RefBase { uint32_t itemId() { return mItemId; } void apply(KeyedVector<uint32_t, ImageItem> &itemIdToItemMap) const; void apply( KeyedVector<uint32_t, ImageItem> &itemIdToItemMap, KeyedVector<uint32_t, ExifItem> &itemIdToExifMap) const; private: uint32_t mItemId; Loading @@ -483,7 +490,13 @@ private: DISALLOW_EVIL_CONSTRUCTORS(ItemReference); }; void ItemReference::apply(KeyedVector<uint32_t, ImageItem> &itemIdToItemMap) const { void ItemReference::apply( KeyedVector<uint32_t, ImageItem> &itemIdToItemMap, KeyedVector<uint32_t, ExifItem> &itemIdToExifMap) const { ALOGV("attach reference type 0x%x to item id %d)", type(), mItemId); switch(type()) { case FOURCC('d', 'i', 'm', 'g'): { ssize_t itemIndex = itemIdToItemMap.indexOfKey(mItemId); // ignore non-image items Loading @@ -491,9 +504,6 @@ void ItemReference::apply(KeyedVector<uint32_t, ImageItem> &itemIdToItemMap) con return; } ALOGV("attach reference type 0x%x to item id %d)", type(), mItemId); if (type() == FOURCC('d', 'i', 'm', 'g')) { ImageItem &derivedImage = itemIdToItemMap.editValueAt(itemIndex); if (!derivedImage.dimgRefs.empty()) { ALOGW("dimgRefs if not clean!"); Loading @@ -512,7 +522,16 @@ void ItemReference::apply(KeyedVector<uint32_t, ImageItem> &itemIdToItemMap) con // mark the source image of the derivation as hidden sourceImage.hidden = true; } } else if (type() == FOURCC('t', 'h', 'm', 'b')) { break; } case FOURCC('t', 'h', 'm', 'b'): { ssize_t itemIndex = itemIdToItemMap.indexOfKey(mItemId); // ignore non-image items if (itemIndex < 0) { return; } // mark thumbnail image as hidden, these can be retrieved if the client // request thumbnail explicitly, but won't be exposed as displayables. ImageItem &thumbImage = itemIdToItemMap.editValueAt(itemIndex); Loading @@ -532,11 +551,43 @@ void ItemReference::apply(KeyedVector<uint32_t, ImageItem> &itemIdToItemMap) con } masterImage.thumbnails.push_back(mItemId); } } else if (type() == FOURCC('a', 'u', 'x', 'l')) { break; } case FOURCC('c', 'd', 's', 'c'): { ssize_t itemIndex = itemIdToExifMap.indexOfKey(mItemId); // ignore non-exif block items if (itemIndex < 0) { return; } for (size_t i = 0; i < mRefs.size(); i++) { itemIndex = itemIdToItemMap.indexOfKey(mRefs[i]); // ignore non-image items if (itemIndex < 0) { continue; } ALOGV("Image item id %d uses metadata item id %d", mRefs[i], mItemId); ImageItem &image = itemIdToItemMap.editValueAt(itemIndex); image.cdscRefs.push_back(mItemId); } break; } case FOURCC('a', 'u', 'x', 'l'): { ssize_t itemIndex = itemIdToItemMap.indexOfKey(mItemId); // ignore non-image items if (itemIndex < 0) { return; } // mark auxiliary image as hidden ImageItem &auxImage = itemIdToItemMap.editValueAt(itemIndex); auxImage.hidden = true; } else { break; } default: ALOGW("ignoring unsupported ref type 0x%x", type()); } } Loading Loading @@ -1299,10 +1350,13 @@ status_t ItemTable::buildImageItemsIfPossible(uint32_t type) { for (size_t i = 0; i < mItemInfos.size(); i++) { const ItemInfo &info = mItemInfos[i]; // ignore non-image items // Only handle 3 types of items, all others are ignored: // 'grid': derived image from tiles // 'hvc1': coded image (or tile) // 'Exif': EXIF metadata if (info.itemType != FOURCC('g', 'r', 'i', 'd') && info.itemType != FOURCC('h', 'v', 'c', '1')) { info.itemType != FOURCC('h', 'v', 'c', '1') && info.itemType != FOURCC('E', 'x', 'i', 'f')) { continue; } Loading @@ -1325,6 +1379,19 @@ status_t ItemTable::buildImageItemsIfPossible(uint32_t type) { return ERROR_MALFORMED; } if (info.itemType == FOURCC('E', 'x', 'i', 'f')) { // Only add if the Exif data is non-empty. The first 4 bytes contain // the offset to TIFF header, which the Exif parser doesn't use. if (size > 4) { ExifItem exifItem = { .offset = offset, .size = size, }; mItemIdToExifMap.add(info.itemId, exifItem); } continue; } ImageItem image(info.itemType, info.itemId, info.hidden); ALOGV("adding %s: itemId %d", image.isGrid() ? "grid" : "image", info.itemId); Loading Loading @@ -1354,7 +1421,7 @@ status_t ItemTable::buildImageItemsIfPossible(uint32_t type) { } for (size_t i = 0; i < mItemReferences.size(); i++) { mItemReferences[i]->apply(mItemIdToItemMap); mItemReferences[i]->apply(mItemIdToItemMap, mItemIdToExifMap); } bool foundPrimary = false; Loading Loading @@ -1574,6 +1641,34 @@ status_t ItemTable::getImageOffsetAndSize( return OK; } status_t ItemTable::getExifOffsetAndSize(off64_t *offset, size_t *size) { if (!mImageItemsValid) { return INVALID_OPERATION; } ssize_t itemIndex = mItemIdToItemMap.indexOfKey(mPrimaryItemId); // this should not happen, something's seriously wrong. if (itemIndex < 0) { return INVALID_OPERATION; } const ImageItem &image = mItemIdToItemMap[itemIndex]; if (image.cdscRefs.size() == 0) { return NAME_NOT_FOUND; } ssize_t exifIndex = mItemIdToExifMap.indexOfKey(image.cdscRefs[0]); if (exifIndex < 0) { return NAME_NOT_FOUND; } // skip the first 4-byte of the offset to TIFF header *offset = mItemIdToExifMap[exifIndex].offset + 4; *size = mItemIdToExifMap[exifIndex].size - 4; return OK; } } // namespace heif } // namespace android media/extractors/mp4/ItemTable.h +3 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ namespace heif { struct AssociationEntry; struct ImageItem; struct ExifItem; struct ItemLoc; struct ItemInfo; struct ItemProperty; Loading @@ -55,6 +56,7 @@ public: status_t findThumbnailItem(const uint32_t imageIndex, uint32_t *itemIndex); status_t getImageOffsetAndSize( uint32_t *itemIndex, off64_t *offset, size_t *size); status_t getExifOffsetAndSize(off64_t *offset, size_t *size); protected: ~ItemTable(); Loading @@ -78,6 +80,7 @@ private: bool mImageItemsValid; uint32_t mCurrentItemIndex; KeyedVector<uint32_t, ImageItem> mItemIdToItemMap; KeyedVector<uint32_t, ExifItem> mItemIdToExifMap; Vector<uint32_t> mDisplayables; status_t parseIlocBox(off64_t offset, size_t size); Loading media/extractors/mp4/MPEG4Extractor.cpp +7 −0 Original line number Diff line number Diff line Loading @@ -586,6 +586,12 @@ status_t MPEG4Extractor::readMetaData() { } if (mIsHeif && (mItemTable != NULL) && (mItemTable->countImages() > 0)) { off64_t exifOffset; size_t exifSize; if (mItemTable->getExifOffsetAndSize(&exifOffset, &exifSize) == OK) { mFileMetaData.setInt64(kKeyExifOffset, (int64_t)exifOffset); mFileMetaData.setInt64(kKeyExifSize, (int64_t)exifSize); } for (uint32_t imageIndex = 0; imageIndex < mItemTable->countImages(); imageIndex++) { sp<MetaData> meta = mItemTable->getImageMeta(imageIndex); Loading @@ -601,6 +607,7 @@ status_t MPEG4Extractor::readMetaData() { ALOGW("Extracting still images only"); err = OK; } mInitCheck = OK; ALOGV("adding HEIF image track %u", imageIndex); Track *track = new Track; Loading media/libmediaextractor/include/media/stagefright/MetaDataBase.h +2 −0 Original line number Diff line number Diff line Loading @@ -218,6 +218,8 @@ enum { kKeyIccProfile = 'prof', // raw data, ICC profile data kKeyIsPrimaryImage = 'prim', // bool (int32_t), image track is the primary image kKeyFrameCount = 'nfrm', // int32_t, total number of frame in video track kKeyExifOffset = 'exof', // int64_t, Exif data offset kKeyExifSize = 'exsz', // int64_t, Exif data size }; enum { Loading media/libstagefright/NuMediaExtractor.cpp +20 −0 Original line number Diff line number Diff line Loading @@ -307,6 +307,26 @@ status_t NuMediaExtractor::getFileFormat(sp<AMessage> *format) const { return OK; } status_t NuMediaExtractor::getExifOffsetSize(off64_t *offset, size_t *size) const { Mutex::Autolock autoLock(mLock); if (mImpl == NULL) { return -EINVAL; } sp<MetaData> meta = mImpl->getMetaData(); int64_t exifOffset, exifSize; if (meta->findInt64(kKeyExifOffset, &exifOffset) && meta->findInt64(kKeyExifSize, &exifSize)) { *offset = (off64_t) exifOffset; *size = (size_t) exifSize; return OK; } return ERROR_UNSUPPORTED; } status_t NuMediaExtractor::selectTrack(size_t index, int64_t startTimeUs, MediaSource::ReadOptions::SeekMode mode) { Mutex::Autolock autoLock(mLock); Loading Loading
media/extractors/mp4/ItemTable.cpp +111 −16 Original line number Diff line number Diff line Loading @@ -76,9 +76,14 @@ struct ImageItem { Vector<uint32_t> thumbnails; Vector<uint32_t> dimgRefs; Vector<uint32_t> cdscRefs; size_t nextTileIndex; }; struct ExifItem { off64_t offset; size_t size; }; ///////////////////////////////////////////////////////////////////// // Loading Loading @@ -473,7 +478,9 @@ struct ItemReference : public Box, public RefBase { uint32_t itemId() { return mItemId; } void apply(KeyedVector<uint32_t, ImageItem> &itemIdToItemMap) const; void apply( KeyedVector<uint32_t, ImageItem> &itemIdToItemMap, KeyedVector<uint32_t, ExifItem> &itemIdToExifMap) const; private: uint32_t mItemId; Loading @@ -483,7 +490,13 @@ private: DISALLOW_EVIL_CONSTRUCTORS(ItemReference); }; void ItemReference::apply(KeyedVector<uint32_t, ImageItem> &itemIdToItemMap) const { void ItemReference::apply( KeyedVector<uint32_t, ImageItem> &itemIdToItemMap, KeyedVector<uint32_t, ExifItem> &itemIdToExifMap) const { ALOGV("attach reference type 0x%x to item id %d)", type(), mItemId); switch(type()) { case FOURCC('d', 'i', 'm', 'g'): { ssize_t itemIndex = itemIdToItemMap.indexOfKey(mItemId); // ignore non-image items Loading @@ -491,9 +504,6 @@ void ItemReference::apply(KeyedVector<uint32_t, ImageItem> &itemIdToItemMap) con return; } ALOGV("attach reference type 0x%x to item id %d)", type(), mItemId); if (type() == FOURCC('d', 'i', 'm', 'g')) { ImageItem &derivedImage = itemIdToItemMap.editValueAt(itemIndex); if (!derivedImage.dimgRefs.empty()) { ALOGW("dimgRefs if not clean!"); Loading @@ -512,7 +522,16 @@ void ItemReference::apply(KeyedVector<uint32_t, ImageItem> &itemIdToItemMap) con // mark the source image of the derivation as hidden sourceImage.hidden = true; } } else if (type() == FOURCC('t', 'h', 'm', 'b')) { break; } case FOURCC('t', 'h', 'm', 'b'): { ssize_t itemIndex = itemIdToItemMap.indexOfKey(mItemId); // ignore non-image items if (itemIndex < 0) { return; } // mark thumbnail image as hidden, these can be retrieved if the client // request thumbnail explicitly, but won't be exposed as displayables. ImageItem &thumbImage = itemIdToItemMap.editValueAt(itemIndex); Loading @@ -532,11 +551,43 @@ void ItemReference::apply(KeyedVector<uint32_t, ImageItem> &itemIdToItemMap) con } masterImage.thumbnails.push_back(mItemId); } } else if (type() == FOURCC('a', 'u', 'x', 'l')) { break; } case FOURCC('c', 'd', 's', 'c'): { ssize_t itemIndex = itemIdToExifMap.indexOfKey(mItemId); // ignore non-exif block items if (itemIndex < 0) { return; } for (size_t i = 0; i < mRefs.size(); i++) { itemIndex = itemIdToItemMap.indexOfKey(mRefs[i]); // ignore non-image items if (itemIndex < 0) { continue; } ALOGV("Image item id %d uses metadata item id %d", mRefs[i], mItemId); ImageItem &image = itemIdToItemMap.editValueAt(itemIndex); image.cdscRefs.push_back(mItemId); } break; } case FOURCC('a', 'u', 'x', 'l'): { ssize_t itemIndex = itemIdToItemMap.indexOfKey(mItemId); // ignore non-image items if (itemIndex < 0) { return; } // mark auxiliary image as hidden ImageItem &auxImage = itemIdToItemMap.editValueAt(itemIndex); auxImage.hidden = true; } else { break; } default: ALOGW("ignoring unsupported ref type 0x%x", type()); } } Loading Loading @@ -1299,10 +1350,13 @@ status_t ItemTable::buildImageItemsIfPossible(uint32_t type) { for (size_t i = 0; i < mItemInfos.size(); i++) { const ItemInfo &info = mItemInfos[i]; // ignore non-image items // Only handle 3 types of items, all others are ignored: // 'grid': derived image from tiles // 'hvc1': coded image (or tile) // 'Exif': EXIF metadata if (info.itemType != FOURCC('g', 'r', 'i', 'd') && info.itemType != FOURCC('h', 'v', 'c', '1')) { info.itemType != FOURCC('h', 'v', 'c', '1') && info.itemType != FOURCC('E', 'x', 'i', 'f')) { continue; } Loading @@ -1325,6 +1379,19 @@ status_t ItemTable::buildImageItemsIfPossible(uint32_t type) { return ERROR_MALFORMED; } if (info.itemType == FOURCC('E', 'x', 'i', 'f')) { // Only add if the Exif data is non-empty. The first 4 bytes contain // the offset to TIFF header, which the Exif parser doesn't use. if (size > 4) { ExifItem exifItem = { .offset = offset, .size = size, }; mItemIdToExifMap.add(info.itemId, exifItem); } continue; } ImageItem image(info.itemType, info.itemId, info.hidden); ALOGV("adding %s: itemId %d", image.isGrid() ? "grid" : "image", info.itemId); Loading Loading @@ -1354,7 +1421,7 @@ status_t ItemTable::buildImageItemsIfPossible(uint32_t type) { } for (size_t i = 0; i < mItemReferences.size(); i++) { mItemReferences[i]->apply(mItemIdToItemMap); mItemReferences[i]->apply(mItemIdToItemMap, mItemIdToExifMap); } bool foundPrimary = false; Loading Loading @@ -1574,6 +1641,34 @@ status_t ItemTable::getImageOffsetAndSize( return OK; } status_t ItemTable::getExifOffsetAndSize(off64_t *offset, size_t *size) { if (!mImageItemsValid) { return INVALID_OPERATION; } ssize_t itemIndex = mItemIdToItemMap.indexOfKey(mPrimaryItemId); // this should not happen, something's seriously wrong. if (itemIndex < 0) { return INVALID_OPERATION; } const ImageItem &image = mItemIdToItemMap[itemIndex]; if (image.cdscRefs.size() == 0) { return NAME_NOT_FOUND; } ssize_t exifIndex = mItemIdToExifMap.indexOfKey(image.cdscRefs[0]); if (exifIndex < 0) { return NAME_NOT_FOUND; } // skip the first 4-byte of the offset to TIFF header *offset = mItemIdToExifMap[exifIndex].offset + 4; *size = mItemIdToExifMap[exifIndex].size - 4; return OK; } } // namespace heif } // namespace android
media/extractors/mp4/ItemTable.h +3 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ namespace heif { struct AssociationEntry; struct ImageItem; struct ExifItem; struct ItemLoc; struct ItemInfo; struct ItemProperty; Loading @@ -55,6 +56,7 @@ public: status_t findThumbnailItem(const uint32_t imageIndex, uint32_t *itemIndex); status_t getImageOffsetAndSize( uint32_t *itemIndex, off64_t *offset, size_t *size); status_t getExifOffsetAndSize(off64_t *offset, size_t *size); protected: ~ItemTable(); Loading @@ -78,6 +80,7 @@ private: bool mImageItemsValid; uint32_t mCurrentItemIndex; KeyedVector<uint32_t, ImageItem> mItemIdToItemMap; KeyedVector<uint32_t, ExifItem> mItemIdToExifMap; Vector<uint32_t> mDisplayables; status_t parseIlocBox(off64_t offset, size_t size); Loading
media/extractors/mp4/MPEG4Extractor.cpp +7 −0 Original line number Diff line number Diff line Loading @@ -586,6 +586,12 @@ status_t MPEG4Extractor::readMetaData() { } if (mIsHeif && (mItemTable != NULL) && (mItemTable->countImages() > 0)) { off64_t exifOffset; size_t exifSize; if (mItemTable->getExifOffsetAndSize(&exifOffset, &exifSize) == OK) { mFileMetaData.setInt64(kKeyExifOffset, (int64_t)exifOffset); mFileMetaData.setInt64(kKeyExifSize, (int64_t)exifSize); } for (uint32_t imageIndex = 0; imageIndex < mItemTable->countImages(); imageIndex++) { sp<MetaData> meta = mItemTable->getImageMeta(imageIndex); Loading @@ -601,6 +607,7 @@ status_t MPEG4Extractor::readMetaData() { ALOGW("Extracting still images only"); err = OK; } mInitCheck = OK; ALOGV("adding HEIF image track %u", imageIndex); Track *track = new Track; Loading
media/libmediaextractor/include/media/stagefright/MetaDataBase.h +2 −0 Original line number Diff line number Diff line Loading @@ -218,6 +218,8 @@ enum { kKeyIccProfile = 'prof', // raw data, ICC profile data kKeyIsPrimaryImage = 'prim', // bool (int32_t), image track is the primary image kKeyFrameCount = 'nfrm', // int32_t, total number of frame in video track kKeyExifOffset = 'exof', // int64_t, Exif data offset kKeyExifSize = 'exsz', // int64_t, Exif data size }; enum { Loading
media/libstagefright/NuMediaExtractor.cpp +20 −0 Original line number Diff line number Diff line Loading @@ -307,6 +307,26 @@ status_t NuMediaExtractor::getFileFormat(sp<AMessage> *format) const { return OK; } status_t NuMediaExtractor::getExifOffsetSize(off64_t *offset, size_t *size) const { Mutex::Autolock autoLock(mLock); if (mImpl == NULL) { return -EINVAL; } sp<MetaData> meta = mImpl->getMetaData(); int64_t exifOffset, exifSize; if (meta->findInt64(kKeyExifOffset, &exifOffset) && meta->findInt64(kKeyExifSize, &exifSize)) { *offset = (off64_t) exifOffset; *size = (size_t) exifSize; return OK; } return ERROR_UNSUPPORTED; } status_t NuMediaExtractor::selectTrack(size_t index, int64_t startTimeUs, MediaSource::ReadOptions::SeekMode mode) { Mutex::Autolock autoLock(mLock); Loading