Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3692acbf authored by Chong Zhang's avatar Chong Zhang Committed by android-build-merger
Browse files

Merge "heif: report Exif offset and size in file meta" into pi-dev am: f334e17d

am: e516986d

Change-Id: If8801d697233e30763073ef3ff0de504c65e9df6
parents 5e6bd002 e516986d
Loading
Loading
Loading
Loading
+111 −16
Original line number Diff line number Diff line
@@ -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;
};

/////////////////////////////////////////////////////////////////////
//
@@ -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;
@@ -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
@@ -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!");
@@ -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);
@@ -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());
    }
}
@@ -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;
        }

@@ -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);
@@ -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;
@@ -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
+3 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ namespace heif {

struct AssociationEntry;
struct ImageItem;
struct ExifItem;
struct ItemLoc;
struct ItemInfo;
struct ItemProperty;
@@ -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();
@@ -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);
+7 −0
Original line number Diff line number Diff line
@@ -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);
@@ -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;
+2 −0
Original line number Diff line number Diff line
@@ -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 {
+20 −0
Original line number Diff line number Diff line
@@ -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