1b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang/* 2b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang * Copyright (C) 2017 The Android Open Source Project 3b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang * 4b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang * Licensed under the Apache License, Version 2.0 (the "License"); 5b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang * you may not use this file except in compliance with the License. 6b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang * You may obtain a copy of the License at 7b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang * 8b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang * http://www.apache.org/licenses/LICENSE-2.0 9b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang * 10b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang * Unless required by applicable law or agreed to in writing, software 11b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang * distributed under the License is distributed on an "AS IS" BASIS, 12b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang * See the License for the specific language governing permissions and 14b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang * limitations under the License. 15b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang */ 16b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 17b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang//#define LOG_NDEBUG 0 18ee079fe295c41f89c2ac6316e99ee10847fb78fdChong Zhang#define LOG_TAG "ItemTable" 19b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 2075226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen#include <ItemTable.h> 212a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen#include <media/DataSourceBase.h> 22b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang#include <media/stagefright/MetaData.h> 23b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang#include <media/stagefright/MediaErrors.h> 24b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang#include <media/stagefright/foundation/ABuffer.h> 25607612858f3afad1ade51a098aafa2a41523b5f7Dongwon Kang#include <media/stagefright/foundation/ByteUtils.h> 26b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang#include <media/stagefright/foundation/hexdump.h> 27e7a8a637a019d67983bdc858ba5e879431619d5aDongwon Kang#include <media/stagefright/foundation/MediaDefs.h> 28b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang#include <utils/Log.h> 29b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 30b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangnamespace android { 31b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 32b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangnamespace heif { 33b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 34b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang///////////////////////////////////////////////////////////////////// 35b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang// 36b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang// struct to keep track of one image item 37b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang// 38b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 39b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstruct ImageItem { 40b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang friend struct ItemReference; 41b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang friend struct ItemProperty; 42b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 43d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang ImageItem() : ImageItem(0, 0, false) {} 44d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang ImageItem(uint32_t _type, uint32_t _id, bool _hidden) : 45d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang type(_type), itemId(_id), hidden(_hidden), 46b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang rows(0), columns(0), width(0), height(0), rotation(0), 47b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang offset(0), size(0), nextTileIndex(0) {} 48b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 49b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang bool isGrid() const { 50b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return type == FOURCC('g', 'r', 'i', 'd'); 51b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 52b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 53b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t getNextTileItemId(uint32_t *nextTileItemId, bool reset) { 54b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (reset) { 55b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang nextTileIndex = 0; 56b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 57b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (nextTileIndex >= dimgRefs.size()) { 58b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_END_OF_STREAM; 59b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 60b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang *nextTileItemId = dimgRefs[nextTileIndex++]; 61b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return OK; 62b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 63b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 64b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint32_t type; 65d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang uint32_t itemId; 66d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang bool hidden; 67b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang int32_t rows; 68b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang int32_t columns; 69b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang int32_t width; 70b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang int32_t height; 71b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang int32_t rotation; 72b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang off64_t offset; 73b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang size_t size; 74b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang sp<ABuffer> hvcc; 75b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang sp<ABuffer> icc; 76b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 77b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang Vector<uint32_t> thumbnails; 78b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang Vector<uint32_t> dimgRefs; 7901a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang Vector<uint32_t> cdscRefs; 80b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang size_t nextTileIndex; 81b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang}; 82b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 8301a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhangstruct ExifItem { 8401a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang off64_t offset; 8501a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang size_t size; 8601a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang}; 87b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 88b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang///////////////////////////////////////////////////////////////////// 89b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang// 90b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang// ISO boxes 91b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang// 92b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 93b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstruct Box { 94b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangprotected: 952a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen Box(DataSourceBase *source, uint32_t type) : 96b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang mDataSource(source), mType(type) {} 97b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 98b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang virtual ~Box() {} 99b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 100b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang virtual status_t onChunkData( 101b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint32_t /*type*/, off64_t /*offset*/, size_t /*size*/) { 102b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return OK; 103b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 104b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 105b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang inline uint32_t type() const { return mType; } 106b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1072a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen inline DataSourceBase *source() const { return mDataSource; } 108b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 109b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t parseChunk(off64_t *offset); 110b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 111b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t parseChunks(off64_t offset, size_t size); 112b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 113b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangprivate: 1142a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen DataSourceBase *mDataSource; 115b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint32_t mType; 116b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang}; 117b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 118b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstatus_t Box::parseChunk(off64_t *offset) { 119b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (*offset < 0) { 120b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGE("b/23540914"); 121b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_MALFORMED; 122b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 123b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint32_t hdr[2]; 124b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (mDataSource->readAt(*offset, hdr, 8) < 8) { 125b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_IO; 126b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 127b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint64_t chunk_size = ntohl(hdr[0]); 128b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang int32_t chunk_type = ntohl(hdr[1]); 129b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang off64_t data_offset = *offset + 8; 130b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 131b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (chunk_size == 1) { 132b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) { 133b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_IO; 134b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 135b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang chunk_size = ntoh64(chunk_size); 136b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang data_offset += 8; 137b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 138b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (chunk_size < 16) { 139b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang // The smallest valid chunk is 16 bytes long in this case. 140b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_MALFORMED; 141b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 142b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } else if (chunk_size == 0) { 143b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang // This shouldn't happen since we should never be top level 144b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGE("invalid chunk size 0 for non-top level box"); 145b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_MALFORMED; 146b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } else if (chunk_size < 8) { 147b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang // The smallest valid chunk is 8 bytes long. 148b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGE("invalid chunk size: %lld", (long long)chunk_size); 149b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_MALFORMED; 150b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 151b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 152b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang char chunk[5]; 153b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang MakeFourCCString(chunk_type, chunk); 154b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("chunk: %s @ %lld", chunk, (long long)*offset); 155b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 156b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang off64_t chunk_data_size = chunk_size - (data_offset - *offset); 157b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (chunk_data_size < 0) { 158b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGE("b/23540914"); 159b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_MALFORMED; 160b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 161b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 162b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t err = onChunkData(chunk_type, data_offset, chunk_data_size); 163b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 164b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (err != OK) { 165b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return err; 166b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 167b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang *offset += chunk_size; 168b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return OK; 169b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang} 170b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 171b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstatus_t Box::parseChunks(off64_t offset, size_t size) { 172b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang off64_t stopOffset = offset + size; 173b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang while (offset < stopOffset) { 174b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t err = parseChunk(&offset); 175b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (err != OK) { 176b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return err; 177b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 178b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 179b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (offset != stopOffset) { 180b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_MALFORMED; 181b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 182b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return OK; 183b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang} 184b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 185b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang/////////////////////////////////////////////////////////////////////// 186b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 187b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstruct FullBox : public Box { 188b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangprotected: 1892a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen FullBox(DataSourceBase *source, uint32_t type) : 190b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang Box(source, type), mVersion(0), mFlags(0) {} 191b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 192b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang inline uint8_t version() const { return mVersion; } 193b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 194b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang inline uint32_t flags() const { return mFlags; } 195b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 196b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t parseFullBoxHeader(off64_t *offset, size_t *size); 197b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 198b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangprivate: 199b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint8_t mVersion; 200b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint32_t mFlags; 201b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang}; 202b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 203b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstatus_t FullBox::parseFullBoxHeader(off64_t *offset, size_t *size) { 204b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (*size < 4) { 205b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_MALFORMED; 206b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 207b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (!source()->readAt(*offset, &mVersion, 1)) { 208b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_IO; 209b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 210b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (!source()->getUInt24(*offset + 1, &mFlags)) { 211b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_IO; 212b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 213b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang *offset += 4; 214b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang *size -= 4; 215b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return OK; 216b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang} 217b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 218b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang///////////////////////////////////////////////////////////////////// 219b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang// 220b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang// PrimaryImage box 221b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang// 222b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 223b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstruct PitmBox : public FullBox { 2242a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen PitmBox(DataSourceBase *source) : 225b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang FullBox(source, FOURCC('p', 'i', 't', 'm')) {} 226b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 227b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t parse(off64_t offset, size_t size, uint32_t *primaryItemId); 228b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang}; 229b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 230b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstatus_t PitmBox::parse(off64_t offset, size_t size, uint32_t *primaryItemId) { 231b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t err = parseFullBoxHeader(&offset, &size); 232b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (err != OK) { 233b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return err; 234b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 235b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 236b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang size_t itemIdSize = (version() == 0) ? 2 : 4; 237b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (size < itemIdSize) { 238b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_MALFORMED; 239b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 240b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint32_t itemId; 241b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (!source()->getUInt32Var(offset, &itemId, itemIdSize)) { 242b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_IO; 243b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 244b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 245b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("primary id %d", itemId); 246b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang *primaryItemId = itemId; 247b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 248b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return OK; 249b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang} 250b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 251b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang///////////////////////////////////////////////////////////////////// 252b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang// 253b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang// ItemLocation related boxes 254b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang// 255b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 256b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstruct ExtentEntry { 257b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint64_t extentIndex; 258b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint64_t extentOffset; 259b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint64_t extentLength; 260b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang}; 261b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 262b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstruct ItemLoc { 263b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ItemLoc() : ItemLoc(0, 0, 0, 0) {} 264b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ItemLoc(uint32_t item_id, uint16_t construction_method, 265b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint16_t data_reference_index, uint64_t base_offset) : 266b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang itemId(item_id), 267b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang constructionMethod(construction_method), 268b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang dataReferenceIndex(data_reference_index), 269b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang baseOffset(base_offset) {} 270b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 271b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang void addExtent(const ExtentEntry& extent) { 272b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang extents.push_back(extent); 273b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 274b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 275b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t getLoc(off64_t *offset, size_t *size, 276b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang off64_t idatOffset, size_t idatSize) const { 277b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang // TODO: fix extent handling, fix constructionMethod = 2 278b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang CHECK(extents.size() == 1); 279b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (constructionMethod == 0) { 280b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang *offset = baseOffset + extents[0].extentOffset; 281b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang *size = extents[0].extentLength; 282b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return OK; 283b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } else if (constructionMethod == 1) { 284b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (baseOffset + extents[0].extentOffset + extents[0].extentLength 285b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang > idatSize) { 286b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_MALFORMED; 287b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 288b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang *offset = baseOffset + extents[0].extentOffset + idatOffset; 289b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang *size = extents[0].extentLength; 290b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return OK; 291b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 292b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_UNSUPPORTED; 293b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 294b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 295b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang // parsed info 296b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint32_t itemId; 297b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint16_t constructionMethod; 298b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint16_t dataReferenceIndex; 299b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang off64_t baseOffset; 300b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang Vector<ExtentEntry> extents; 301b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang}; 302b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 303b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstruct IlocBox : public FullBox { 3042a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen IlocBox(DataSourceBase *source, KeyedVector<uint32_t, ItemLoc> *itemLocs) : 305b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang FullBox(source, FOURCC('i', 'l', 'o', 'c')), 306b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang mItemLocs(itemLocs), mHasConstructMethod1(false) {} 307b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 308b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t parse(off64_t offset, size_t size); 309b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 310b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang bool hasConstructMethod1() { return mHasConstructMethod1; } 311b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 312b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangprivate: 313b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang static bool isSizeFieldValid(uint32_t offset_size) { 314b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return offset_size == 0 || offset_size == 4 || offset_size == 8; 315b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 316b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang KeyedVector<uint32_t, ItemLoc> *mItemLocs; 317b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang bool mHasConstructMethod1; 318b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang}; 319b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 320b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstatus_t IlocBox::parse(off64_t offset, size_t size) { 321b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t err = parseFullBoxHeader(&offset, &size); 322b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (err != OK) { 323b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return err; 324b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 325b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (version() > 2) { 326b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGE("%s: invalid version %d", __FUNCTION__, version()); 327b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_MALFORMED; 328b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 329b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 330b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (size < 2) { 331b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_MALFORMED; 332b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 333b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint8_t offset_size; 334b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (!source()->readAt(offset++, &offset_size, 1)) { 335b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_IO; 336b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 337b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint8_t length_size = (offset_size & 0xF); 338b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang offset_size >>= 4; 339b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 340b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint8_t base_offset_size; 341b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (!source()->readAt(offset++, &base_offset_size, 1)) { 342b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_IO; 343b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 344b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint8_t index_size = 0; 345b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (version() == 1 || version() == 2) { 346b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang index_size = (base_offset_size & 0xF); 347b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 348b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang base_offset_size >>= 4; 349b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang size -= 2; 350b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 351b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (!isSizeFieldValid(offset_size) 352b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang || !isSizeFieldValid(length_size) 353b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang || !isSizeFieldValid(base_offset_size) 354b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang || !isSizeFieldValid((index_size))) { 355b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGE("%s: offset size not valid: %d, %d, %d, %d", __FUNCTION__, 356b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang offset_size, length_size, base_offset_size, index_size); 357b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_MALFORMED; 358b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 359b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 360b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint32_t item_count; 361b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang size_t itemFieldSize = version() < 2 ? 2 : 4; 362b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (size < itemFieldSize) { 363b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_MALFORMED; 364b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 365b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (!source()->getUInt32Var(offset, &item_count, itemFieldSize)) { 366b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_IO; 367b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 368b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 369b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("item_count %lld", (long long) item_count); 370b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang offset += itemFieldSize; 371b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang size -= itemFieldSize; 372b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 373b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang for (size_t i = 0; i < item_count; i++) { 374b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint32_t item_id; 375b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (!source()->getUInt32Var(offset, &item_id, itemFieldSize)) { 376b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_IO; 377b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 378b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("item[%zu]: id %lld", i, (long long)item_id); 379b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang offset += itemFieldSize; 380b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 381b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint8_t construction_method = 0; 382b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (version() == 1 || version() == 2) { 383b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint8_t buf[2]; 384b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (!source()->readAt(offset, buf, 2)) { 385b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_IO; 386b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 387b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang construction_method = (buf[1] & 0xF); 388b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("construction_method %d", construction_method); 389b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (construction_method == 1) { 390b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang mHasConstructMethod1 = true; 391b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 392b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 393b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang offset += 2; 394b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 395b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 396b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint16_t data_reference_index; 397b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (!source()->getUInt16(offset, &data_reference_index)) { 398b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_IO; 399b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 400b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("data_reference_index %d", data_reference_index); 401b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (data_reference_index != 0) { 402b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang // we don't support reference to other files 403b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_UNSUPPORTED; 404b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 405b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang offset += 2; 406b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 407b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint64_t base_offset = 0; 408b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (base_offset_size != 0) { 409b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (!source()->getUInt64Var(offset, &base_offset, base_offset_size)) { 410b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_IO; 411b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 412b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang offset += base_offset_size; 413b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 414b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("base_offset %lld", (long long) base_offset); 415b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 416b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ssize_t index = mItemLocs->add(item_id, ItemLoc( 417b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang item_id, construction_method, data_reference_index, base_offset)); 418b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ItemLoc &item = mItemLocs->editValueAt(index); 419b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 420b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint16_t extent_count; 421b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (!source()->getUInt16(offset, &extent_count)) { 422b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_IO; 423b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 424b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("extent_count %d", extent_count); 425b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 426b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (extent_count > 1 && (offset_size == 0 || length_size == 0)) { 427b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang // if the item is dividec into more than one extents, offset and 428b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang // length must be present. 429b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_MALFORMED; 430b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 431b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang offset += 2; 432b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 433b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang for (size_t j = 0; j < extent_count; j++) { 434b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint64_t extent_index = 1; // default=1 435b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if ((version() == 1 || version() == 2) && (index_size > 0)) { 436b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (!source()->getUInt64Var(offset, &extent_index, index_size)) { 437b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_IO; 438b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 439b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang // TODO: add support for this mode 440b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang offset += index_size; 441b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("extent_index %lld", (long long)extent_index); 442b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 443b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 444b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint64_t extent_offset = 0; // default=0 445b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (offset_size > 0) { 446b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (!source()->getUInt64Var(offset, &extent_offset, offset_size)) { 447b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_IO; 448b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 449b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang offset += offset_size; 450b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 451b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("extent_offset %lld", (long long)extent_offset); 452b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 453b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint64_t extent_length = 0; // this indicates full length of file 454b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (length_size > 0) { 455b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (!source()->getUInt64Var(offset, &extent_length, length_size)) { 456b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_IO; 457b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 458b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang offset += length_size; 459b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 460b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("extent_length %lld", (long long)extent_length); 461b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 462b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang item.addExtent({ extent_index, extent_offset, extent_length }); 463b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 464b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 465b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return OK; 466b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang} 467b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 468b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang///////////////////////////////////////////////////////////////////// 469b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang// 470b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang// ItemReference related boxes 471b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang// 472b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 473b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstruct ItemReference : public Box, public RefBase { 4742a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen ItemReference(DataSourceBase *source, uint32_t type, uint32_t itemIdSize) : 475b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang Box(source, type), mItemId(0), mRefIdSize(itemIdSize) {} 476b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 477b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t parse(off64_t offset, size_t size); 478b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 479b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint32_t itemId() { return mItemId; } 480b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 48101a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang void apply( 48201a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang KeyedVector<uint32_t, ImageItem> &itemIdToItemMap, 48301a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang KeyedVector<uint32_t, ExifItem> &itemIdToExifMap) const; 484b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 485b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangprivate: 486b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint32_t mItemId; 487b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint32_t mRefIdSize; 488b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang Vector<uint32_t> mRefs; 489b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 490b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang DISALLOW_EVIL_CONSTRUCTORS(ItemReference); 491b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang}; 492b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 49301a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhangvoid ItemReference::apply( 49401a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang KeyedVector<uint32_t, ImageItem> &itemIdToItemMap, 49501a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang KeyedVector<uint32_t, ExifItem> &itemIdToExifMap) const { 49601a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang ALOGV("attach reference type 0x%x to item id %d)", type(), mItemId); 497ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang 49801a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang switch(type()) { 49901a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang case FOURCC('d', 'i', 'm', 'g'): { 50001a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang ssize_t itemIndex = itemIdToItemMap.indexOfKey(mItemId); 501ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang 50201a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang // ignore non-image items 50301a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang if (itemIndex < 0) { 50401a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang return; 50501a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang } 506ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang 507ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang ImageItem &derivedImage = itemIdToItemMap.editValueAt(itemIndex); 508ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang if (!derivedImage.dimgRefs.empty()) { 50999745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang ALOGW("dimgRefs not clean!"); 510ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang } 511ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang derivedImage.dimgRefs.appendVector(mRefs); 512d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang 513d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang for (size_t i = 0; i < mRefs.size(); i++) { 514d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang itemIndex = itemIdToItemMap.indexOfKey(mRefs[i]); 515d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang 516d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang // ignore non-image items 517d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang if (itemIndex < 0) { 518d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang continue; 519d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang } 520d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang ImageItem &sourceImage = itemIdToItemMap.editValueAt(itemIndex); 521d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang 522d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang // mark the source image of the derivation as hidden 523d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang sourceImage.hidden = true; 524d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang } 52501a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang break; 52601a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang } 52701a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang case FOURCC('t', 'h', 'm', 'b'): { 52801a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang ssize_t itemIndex = itemIdToItemMap.indexOfKey(mItemId); 52901a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang 53001a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang // ignore non-image items 53101a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang if (itemIndex < 0) { 53201a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang return; 53301a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang } 53401a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang 535d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang // mark thumbnail image as hidden, these can be retrieved if the client 536d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang // request thumbnail explicitly, but won't be exposed as displayables. 537d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang ImageItem &thumbImage = itemIdToItemMap.editValueAt(itemIndex); 538d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang thumbImage.hidden = true; 539d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang 540ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang for (size_t i = 0; i < mRefs.size(); i++) { 541ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang itemIndex = itemIdToItemMap.indexOfKey(mRefs[i]); 542ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang 543ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang // ignore non-image items 544ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang if (itemIndex < 0) { 545ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang continue; 546ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang } 547ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang ALOGV("Image item id %d uses thumbnail item id %d", mRefs[i], mItemId); 548ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang ImageItem &masterImage = itemIdToItemMap.editValueAt(itemIndex); 549ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang if (!masterImage.thumbnails.empty()) { 550ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang ALOGW("already has thumbnails!"); 551ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang } 552ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang masterImage.thumbnails.push_back(mItemId); 553ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang } 55401a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang break; 55501a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang } 55601a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang case FOURCC('c', 'd', 's', 'c'): { 55701a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang ssize_t itemIndex = itemIdToExifMap.indexOfKey(mItemId); 55801a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang 55901a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang // ignore non-exif block items 56001a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang if (itemIndex < 0) { 56101a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang return; 56201a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang } 56301a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang 56401a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang for (size_t i = 0; i < mRefs.size(); i++) { 56501a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang itemIndex = itemIdToItemMap.indexOfKey(mRefs[i]); 56601a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang 56701a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang // ignore non-image items 56801a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang if (itemIndex < 0) { 56901a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang continue; 57001a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang } 57101a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang ALOGV("Image item id %d uses metadata item id %d", mRefs[i], mItemId); 57201a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang ImageItem &image = itemIdToItemMap.editValueAt(itemIndex); 57301a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang image.cdscRefs.push_back(mItemId); 57401a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang } 57501a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang break; 57601a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang } 57701a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang case FOURCC('a', 'u', 'x', 'l'): { 57801a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang ssize_t itemIndex = itemIdToItemMap.indexOfKey(mItemId); 57901a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang 58001a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang // ignore non-image items 58101a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang if (itemIndex < 0) { 58201a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang return; 58301a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang } 58401a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang 585d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang // mark auxiliary image as hidden 586d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang ImageItem &auxImage = itemIdToItemMap.editValueAt(itemIndex); 587d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang auxImage.hidden = true; 58801a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang break; 58901a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang } 59001a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang default: 591ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang ALOGW("ignoring unsupported ref type 0x%x", type()); 592ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang } 593ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang} 594ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang 595b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstatus_t ItemReference::parse(off64_t offset, size_t size) { 596b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (size < mRefIdSize + 2) { 597b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_MALFORMED; 598b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 599b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (!source()->getUInt32Var(offset, &mItemId, mRefIdSize)) { 600b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_IO; 601b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 602b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang offset += mRefIdSize; 603b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 604b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint16_t count; 605b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (!source()->getUInt16(offset, &count)) { 606b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_IO; 607b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 608b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang offset += 2; 609b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang size -= (mRefIdSize + 2); 610b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 611b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (size < count * mRefIdSize) { 612b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_MALFORMED; 613b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 614b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 615b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang for (size_t i = 0; i < count; i++) { 616b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint32_t refItemId; 617b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (!source()->getUInt32Var(offset, &refItemId, mRefIdSize)) { 618b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_IO; 619b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 620b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang offset += mRefIdSize; 621b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang mRefs.push_back(refItemId); 622b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("item id %d: referencing item id %d", mItemId, refItemId); 623b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 624b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 625b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return OK; 626b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang} 627b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 628b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstruct IrefBox : public FullBox { 6292a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen IrefBox(DataSourceBase *source, Vector<sp<ItemReference> > *itemRefs) : 630b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang FullBox(source, FOURCC('i', 'r', 'e', 'f')), mRefIdSize(0), mItemRefs(itemRefs) {} 631b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 632b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t parse(off64_t offset, size_t size); 633b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 634b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangprotected: 635b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t onChunkData(uint32_t type, off64_t offset, size_t size) override; 636b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 637b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangprivate: 638b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint32_t mRefIdSize; 639b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang Vector<sp<ItemReference> > *mItemRefs; 640b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang}; 641b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 642b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstatus_t IrefBox::parse(off64_t offset, size_t size) { 643b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("%s: offset %lld, size %zu", __FUNCTION__, (long long)offset, size); 644b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t err = parseFullBoxHeader(&offset, &size); 645b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (err != OK) { 646b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return err; 647b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 648b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 649b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang mRefIdSize = (version() == 0) ? 2 : 4; 650b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return parseChunks(offset, size); 651b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang} 652b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 653b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstatus_t IrefBox::onChunkData(uint32_t type, off64_t offset, size_t size) { 654b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang sp<ItemReference> itemRef = new ItemReference(source(), type, mRefIdSize); 655b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 656b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t err = itemRef->parse(offset, size); 657b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (err != OK) { 658b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return err; 659b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 660b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang mItemRefs->push_back(itemRef); 661b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return OK; 662b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang} 663b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 664b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang///////////////////////////////////////////////////////////////////// 665b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang// 666b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang// ItemProperty related boxes 667b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang// 668b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 669b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstruct AssociationEntry { 670b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint32_t itemId; 671b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang bool essential; 672b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint16_t index; 673b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang}; 674b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 675b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstruct ItemProperty : public RefBase { 676b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ItemProperty() {} 677b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 678b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang virtual void attachTo(ImageItem &/*image*/) const { 679b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGW("Unrecognized property"); 680b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 681b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang virtual status_t parse(off64_t /*offset*/, size_t /*size*/) { 682b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGW("Unrecognized property"); 683b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return OK; 684b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 685b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 686b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangprivate: 687b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang DISALLOW_EVIL_CONSTRUCTORS(ItemProperty); 688b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang}; 689b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 690b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstruct IspeBox : public FullBox, public ItemProperty { 6912a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen IspeBox(DataSourceBase *source) : 692b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang FullBox(source, FOURCC('i', 's', 'p', 'e')), mWidth(0), mHeight(0) {} 693b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 694b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t parse(off64_t offset, size_t size) override; 695b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 696b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang void attachTo(ImageItem &image) const override { 697b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang image.width = mWidth; 698b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang image.height = mHeight; 699b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 700b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 701b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangprivate: 702b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint32_t mWidth; 703b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint32_t mHeight; 704b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang}; 705b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 706b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstatus_t IspeBox::parse(off64_t offset, size_t size) { 707b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("%s: offset %lld, size %zu", __FUNCTION__, (long long)offset, size); 708b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 709b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t err = parseFullBoxHeader(&offset, &size); 710b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (err != OK) { 711b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return err; 712b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 713b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 714b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (size < 8) { 715b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_MALFORMED; 716b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 717b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (!source()->getUInt32(offset, &mWidth) 718b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang || !source()->getUInt32(offset + 4, &mHeight)) { 719b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_IO; 720b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 721b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("property ispe: %dx%d", mWidth, mHeight); 722b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 723b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return OK; 724b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang} 725b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 726b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstruct HvccBox : public Box, public ItemProperty { 7272a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen HvccBox(DataSourceBase *source) : 728b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang Box(source, FOURCC('h', 'v', 'c', 'C')) {} 729b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 730b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t parse(off64_t offset, size_t size) override; 731b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 732b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang void attachTo(ImageItem &image) const override { 733b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang image.hvcc = mHVCC; 734b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 735b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 736b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangprivate: 737b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang sp<ABuffer> mHVCC; 738b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang}; 739b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 740b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstatus_t HvccBox::parse(off64_t offset, size_t size) { 741b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("%s: offset %lld, size %zu", __FUNCTION__, (long long)offset, size); 742b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 743b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang mHVCC = new ABuffer(size); 744b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 745b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (mHVCC->data() == NULL) { 746b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGE("b/28471206"); 747b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return NO_MEMORY; 748b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 749b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 750b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (source()->readAt(offset, mHVCC->data(), size) < (ssize_t)size) { 751b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_IO; 752b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 753b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 754b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("property hvcC"); 755b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 756b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return OK; 757b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang} 758b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 759b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstruct IrotBox : public Box, public ItemProperty { 7602a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen IrotBox(DataSourceBase *source) : 761b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang Box(source, FOURCC('i', 'r', 'o', 't')), mAngle(0) {} 762b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 763b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t parse(off64_t offset, size_t size) override; 764b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 765b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang void attachTo(ImageItem &image) const override { 766b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang image.rotation = mAngle * 90; 767b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 768b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 769b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangprivate: 770b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint8_t mAngle; 771b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang}; 772b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 773b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstatus_t IrotBox::parse(off64_t offset, size_t size) { 774b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("%s: offset %lld, size %zu", __FUNCTION__, (long long)offset, size); 775b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 776b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (size < 1) { 777b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_MALFORMED; 778b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 779b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (source()->readAt(offset, &mAngle, 1) != 1) { 780b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_IO; 781b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 782b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang mAngle &= 0x3; 783b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("property irot: %d", mAngle); 784b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 785b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return OK; 786b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang} 787b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 788b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstruct ColrBox : public Box, public ItemProperty { 7892a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen ColrBox(DataSourceBase *source) : 790b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang Box(source, FOURCC('c', 'o', 'l', 'r')) {} 791b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 792b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t parse(off64_t offset, size_t size) override; 793b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 794b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang void attachTo(ImageItem &image) const override { 795b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang image.icc = mICCData; 796b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 797b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 798b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangprivate: 799b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang sp<ABuffer> mICCData; 800b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang}; 801b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 802b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstatus_t ColrBox::parse(off64_t offset, size_t size) { 803b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("%s: offset %lld, size %zu", __FUNCTION__, (long long)offset, size); 804b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 805b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (size < 4) { 806b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_MALFORMED; 807b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 808b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint32_t colour_type; 809b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (!source()->getUInt32(offset, &colour_type)) { 810b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_IO; 811b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 812b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang offset += 4; 813b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang size -= 4; 814b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (colour_type == FOURCC('n', 'c', 'l', 'x')) { 815b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return OK; 816b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 817b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if ((colour_type != FOURCC('r', 'I', 'C', 'C')) && 818b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang (colour_type != FOURCC('p', 'r', 'o', 'f'))) { 819b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_MALFORMED; 820b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 821b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 822b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang mICCData = new ABuffer(size); 823b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (mICCData->data() == NULL) { 824b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGE("b/28471206"); 825b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return NO_MEMORY; 826b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 827b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 828b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (source()->readAt(offset, mICCData->data(), size) != (ssize_t)size) { 829b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_IO; 830b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 831b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 832b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("property Colr: size %zd", size); 833b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return OK; 834b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang} 835b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 836b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstruct IpmaBox : public FullBox { 8372a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen IpmaBox(DataSourceBase *source, Vector<AssociationEntry> *associations) : 838b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang FullBox(source, FOURCC('i', 'p', 'm', 'a')), mAssociations(associations) {} 839b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 840b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t parse(off64_t offset, size_t size); 841b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangprivate: 842b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang Vector<AssociationEntry> *mAssociations; 843b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang}; 844b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 845b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstatus_t IpmaBox::parse(off64_t offset, size_t size) { 846b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t err = parseFullBoxHeader(&offset, &size); 847b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (err != OK) { 848b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return err; 849b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 850b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 851b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (size < 4) { 852b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_MALFORMED; 853b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 854b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint32_t entryCount; 855b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (!source()->getUInt32(offset, &entryCount)) { 856b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_IO; 857b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 858b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang offset += 4; 859b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang size -= 4; 860b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 861b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang for (size_t k = 0; k < entryCount; ++k) { 862b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint32_t itemId = 0; 863b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang size_t itemIdSize = (version() < 1) ? 2 : 4; 864b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 865b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (size < itemIdSize + 1) { 866b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_MALFORMED; 867b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 868b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 869b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (!source()->getUInt32Var(offset, &itemId, itemIdSize)) { 870b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_IO; 871b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 872b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang offset += itemIdSize; 873b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang size -= itemIdSize; 874b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 875b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint8_t associationCount; 876b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (!source()->readAt(offset, &associationCount, 1)) { 877b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_IO; 878b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 879b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang offset++; 880b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang size--; 881b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 882b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang for (size_t i = 0; i < associationCount; ++i) { 883b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang size_t propIndexSize = (flags() & 1) ? 2 : 1; 884b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (size < propIndexSize) { 885b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_MALFORMED; 886b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 887b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint16_t propIndex; 888b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (!source()->getUInt16Var(offset, &propIndex, propIndexSize)) { 889b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_IO; 890b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 891b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang offset += propIndexSize; 892b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang size -= propIndexSize; 893b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint16_t bitmask = (1 << (8 * propIndexSize - 1)); 894b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang AssociationEntry entry = { 895b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang .itemId = itemId, 896b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang .essential = !!(propIndex & bitmask), 897b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang .index = (uint16_t) (propIndex & ~bitmask) 898b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang }; 899b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 900b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("item id %d associated to property %d (essential %d)", 901b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang itemId, entry.index, entry.essential); 902b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 903b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang mAssociations->push_back(entry); 904b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 905b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 906b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 907b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return OK; 908b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang} 909b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 910b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstruct IpcoBox : public Box { 9112a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen IpcoBox(DataSourceBase *source, Vector<sp<ItemProperty> > *properties) : 912b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang Box(source, FOURCC('i', 'p', 'c', 'o')), mItemProperties(properties) {} 913b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 914b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t parse(off64_t offset, size_t size); 915b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangprotected: 916b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t onChunkData(uint32_t type, off64_t offset, size_t size) override; 917b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 918b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangprivate: 919b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang Vector<sp<ItemProperty> > *mItemProperties; 920b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang}; 921b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 922b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstatus_t IpcoBox::parse(off64_t offset, size_t size) { 923b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("%s: offset %lld, size %zu", __FUNCTION__, (long long)offset, size); 924b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang // push dummy as the index is 1-based 925b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang mItemProperties->push_back(new ItemProperty()); 926b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return parseChunks(offset, size); 927b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang} 928b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 929b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstatus_t IpcoBox::onChunkData(uint32_t type, off64_t offset, size_t size) { 930b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang sp<ItemProperty> itemProperty; 931b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang switch(type) { 932b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang case FOURCC('h', 'v', 'c', 'C'): 933b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang { 934b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang itemProperty = new HvccBox(source()); 935b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang break; 936b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 937b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang case FOURCC('i', 's', 'p', 'e'): 938b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang { 939b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang itemProperty = new IspeBox(source()); 940b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang break; 941b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 942b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang case FOURCC('i', 'r', 'o', 't'): 943b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang { 944b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang itemProperty = new IrotBox(source()); 945b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang break; 946b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 947b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang case FOURCC('c', 'o', 'l', 'r'): 948b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang { 949b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang itemProperty = new ColrBox(source()); 950b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang break; 951b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 952b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang default: 953b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang { 954b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang // push dummy to maintain correct item property index 955b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang itemProperty = new ItemProperty(); 956b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang break; 957b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 958b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 959b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t err = itemProperty->parse(offset, size); 960b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (err != OK) { 961b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return err; 962b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 963b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang mItemProperties->push_back(itemProperty); 964b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return OK; 965b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang} 966b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 967b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstruct IprpBox : public Box { 9682a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen IprpBox(DataSourceBase *source, 969b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang Vector<sp<ItemProperty> > *properties, 970b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang Vector<AssociationEntry> *associations) : 971b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang Box(source, FOURCC('i', 'p', 'r', 'p')), 972b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang mProperties(properties), mAssociations(associations) {} 973b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 974b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t parse(off64_t offset, size_t size); 975b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangprotected: 976b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t onChunkData(uint32_t type, off64_t offset, size_t size) override; 977b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 978b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangprivate: 979b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang Vector<sp<ItemProperty> > *mProperties; 980b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang Vector<AssociationEntry> *mAssociations; 981b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang}; 982b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 983b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstatus_t IprpBox::parse(off64_t offset, size_t size) { 984b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("%s: offset %lld, size %zu", __FUNCTION__, (long long)offset, size); 985b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 986b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t err = parseChunks(offset, size); 987b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (err != OK) { 988b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return err; 989b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 990b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return OK; 991b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang} 992b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 993b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstatus_t IprpBox::onChunkData(uint32_t type, off64_t offset, size_t size) { 994b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang switch(type) { 995b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang case FOURCC('i', 'p', 'c', 'o'): 996b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang { 997b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang IpcoBox ipcoBox(source(), mProperties); 998b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ipcoBox.parse(offset, size); 999b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1000b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang case FOURCC('i', 'p', 'm', 'a'): 1001b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang { 1002b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang IpmaBox ipmaBox(source(), mAssociations); 1003b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ipmaBox.parse(offset, size); 1004b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1005b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang default: 1006b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang { 1007b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGW("Unrecognized box."); 1008b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang break; 1009b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1010b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1011b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return OK; 1012b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang} 1013b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1014b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang///////////////////////////////////////////////////////////////////// 1015b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang// 1016b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang// ItemInfo related boxes 1017b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang// 1018b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstruct ItemInfo { 1019b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint32_t itemId; 1020b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint32_t itemType; 1021d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang bool hidden; 1022b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang}; 1023b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1024b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstruct InfeBox : public FullBox { 10252a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen InfeBox(DataSourceBase *source) : 1026b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang FullBox(source, FOURCC('i', 'n', 'f', 'e')) {} 1027b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1028b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t parse(off64_t offset, size_t size, ItemInfo *itemInfo); 1029b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1030b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangprivate: 1031b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang bool parseNullTerminatedString(off64_t *offset, size_t *size, String8 *out); 1032b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang}; 1033b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1034b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangbool InfeBox::parseNullTerminatedString( 1035b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang off64_t *offset, size_t *size, String8 *out) { 1036706018544e02251ddd725b9ebc9e6fa827775ae0Chong Zhang char tmp; 1037706018544e02251ddd725b9ebc9e6fa827775ae0Chong Zhang Vector<char> buf; 1038706018544e02251ddd725b9ebc9e6fa827775ae0Chong Zhang buf.setCapacity(256); 1039b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang off64_t newOffset = *offset; 1040b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang off64_t stopOffset = *offset + *size; 1041b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang while (newOffset < stopOffset) { 1042706018544e02251ddd725b9ebc9e6fa827775ae0Chong Zhang if (!source()->readAt(newOffset++, &tmp, 1)) { 1043b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return false; 1044b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1045706018544e02251ddd725b9ebc9e6fa827775ae0Chong Zhang buf.push_back(tmp); 1046706018544e02251ddd725b9ebc9e6fa827775ae0Chong Zhang if (tmp == 0) { 1047706018544e02251ddd725b9ebc9e6fa827775ae0Chong Zhang out->setTo(buf.array()); 1048b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1049b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang *offset = newOffset; 1050b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang *size = stopOffset - newOffset; 1051b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1052b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return true; 1053b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1054b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1055b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return false; 1056b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang} 1057b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1058b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstatus_t InfeBox::parse(off64_t offset, size_t size, ItemInfo *itemInfo) { 1059b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t err = parseFullBoxHeader(&offset, &size); 1060b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (err != OK) { 1061b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return err; 1062b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1063b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1064b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (version() == 0 || version() == 1) { 1065ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang return ERROR_UNSUPPORTED; 1066b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } else { // version >= 2 1067b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint32_t item_id; 1068b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang size_t itemIdSize = (version() == 2) ? 2 : 4; 1069b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (size < itemIdSize + 6) { 1070b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_MALFORMED; 1071b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1072b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (!source()->getUInt32Var(offset, &item_id, itemIdSize)) { 1073b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_IO; 1074b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1075b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("item_id %d", item_id); 1076b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang offset += itemIdSize; 1077b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint16_t item_protection_index; 1078b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (!source()->getUInt16(offset, &item_protection_index)) { 1079b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_IO; 1080b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1081b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("item_protection_index %d", item_protection_index); 1082b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang offset += 2; 1083b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint32_t item_type; 1084b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (!source()->getUInt32(offset, &item_type)) { 1085b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_IO; 1086b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1087b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1088b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang itemInfo->itemId = item_id; 1089b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang itemInfo->itemType = item_type; 1090d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang // According to HEIF spec, (flags & 1) indicates the image is hidden 1091d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang // and not supposed to be displayed. 1092d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang itemInfo->hidden = (flags() & 1); 1093b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1094b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang char itemTypeString[5]; 1095b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang MakeFourCCString(item_type, itemTypeString); 1096b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("item_type %s", itemTypeString); 1097b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang offset += 4; 1098b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang size -= itemIdSize + 6; 1099b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1100b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang String8 item_name; 1101b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (!parseNullTerminatedString(&offset, &size, &item_name)) { 1102b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_MALFORMED; 1103b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1104b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("item_name %s", item_name.c_str()); 1105b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1106b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (item_type == FOURCC('m', 'i', 'm', 'e')) { 1107b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang String8 content_type; 1108b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (!parseNullTerminatedString(&offset, &size, &content_type)) { 1109b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_MALFORMED; 1110b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1111b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 111246c24cd8224d16124bb00b2cf35ae202d9484687Ray Essick // content_encoding is optional; can be omitted if would be empty 111346c24cd8224d16124bb00b2cf35ae202d9484687Ray Essick if (size > 0) { 111446c24cd8224d16124bb00b2cf35ae202d9484687Ray Essick String8 content_encoding; 111546c24cd8224d16124bb00b2cf35ae202d9484687Ray Essick if (!parseNullTerminatedString(&offset, &size, &content_encoding)) { 111646c24cd8224d16124bb00b2cf35ae202d9484687Ray Essick return ERROR_MALFORMED; 111746c24cd8224d16124bb00b2cf35ae202d9484687Ray Essick } 1118b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1119b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } else if (item_type == FOURCC('u', 'r', 'i', ' ')) { 1120b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang String8 item_uri_type; 1121b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (!parseNullTerminatedString(&offset, &size, &item_uri_type)) { 1122b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_MALFORMED; 1123b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1124b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1125b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1126b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return OK; 1127b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang} 1128b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1129b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstruct IinfBox : public FullBox { 11302a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen IinfBox(DataSourceBase *source, Vector<ItemInfo> *itemInfos) : 1131b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang FullBox(source, FOURCC('i', 'i', 'n', 'f')), 1132b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang mItemInfos(itemInfos), mHasGrids(false) {} 1133b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1134b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t parse(off64_t offset, size_t size); 1135b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1136b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang bool hasGrids() { return mHasGrids; } 1137b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1138b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangprotected: 1139b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t onChunkData(uint32_t type, off64_t offset, size_t size) override; 1140b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1141b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangprivate: 1142b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang Vector<ItemInfo> *mItemInfos; 1143b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang bool mHasGrids; 1144b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang}; 1145b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1146b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstatus_t IinfBox::parse(off64_t offset, size_t size) { 1147b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("%s: offset %lld, size %zu", __FUNCTION__, (long long)offset, size); 1148b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1149b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t err = parseFullBoxHeader(&offset, &size); 1150b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (err != OK) { 1151b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return err; 1152b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1153b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1154b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang size_t entryCountSize = version() == 0 ? 2 : 4; 1155b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (size < entryCountSize) { 1156b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_MALFORMED; 1157b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1158b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint32_t entry_count; 1159b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (!source()->getUInt32Var(offset, &entry_count, entryCountSize)) { 1160b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_IO; 1161b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1162b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("entry_count %d", entry_count); 1163b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1164b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang off64_t stopOffset = offset + size; 1165b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang offset += entryCountSize; 1166b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang for (size_t i = 0; i < entry_count && offset < stopOffset; i++) { 1167b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("entry %zu", i); 1168b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t err = parseChunk(&offset); 1169b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (err != OK) { 1170b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return err; 1171b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1172b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1173b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (offset != stopOffset) { 1174b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_MALFORMED; 1175b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1176b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1177b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return OK; 1178b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang} 1179b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1180b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstatus_t IinfBox::onChunkData(uint32_t type, off64_t offset, size_t size) { 1181b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (type != FOURCC('i', 'n', 'f', 'e')) { 1182b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return OK; 1183b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1184b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1185b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang InfeBox infeBox(source()); 1186b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ItemInfo itemInfo; 1187b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t err = infeBox.parse(offset, size, &itemInfo); 1188ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang if (err == OK) { 1189ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang mItemInfos->push_back(itemInfo); 1190ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang mHasGrids |= (itemInfo.itemType == FOURCC('g', 'r', 'i', 'd')); 1191b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 11925518a2cd0b5b57901e4cf6fd84cbefd5d613e9adChong Zhang // InfeBox parse returns ERROR_UNSUPPORTED if the box if an unsupported 11935518a2cd0b5b57901e4cf6fd84cbefd5d613e9adChong Zhang // version. Ignore this error as it's not fatal. 11945518a2cd0b5b57901e4cf6fd84cbefd5d613e9adChong Zhang return (err == ERROR_UNSUPPORTED) ? OK : err; 1195b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang} 1196b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1197b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang////////////////////////////////////////////////////////////////// 1198b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 11992a243f08193fe9ff1afe018e9953f01c44ced9deMarco NelissenItemTable::ItemTable(DataSourceBase *source) 1200b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang : mDataSource(source), 1201b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang mPrimaryItemId(0), 1202b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang mIdatOffset(0), 1203b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang mIdatSize(0), 1204b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang mImageItemsValid(false), 1205ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang mCurrentItemIndex(0) { 1206b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang mRequiredBoxes.insert('iprp'); 1207b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang mRequiredBoxes.insert('iloc'); 1208b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang mRequiredBoxes.insert('pitm'); 1209b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang mRequiredBoxes.insert('iinf'); 1210b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang} 1211b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1212b51ca280e6aaace44ec1d80837439b825c6fce82Chong ZhangItemTable::~ItemTable() {} 1213b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1214b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstatus_t ItemTable::parse(uint32_t type, off64_t data_offset, size_t chunk_data_size) { 1215b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang switch(type) { 1216b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang case FOURCC('i', 'l', 'o', 'c'): 1217b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang { 1218b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return parseIlocBox(data_offset, chunk_data_size); 1219b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1220b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang case FOURCC('i', 'i', 'n', 'f'): 1221b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang { 1222b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return parseIinfBox(data_offset, chunk_data_size); 1223b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1224b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang case FOURCC('i', 'p', 'r', 'p'): 1225b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang { 1226b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return parseIprpBox(data_offset, chunk_data_size); 1227b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1228b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang case FOURCC('p', 'i', 't', 'm'): 1229b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang { 1230b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return parsePitmBox(data_offset, chunk_data_size); 1231b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1232b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang case FOURCC('i', 'd', 'a', 't'): 1233b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang { 1234b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return parseIdatBox(data_offset, chunk_data_size); 1235b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1236b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang case FOURCC('i', 'r', 'e', 'f'): 1237b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang { 1238b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return parseIrefBox(data_offset, chunk_data_size); 1239b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1240b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang case FOURCC('i', 'p', 'r', 'o'): 1241b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang { 1242b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGW("ipro box not supported!"); 1243b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang break; 1244b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1245b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang default: 1246b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang { 1247b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGW("unrecognized box type: 0x%x", type); 1248b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang break; 1249b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1250b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1251b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_UNSUPPORTED; 1252b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang} 1253b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1254b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstatus_t ItemTable::parseIlocBox(off64_t offset, size_t size) { 1255b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("%s: offset %lld, size %zu", __FUNCTION__, (long long)offset, size); 1256b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1257b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang IlocBox ilocBox(mDataSource, &mItemLocs); 1258b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t err = ilocBox.parse(offset, size); 1259b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (err != OK) { 1260b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return err; 1261b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1262b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1263b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (ilocBox.hasConstructMethod1()) { 1264b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang mRequiredBoxes.insert('idat'); 1265b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1266b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1267b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return buildImageItemsIfPossible('iloc'); 1268b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang} 1269b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1270b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstatus_t ItemTable::parseIinfBox(off64_t offset, size_t size) { 1271b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("%s: offset %lld, size %zu", __FUNCTION__, (long long)offset, size); 1272b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1273b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang IinfBox iinfBox(mDataSource, &mItemInfos); 1274b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t err = iinfBox.parse(offset, size); 1275b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (err != OK) { 1276b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return err; 1277b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1278b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1279b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (iinfBox.hasGrids()) { 1280b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang mRequiredBoxes.insert('iref'); 1281b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1282b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1283b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return buildImageItemsIfPossible('iinf'); 1284b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang} 1285b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1286b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstatus_t ItemTable::parsePitmBox(off64_t offset, size_t size) { 1287b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("%s: offset %lld, size %zu", __FUNCTION__, (long long)offset, size); 1288b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1289b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang PitmBox pitmBox(mDataSource); 1290b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t err = pitmBox.parse(offset, size, &mPrimaryItemId); 1291b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (err != OK) { 1292b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return err; 1293b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1294b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1295b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return buildImageItemsIfPossible('pitm'); 1296b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang} 1297b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1298b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstatus_t ItemTable::parseIprpBox(off64_t offset, size_t size) { 1299b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("%s: offset %lld, size %zu", __FUNCTION__, (long long)offset, size); 1300b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1301b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang IprpBox iprpBox(mDataSource, &mItemProperties, &mAssociations); 1302b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t err = iprpBox.parse(offset, size); 1303b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (err != OK) { 1304b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return err; 1305b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1306b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1307b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return buildImageItemsIfPossible('iprp'); 1308b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang} 1309b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1310b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstatus_t ItemTable::parseIdatBox(off64_t offset, size_t size) { 1311b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("%s: idat offset %lld, size %zu", __FUNCTION__, (long long)offset, size); 1312b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1313b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang // only remember the offset and size of idat box for later use 1314b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang mIdatOffset = offset; 1315b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang mIdatSize = size; 1316b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1317b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return buildImageItemsIfPossible('idat'); 1318b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang} 1319b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1320b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstatus_t ItemTable::parseIrefBox(off64_t offset, size_t size) { 1321b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("%s: offset %lld, size %zu", __FUNCTION__, (long long)offset, size); 1322b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1323b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang IrefBox irefBox(mDataSource, &mItemReferences); 1324b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang status_t err = irefBox.parse(offset, size); 1325b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (err != OK) { 1326b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return err; 1327b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1328b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1329b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return buildImageItemsIfPossible('iref'); 1330b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang} 1331b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1332b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstatus_t ItemTable::buildImageItemsIfPossible(uint32_t type) { 1333b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (mImageItemsValid) { 1334b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return OK; 1335b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1336b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1337b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang mBoxesSeen.insert(type); 1338b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1339b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang // need at least 'iprp', 'iloc', 'pitm', 'iinf'; 1340b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang // need 'idat' if any items used construction_method of 2; 1341b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang // need 'iref' if there are grids. 1342b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (!std::includes( 1343b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang mBoxesSeen.begin(), mBoxesSeen.end(), 1344b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang mRequiredBoxes.begin(), mRequiredBoxes.end())) { 1345b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return OK; 1346b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1347b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1348b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("building image table..."); 1349b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1350b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang for (size_t i = 0; i < mItemInfos.size(); i++) { 1351b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang const ItemInfo &info = mItemInfos[i]; 1352b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 135301a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang // Only handle 3 types of items, all others are ignored: 135401a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang // 'grid': derived image from tiles 135501a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang // 'hvc1': coded image (or tile) 135601a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang // 'Exif': EXIF metadata 1357b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (info.itemType != FOURCC('g', 'r', 'i', 'd') && 135801a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang info.itemType != FOURCC('h', 'v', 'c', '1') && 135901a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang info.itemType != FOURCC('E', 'x', 'i', 'f')) { 1360b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang continue; 1361b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1362b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1363ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang ssize_t itemIndex = mItemIdToItemMap.indexOfKey(info.itemId); 1364ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang if (itemIndex >= 0) { 1365b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGW("ignoring duplicate image item id %d", info.itemId); 1366b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang continue; 1367b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1368b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1369b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ssize_t ilocIndex = mItemLocs.indexOfKey(info.itemId); 1370b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (ilocIndex < 0) { 1371b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGE("iloc missing for image item id %d", info.itemId); 1372b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang continue; 1373b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1374b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang const ItemLoc &iloc = mItemLocs[ilocIndex]; 1375b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1376b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang off64_t offset; 1377b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang size_t size; 1378b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (iloc.getLoc(&offset, &size, mIdatOffset, mIdatSize) != OK) { 1379b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_MALFORMED; 1380b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1381b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 138201a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang if (info.itemType == FOURCC('E', 'x', 'i', 'f')) { 138301a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang // Only add if the Exif data is non-empty. The first 4 bytes contain 138401a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang // the offset to TIFF header, which the Exif parser doesn't use. 138501a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang if (size > 4) { 138601a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang ExifItem exifItem = { 138701a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang .offset = offset, 138801a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang .size = size, 138901a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang }; 139001a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang mItemIdToExifMap.add(info.itemId, exifItem); 139101a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang } 139201a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang continue; 139301a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang } 139401a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang 1395d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang ImageItem image(info.itemType, info.itemId, info.hidden); 1396b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1397b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("adding %s: itemId %d", image.isGrid() ? "grid" : "image", info.itemId); 1398b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1399b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (image.isGrid()) { 1400ef75163eb891b5259c0f5c2fc20fca2a5a47b7b7Chong Zhang // ImageGrid struct is at least 8-byte, at most 12-byte (if flags&1) 1401ef75163eb891b5259c0f5c2fc20fca2a5a47b7b7Chong Zhang if (size < 8 || size > 12) { 1402b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_MALFORMED; 1403b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1404b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint8_t buf[12]; 1405b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (!mDataSource->readAt(offset, buf, size)) { 1406b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_IO; 1407b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1408b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1409b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang image.rows = buf[2] + 1; 1410b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang image.columns = buf[3] + 1; 1411b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1412b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("rows %d, columans %d", image.rows, image.columns); 1413b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } else { 1414b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang image.offset = offset; 1415b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang image.size = size; 1416b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1417ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang mItemIdToItemMap.add(info.itemId, image); 1418b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1419b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1420b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang for (size_t i = 0; i < mAssociations.size(); i++) { 1421b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang attachProperty(mAssociations[i]); 1422b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1423b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1424b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang for (size_t i = 0; i < mItemReferences.size(); i++) { 142501a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang mItemReferences[i]->apply(mItemIdToItemMap, mItemIdToExifMap); 1426b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1427b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1428d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang bool foundPrimary = false; 1429d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang for (size_t i = 0; i < mItemIdToItemMap.size(); i++) { 1430d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang // add all non-hidden images, also add the primary even if it's marked 1431d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang // hidden, in case the primary is set to a thumbnail 1432d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang bool isPrimary = (mItemIdToItemMap[i].itemId == mPrimaryItemId); 1433d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang if (!mItemIdToItemMap[i].hidden || isPrimary) { 1434d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang mDisplayables.push_back(i); 1435d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang } 1436d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang foundPrimary |= isPrimary; 1437d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang } 1438d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang 1439d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang ALOGV("found %zu displayables", mDisplayables.size()); 1440d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang 1441d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang // fail if no displayables are found 1442d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang if (mDisplayables.empty()) { 1443d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang return ERROR_MALFORMED; 1444d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang } 1445d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang 1446d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang // if the primary item id is invalid, set primary to the first displayable 1447d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang if (!foundPrimary) { 1448d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang mPrimaryItemId = mItemIdToItemMap[mDisplayables[0]].itemId; 1449d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang } 1450d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang 1451b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang mImageItemsValid = true; 1452b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return OK; 1453b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang} 1454b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1455b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangvoid ItemTable::attachProperty(const AssociationEntry &association) { 1456ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang ssize_t itemIndex = mItemIdToItemMap.indexOfKey(association.itemId); 1457b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1458b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang // ignore non-image items 1459ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang if (itemIndex < 0) { 1460b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return; 1461b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1462b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1463b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint16_t propertyIndex = association.index; 1464b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (propertyIndex >= mItemProperties.size()) { 1465b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGW("Ignoring invalid property index %d", propertyIndex); 1466b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return; 1467b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1468b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1469b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang ALOGV("attach property %d to item id %d)", 1470b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang propertyIndex, association.itemId); 1471b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1472d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang mItemProperties[propertyIndex]->attachTo(mItemIdToItemMap.editValueAt(itemIndex)); 1473d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang} 1474d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang 1475d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhanguint32_t ItemTable::countImages() const { 1476d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang return mImageItemsValid ? mDisplayables.size() : 0; 1477b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang} 1478b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1479d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhangsp<MetaData> ItemTable::getImageMeta(const uint32_t imageIndex) { 1480b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (!mImageItemsValid) { 1481b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return NULL; 1482b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1483b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1484d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang if (imageIndex >= mDisplayables.size()) { 1485d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang ALOGE("%s: invalid image index %u", __FUNCTION__, imageIndex); 1486b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return NULL; 1487b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1488d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang const uint32_t itemIndex = mDisplayables[imageIndex]; 1489d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang ALOGV("image[%u]: item index %u", imageIndex, itemIndex); 1490b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1491ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang const ImageItem *image = &mItemIdToItemMap[itemIndex]; 1492b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 149399745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang ssize_t tileItemIndex = -1; 149499745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang if (image->isGrid()) { 149599745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang if (image->dimgRefs.empty()) { 149699745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang return NULL; 149799745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang } 149899745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang tileItemIndex = mItemIdToItemMap.indexOfKey(image->dimgRefs[0]); 149999745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang if (tileItemIndex < 0) { 150099745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang return NULL; 150199745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang } 150299745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang } 150399745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang 1504b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang sp<MetaData> meta = new MetaData; 1505d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC); 1506d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang 1507d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang if (image->itemId == mPrimaryItemId) { 1508fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang meta->setInt32(kKeyTrackIsDefault, 1); 1509d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang } 1510d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang 1511d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang ALOGV("image[%u]: size %dx%d", imageIndex, image->width, image->height); 1512b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1513b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang meta->setInt32(kKeyWidth, image->width); 1514b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang meta->setInt32(kKeyHeight, image->height); 1515b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (image->rotation != 0) { 1516686c23b85099378cf8b1efb82260342d996ceb3cChong Zhang // Rotation angle in HEIF is CCW, convert to CW here to be 1517686c23b85099378cf8b1efb82260342d996ceb3cChong Zhang // consistent with the other media formats. 1518686c23b85099378cf8b1efb82260342d996ceb3cChong Zhang switch(image->rotation) { 1519686c23b85099378cf8b1efb82260342d996ceb3cChong Zhang case 90: meta->setInt32(kKeyRotation, 270); break; 1520686c23b85099378cf8b1efb82260342d996ceb3cChong Zhang case 180: meta->setInt32(kKeyRotation, 180); break; 1521686c23b85099378cf8b1efb82260342d996ceb3cChong Zhang case 270: meta->setInt32(kKeyRotation, 90); break; 1522686c23b85099378cf8b1efb82260342d996ceb3cChong Zhang default: break; // don't set if invalid 1523686c23b85099378cf8b1efb82260342d996ceb3cChong Zhang } 1524b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1525b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang meta->setInt32(kKeyMaxInputSize, image->width * image->height * 1.5); 1526b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1527b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (!image->thumbnails.empty()) { 1528ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang ssize_t thumbItemIndex = mItemIdToItemMap.indexOfKey(image->thumbnails[0]); 1529ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang if (thumbItemIndex >= 0) { 1530ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang const ImageItem &thumbnail = mItemIdToItemMap[thumbItemIndex]; 1531b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1532b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang meta->setInt32(kKeyThumbnailWidth, thumbnail.width); 1533b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang meta->setInt32(kKeyThumbnailHeight, thumbnail.height); 1534b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang meta->setData(kKeyThumbnailHVCC, kTypeHVCC, 1535b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang thumbnail.hvcc->data(), thumbnail.hvcc->size()); 1536d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang ALOGV("image[%u]: thumbnail: size %dx%d, item index %zd", 1537d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang imageIndex, thumbnail.width, thumbnail.height, thumbItemIndex); 1538b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } else { 1539ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang ALOGW("%s: Referenced thumbnail does not exist!", __FUNCTION__); 1540b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1541b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1542b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1543b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (image->isGrid()) { 1544d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang meta->setInt32(kKeyGridRows, image->rows); 1545d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang meta->setInt32(kKeyGridCols, image->columns); 1546b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1547ee079fe295c41f89c2ac6316e99ee10847fb78fdChong Zhang // point image to the first tile for grid size and HVCC 1548ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang image = &mItemIdToItemMap.editValueAt(tileItemIndex); 154967d5b91f2fa0b106c038e642225e3b538db2be2eChong Zhang meta->setInt32(kKeyTileWidth, image->width); 155067d5b91f2fa0b106c038e642225e3b538db2be2eChong Zhang meta->setInt32(kKeyTileHeight, image->height); 1551ee079fe295c41f89c2ac6316e99ee10847fb78fdChong Zhang meta->setInt32(kKeyMaxInputSize, image->width * image->height * 1.5); 1552b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1553b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1554b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (image->hvcc == NULL) { 1555d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang ALOGE("%s: hvcc is missing for image[%u]!", __FUNCTION__, imageIndex); 1556b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return NULL; 1557b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1558b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang meta->setData(kKeyHVCC, kTypeHVCC, image->hvcc->data(), image->hvcc->size()); 1559b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1560b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (image->icc != NULL) { 1561b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang meta->setData(kKeyIccProfile, 0, image->icc->data(), image->icc->size()); 1562b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1563b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return meta; 1564b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang} 1565b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1566d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhangstatus_t ItemTable::findImageItem(const uint32_t imageIndex, uint32_t *itemIndex) { 1567b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (!mImageItemsValid) { 1568b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return INVALID_OPERATION; 1569b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1570b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1571d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang if (imageIndex >= mDisplayables.size()) { 1572d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang ALOGE("%s: invalid image index %d", __FUNCTION__, imageIndex); 1573d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang return BAD_VALUE; 1574b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1575b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1576d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang *itemIndex = mDisplayables[imageIndex]; 1577d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang 1578d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang ALOGV("image[%u]: item index %u", imageIndex, *itemIndex); 1579b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return OK; 1580b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang} 1581b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1582d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhangstatus_t ItemTable::findThumbnailItem(const uint32_t imageIndex, uint32_t *itemIndex) { 1583b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (!mImageItemsValid) { 1584b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return INVALID_OPERATION; 1585b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1586b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1587d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang if (imageIndex >= mDisplayables.size()) { 1588d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang ALOGE("%s: invalid image index %d", __FUNCTION__, imageIndex); 1589d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang return BAD_VALUE; 1590b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1591b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1592d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang uint32_t masterItemIndex = mDisplayables[imageIndex]; 1593d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang 1594d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang const ImageItem &masterImage = mItemIdToItemMap[masterItemIndex]; 1595d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang if (masterImage.thumbnails.empty()) { 1596d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang *itemIndex = masterItemIndex; 1597b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return OK; 1598b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1599b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1600d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang ssize_t thumbItemIndex = mItemIdToItemMap.indexOfKey(masterImage.thumbnails[0]); 1601ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang if (thumbItemIndex < 0) { 1602d5fa357ddff0589d8a331583a56e62712af471beChong Zhang // Do not return the master image in this case, fail it so that the 1603d5fa357ddff0589d8a331583a56e62712af471beChong Zhang // thumbnail extraction code knows we really don't have it. 1604d5fa357ddff0589d8a331583a56e62712af471beChong Zhang return INVALID_OPERATION; 1605b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1606b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1607ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang *itemIndex = thumbItemIndex; 1608b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return OK; 1609b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang} 1610b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1611b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhangstatus_t ItemTable::getImageOffsetAndSize( 1612ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang uint32_t *itemIndex, off64_t *offset, size_t *size) { 1613b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (!mImageItemsValid) { 1614b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return INVALID_OPERATION; 1615b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1616b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1617ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang if (itemIndex != NULL) { 1618ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang if (*itemIndex >= mItemIdToItemMap.size()) { 1619ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang ALOGE("%s: Bad item index!", __FUNCTION__); 1620b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return BAD_VALUE; 1621b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1622ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang mCurrentItemIndex = *itemIndex; 1623b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1624b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1625ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang ImageItem &image = mItemIdToItemMap.editValueAt(mCurrentItemIndex); 1626b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (image.isGrid()) { 1627b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang uint32_t tileItemId; 1628ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang status_t err = image.getNextTileItemId(&tileItemId, itemIndex != NULL); 1629b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang if (err != OK) { 1630b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return err; 1631b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1632ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang ssize_t tileItemIndex = mItemIdToItemMap.indexOfKey(tileItemId); 1633ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang if (tileItemIndex < 0) { 1634b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_END_OF_STREAM; 1635b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1636ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang *offset = mItemIdToItemMap[tileItemIndex].offset; 1637ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang *size = mItemIdToItemMap[tileItemIndex].size; 1638b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } else { 1639ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang if (itemIndex == NULL) { 1640b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang // For single images, we only allow it to be read once, after that 1641ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang // it's EOS. New item index must be requested each time. 1642b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return ERROR_END_OF_STREAM; 1643b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1644ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang *offset = mItemIdToItemMap[mCurrentItemIndex].offset; 1645ecd0813e91e1fbb1167ec8fd0faa22c1c87af804Chong Zhang *size = mItemIdToItemMap[mCurrentItemIndex].size; 1646b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang } 1647b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1648b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang return OK; 1649b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang} 1650b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 165101a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhangstatus_t ItemTable::getExifOffsetAndSize(off64_t *offset, size_t *size) { 165201a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang if (!mImageItemsValid) { 165301a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang return INVALID_OPERATION; 165401a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang } 165501a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang 165601a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang ssize_t itemIndex = mItemIdToItemMap.indexOfKey(mPrimaryItemId); 165701a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang 165801a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang // this should not happen, something's seriously wrong. 165901a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang if (itemIndex < 0) { 166001a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang return INVALID_OPERATION; 166101a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang } 166201a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang 166301a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang const ImageItem &image = mItemIdToItemMap[itemIndex]; 166401a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang if (image.cdscRefs.size() == 0) { 166501a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang return NAME_NOT_FOUND; 166601a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang } 166701a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang 166801a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang ssize_t exifIndex = mItemIdToExifMap.indexOfKey(image.cdscRefs[0]); 166901a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang if (exifIndex < 0) { 167001a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang return NAME_NOT_FOUND; 167101a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang } 167201a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang 167301a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang // skip the first 4-byte of the offset to TIFF header 167401a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang *offset = mItemIdToExifMap[exifIndex].offset + 4; 167501a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang *size = mItemIdToExifMap[exifIndex].size - 4; 167601a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang return OK; 167701a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang} 167801a7601f753fb80e89202fc0b115e263581fc3f4Chong Zhang 1679b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang} // namespace heif 1680b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang 1681b51ca280e6aaace44ec1d80837439b825c6fce82Chong Zhang} // namespace android 1682