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