• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "box/item_property_box.h"
17 
18 #include <algorithm>
19 
20 namespace {
21     const uint8_t LARGE_PROPERTY_INDEX_FLAG = 1;
22 }
23 
24 namespace OHOS {
25 namespace ImagePlugin {
ParseContent(HeifStreamReader & reader)26 heif_error HeifIprpBox::ParseContent(HeifStreamReader &reader)
27 {
28     return ReadChildren(reader);
29 }
30 
ParseContent(HeifStreamReader & reader)31 heif_error HeifIpcoBox::ParseContent(HeifStreamReader &reader)
32 {
33     return ReadChildren(reader);
34 }
35 
GetProperties(uint32_t itemId,const std::shared_ptr<class HeifIpmaBox> & ipma,std::vector<std::shared_ptr<HeifBox>> & outProperties) const36 heif_error HeifIpcoBox::GetProperties(uint32_t itemId, const std::shared_ptr<class HeifIpmaBox> &ipma,
37                                       std::vector<std::shared_ptr<HeifBox>> &outProperties) const
38 {
39     const std::vector<PropertyAssociation> *propertyAssocs = ipma->GetProperties(itemId);
40     if (propertyAssocs == nullptr) {
41         return heif_error_property_not_found;
42     }
43 
44     const auto &allProperties = GetChildren();
45     for (const PropertyAssociation &assoc: *propertyAssocs) {
46         if (assoc.propertyIndex > allProperties.size()) {
47             return heif_error_invalid_property_index;
48         }
49 
50         if (assoc.propertyIndex > 0) {
51             outProperties.push_back(allProperties[assoc.propertyIndex - 1]);
52         }
53     }
54 
55     return heif_error_ok;
56 }
57 
GetProperty(heif_item_id itemId,const std::shared_ptr<class HeifIpmaBox> & ipma,uint32_t boxType) const58 std::shared_ptr<HeifBox> HeifIpcoBox::GetProperty(heif_item_id itemId,
59     const std::shared_ptr<class HeifIpmaBox> &ipma, uint32_t boxType) const
60 {
61     const std::vector<PropertyAssociation> *propertyAssocs = ipma->GetProperties(itemId);
62     if (propertyAssocs == nullptr) {
63         return nullptr;
64     }
65 
66     const auto &allProperties = GetChildren();
67     for (const PropertyAssociation &assoc: *propertyAssocs) {
68         if (assoc.propertyIndex > allProperties.size() ||
69             assoc.propertyIndex == 0) {
70             return nullptr;
71         }
72 
73         const auto &property = allProperties[assoc.propertyIndex - 1];
74         if (property->GetBoxType() == boxType) {
75             return property;
76         }
77     }
78 
79     return nullptr;
80 }
81 
ParseContent(HeifStreamReader & reader)82 heif_error HeifIpmaBox::ParseContent(HeifStreamReader &reader)
83 {
84     ParseFullHeader(reader);
85 
86     uint32_t entryNum = reader.Read32();
87     for (uint32_t i = 0; i < entryNum && !reader.HasError() && !reader.IsAtEnd(); i++) {
88         PropertyEntry entry;
89         if (GetVersion() < HEIF_BOX_VERSION_ONE) {
90             entry.itemId = reader.Read16();
91         } else {
92             entry.itemId = reader.Read32();
93         }
94 
95         int assocNum = reader.Read8();
96         for (int k = 0; k < assocNum; k++) {
97             PropertyAssociation association;
98             uint16_t index;
99             if (GetFlags() & LARGE_PROPERTY_INDEX_FLAG) {
100                 index = reader.Read16();
101                 association.essential = !!(index & 0x8000);
102                 association.propertyIndex = (index & 0x7fff);
103             } else {
104                 index = reader.Read8();
105                 association.essential = !!(index & 0x80);
106                 association.propertyIndex = (index & 0x7f);
107             }
108             entry.associations.push_back(association);
109         }
110         entries_.push_back(entry);
111     }
112     return reader.GetError();
113 }
114 
GetProperties(uint32_t itemId) const115 const std::vector<PropertyAssociation> *HeifIpmaBox::GetProperties(uint32_t itemId) const
116 {
117     auto iter = std::find_if(entries_.begin(), entries_.end(), [&itemId](const auto& entry) {
118         return entry.itemId == itemId;
119     });
120     return iter == entries_.end() ? nullptr : &(iter->associations);
121 }
122 
AddProperty(heif_item_id itemId,PropertyAssociation assoc)123 void HeifIpmaBox::AddProperty(heif_item_id itemId, PropertyAssociation assoc)
124 {
125     size_t idx;
126     for (idx = 0; idx < entries_.size(); idx++) {
127         if (entries_[idx].itemId == itemId) {
128             break;
129         }
130     }
131 
132     if (idx == entries_.size()) {
133         PropertyEntry entry;
134         entry.itemId = itemId;
135         entries_.push_back(entry);
136     }
137 
138     entries_[idx].associations.push_back(assoc);
139 }
140 
InferFullBoxVersion()141 void HeifIpmaBox::InferFullBoxVersion()
142 {
143     int version = HEIF_BOX_VERSION_ZERO;
144     bool largeIndices = false;
145 
146     for (const PropertyEntry &entry: entries_) {
147         if (entry.itemId > 0xFFFF) {
148             version = HEIF_BOX_VERSION_ONE;
149         }
150 
151         for (const auto &assoc: entry.associations) {
152             if (assoc.propertyIndex > 0x7F) {
153                 largeIndices = true;
154             }
155         }
156     }
157 
158     SetVersion((uint8_t) version);
159     SetFlags(largeIndices ? LARGE_PROPERTY_INDEX_FLAG : 0);
160 }
161 
Write(HeifStreamWriter & writer) const162 heif_error HeifIpmaBox::Write(HeifStreamWriter &writer) const
163 {
164     size_t boxStart = ReserveHeader(writer);
165 
166     size_t entryNum = entries_.size();
167     writer.Write32((uint32_t) entryNum);
168 
169     for (const PropertyEntry &entry: entries_) {
170         if (GetVersion() < HEIF_BOX_VERSION_ONE) {
171             writer.Write16((uint16_t) entry.itemId);
172         } else {
173             writer.Write32(entry.itemId);
174         }
175         size_t assocNum = entry.associations.size();
176         writer.Write8((uint8_t) assocNum);
177         for (const PropertyAssociation &association: entry.associations) {
178             if (GetFlags() & LARGE_PROPERTY_INDEX_FLAG) {
179                 writer.Write16((uint16_t) ((association.essential ? 0x8000 : 0) |
180                                            (association.propertyIndex & 0x7FFF)));
181             } else {
182                 writer.Write8((uint8_t) ((association.essential ? 0x80 : 0) |
183                                          (association.propertyIndex & 0x7F)));
184             }
185         }
186     }
187 
188     WriteCalculatedHeader(writer, boxStart);
189     return heif_error_ok;
190 }
191 
MergeImpaBoxes(const HeifIpmaBox & b)192 void HeifIpmaBox::MergeImpaBoxes(const HeifIpmaBox &b)
193 {
194     entries_.insert(entries_.end(), b.entries_.begin(), b.entries_.end());
195 }
196 } // namespace ImagePlugin
197 } // namespace OHOS
198