/src/libheif/libheif/file.h
Line | Count | Source |
1 | | /* |
2 | | * HEIF codec. |
3 | | * Copyright (c) 2017 Dirk Farin <dirk.farin@gmail.com> |
4 | | * |
5 | | * This file is part of libheif. |
6 | | * |
7 | | * libheif is free software: you can redistribute it and/or modify |
8 | | * it under the terms of the GNU Lesser General Public License as |
9 | | * published by the Free Software Foundation, either version 3 of |
10 | | * the License, or (at your option) any later version. |
11 | | * |
12 | | * libheif is distributed in the hope that it will be useful, |
13 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | | * GNU Lesser General Public License for more details. |
16 | | * |
17 | | * You should have received a copy of the GNU Lesser General Public License |
18 | | * along with libheif. If not, see <http://www.gnu.org/licenses/>. |
19 | | */ |
20 | | |
21 | | #ifndef LIBHEIF_FILE_H |
22 | | #define LIBHEIF_FILE_H |
23 | | |
24 | | #include "box.h" |
25 | | #include "id_creator.h" |
26 | | #include "nclx.h" |
27 | | #include "image-items/avif.h" |
28 | | #include "image-items/hevc.h" |
29 | | #include "image-items/vvc.h" |
30 | | //#include "codecs/uncompressed/unc_boxes.h" |
31 | | #include "file_layout.h" |
32 | | |
33 | | #include <map> |
34 | | #include <memory> |
35 | | #include <string> |
36 | | #include <map> |
37 | | #include <vector> |
38 | | #include <unordered_set> |
39 | | #include <limits> |
40 | | #include <utility> |
41 | | #include "mdat_data.h" |
42 | | |
43 | | #if ENABLE_PARALLEL_TILE_DECODING |
44 | | |
45 | | #include <mutex> |
46 | | |
47 | | #endif |
48 | | |
49 | | |
50 | | class HeifPixelImage; |
51 | | |
52 | | class Box_j2kH; |
53 | | |
54 | | class Box_moov; |
55 | | |
56 | | class Box_mvhd; |
57 | | |
58 | | |
59 | | |
60 | | class HeifFile |
61 | | { |
62 | | public: |
63 | | HeifFile(); |
64 | | |
65 | | ~HeifFile(); |
66 | | |
67 | | // The limits will be shared from the HeifContext limits. |
68 | | // You have to make sure that the pointer points to a valid object as long as the HeifFile is used. |
69 | 32.7k | void set_security_limits(const heif_security_limits* limits) { m_limits = limits; } |
70 | | |
71 | 7.02k | const heif_security_limits* get_security_limits() const { return m_limits; } |
72 | | |
73 | | Error read(const std::shared_ptr<StreamReader>& reader); |
74 | | |
75 | | Error read_from_file(const char* input_filename); |
76 | | |
77 | | Error read_from_memory(const void* data, size_t size, bool copy); |
78 | | |
79 | | bool has_images() const; |
80 | | |
81 | 9.50k | bool has_sequences() const { return m_moov_box != nullptr; } |
82 | | |
83 | 0 | std::shared_ptr<StreamReader> get_reader() { return m_input_stream; } |
84 | | |
85 | | void new_empty_file(); |
86 | | |
87 | | void init_for_meta_item(); |
88 | | |
89 | | void init_for_image(); |
90 | | |
91 | | void init_for_sequence(); |
92 | | |
93 | 249 | void set_hdlr_box(std::shared_ptr<Box_hdlr> box) { m_hdlr_box = std::move(box); } |
94 | | |
95 | | size_t append_mdat_data(const std::vector<uint8_t>& data); |
96 | | |
97 | | void derive_box_versions(); |
98 | | |
99 | | void write(StreamWriter& writer); |
100 | | |
101 | 0 | void set_write_mini_format(bool enable) { m_write_mini_format = enable; } |
102 | 0 | bool get_write_mini_format() const { return m_write_mini_format; } |
103 | | |
104 | 0 | int get_num_images() const { return static_cast<int>(m_infe_boxes.size()); } |
105 | | |
106 | 15.9k | heif_item_id get_primary_image_ID() const { return m_pitm_box ? m_pitm_box->get_item_ID() : 0; } |
107 | | |
108 | 0 | size_t get_number_of_items() const { return m_infe_boxes.size(); } |
109 | | |
110 | | std::vector<heif_item_id> get_item_IDs() const; |
111 | | |
112 | | bool item_exists(heif_item_id ID) const; |
113 | | |
114 | | bool has_item_with_id(heif_item_id ID) const; |
115 | | |
116 | | uint32_t get_item_type_4cc(heif_item_id ID) const; |
117 | | |
118 | | std::string get_content_type(heif_item_id ID) const; |
119 | | |
120 | | std::string get_item_uri_type(heif_item_id ID) const; |
121 | | |
122 | | Result<std::vector<uint8_t>> get_uncompressed_item_data(heif_item_id ID) const; |
123 | | |
124 | | Error append_data_from_file_range(std::vector<uint8_t>& out_data, uint64_t offset, uint32_t size) const; |
125 | | |
126 | | Error append_data_from_iloc(heif_item_id ID, std::vector<uint8_t>& out_data, uint64_t offset, uint64_t size) const; |
127 | | |
128 | 9.74k | Error append_data_from_iloc(heif_item_id ID, std::vector<uint8_t>& out_data) const { |
129 | 9.74k | return append_data_from_iloc(ID, out_data, 0, std::numeric_limits<uint64_t>::max()); |
130 | 9.74k | } |
131 | | |
132 | | // If `out_compression` is not NULL, the compression method is returned there and the compressed data is returned. |
133 | | // If `out_compression` is NULL, the data is returned decompressed. |
134 | | Result<std::vector<uint8_t>> get_item_data(heif_item_id ID, heif_metadata_compression* out_compression) const; |
135 | | |
136 | 249 | std::shared_ptr<Box_ftyp> get_ftyp_box() { return m_ftyp_box; } |
137 | | |
138 | 249 | void init_meta_box() { m_meta_box = std::make_shared<Box_meta>(); } |
139 | | |
140 | | std::shared_ptr<const Box_infe> get_infe_box(heif_item_id imageID) const; |
141 | | |
142 | | std::shared_ptr<Box_infe> get_infe_box(heif_item_id imageID); |
143 | | |
144 | | void set_iref_box(std::shared_ptr<Box_iref>); |
145 | | |
146 | 17.1k | std::shared_ptr<Box_iref> get_iref_box() { return m_iref_box; } |
147 | | |
148 | 0 | std::shared_ptr<const Box_iref> get_iref_box() const { return m_iref_box; } |
149 | | |
150 | 15.5k | std::shared_ptr<Box_ipco> get_ipco_box() { return m_ipco_box; } |
151 | | |
152 | | void set_ipco_box(std::shared_ptr<Box_ipco>); |
153 | | |
154 | 0 | std::shared_ptr<Box_ipco> get_ipco_box() const { return m_ipco_box; } |
155 | | |
156 | | void set_ipma_box(std::shared_ptr<Box_ipma>); |
157 | | |
158 | 15.5k | std::shared_ptr<Box_ipma> get_ipma_box() { return m_ipma_box; } |
159 | | |
160 | 0 | std::shared_ptr<Box_ipma> get_ipma_box() const { return m_ipma_box; } |
161 | | |
162 | 0 | std::shared_ptr<Box_grpl> get_grpl_box() const { return m_grpl_box; } |
163 | | |
164 | 0 | std::shared_ptr<Box_meta> get_meta_box() const { return m_meta_box; } |
165 | | |
166 | | std::shared_ptr<Box_EntityToGroup> get_entity_group(heif_entity_group_id id); |
167 | | |
168 | | Error get_properties(heif_item_id imageID, |
169 | | std::vector<std::shared_ptr<Box>>& properties) const; |
170 | | |
171 | | template<class BoxType> |
172 | | std::shared_ptr<BoxType> get_property_for_item(heif_item_id imageID) const |
173 | 14.1k | { |
174 | 14.1k | std::vector<std::shared_ptr<Box>> properties; |
175 | 14.1k | Error err = get_properties(imageID, properties); |
176 | 14.1k | if (err) { |
177 | 0 | return nullptr; |
178 | 0 | } |
179 | | |
180 | 35.6k | for (auto& property : properties) { |
181 | 35.6k | if (auto box = std::dynamic_pointer_cast<BoxType>(property)) { |
182 | 0 | return box; |
183 | 0 | } |
184 | 35.6k | } |
185 | | |
186 | 14.1k | return nullptr; |
187 | 14.1k | } Unexecuted instantiation: std::__1::shared_ptr<Box_udes> HeifFile::get_property_for_item<Box_udes>(unsigned int) const Unexecuted instantiation: std::__1::shared_ptr<Box_imir> HeifFile::get_property_for_item<Box_imir>(unsigned int) const Unexecuted instantiation: std::__1::shared_ptr<Box_irot> HeifFile::get_property_for_item<Box_irot>(unsigned int) const Unexecuted instantiation: std::__1::shared_ptr<Box_clap> HeifFile::get_property_for_item<Box_clap>(unsigned int) const Unexecuted instantiation: std::__1::shared_ptr<Box_other> HeifFile::get_property_for_item<Box_other>(unsigned int) const std::__1::shared_ptr<Box_rref> HeifFile::get_property_for_item<Box_rref>(unsigned int) const Line | Count | Source | 173 | 14.1k | { | 174 | 14.1k | std::vector<std::shared_ptr<Box>> properties; | 175 | 14.1k | Error err = get_properties(imageID, properties); | 176 | 14.1k | if (err) { | 177 | 0 | return nullptr; | 178 | 0 | } | 179 | | | 180 | 35.6k | for (auto& property : properties) { | 181 | 35.6k | if (auto box = std::dynamic_pointer_cast<BoxType>(property)) { | 182 | 0 | return box; | 183 | 0 | } | 184 | 35.6k | } | 185 | | | 186 | 14.1k | return nullptr; | 187 | 14.1k | } |
Unexecuted instantiation: std::__1::shared_ptr<Box_elng> HeifFile::get_property_for_item<Box_elng>(unsigned int) const Unexecuted instantiation: std::__1::shared_ptr<Box_taic> HeifFile::get_property_for_item<Box_taic>(unsigned int) const Unexecuted instantiation: std::__1::shared_ptr<Box_itai> HeifFile::get_property_for_item<Box_itai>(unsigned int) const Unexecuted instantiation: std::__1::shared_ptr<Box_pixi> HeifFile::get_property_for_item<Box_pixi>(unsigned int) const |
188 | | |
189 | | std::string debug_dump_boxes() const; |
190 | | |
191 | | std::string debug_dump_item_data() const; |
192 | | |
193 | | |
194 | | // --- writing --- |
195 | | |
196 | 0 | IDCreator& get_id_creator() { return m_id_creator; } |
197 | | |
198 | 0 | const IDCreator& get_id_creator() const { return m_id_creator; } |
199 | | |
200 | | Result<heif_item_id> get_unused_item_id(); |
201 | | |
202 | | Result<heif_item_id> add_new_image(uint32_t item_type); |
203 | | |
204 | | Result<std::shared_ptr<Box_infe>> add_new_infe_box(uint32_t item_type); |
205 | | |
206 | | Result<std::shared_ptr<Box_infe>> add_new_meta_infe_box(uint32_t item_type); |
207 | | |
208 | | void add_ispe_property(heif_item_id id, uint32_t width, uint32_t height, bool essential); |
209 | | |
210 | | // set irot/imir according to heif_orientation |
211 | | void add_orientation_properties(heif_item_id id, heif_orientation); |
212 | | |
213 | | // TODO: can we remove the 'essential' parameter and take this from the box? Or is that depending on the context? |
214 | | heif_property_id add_property(heif_item_id id, const std::shared_ptr<Box>& property, bool essential); |
215 | | |
216 | | heif_property_id add_property_without_deduplication(heif_item_id id, const std::shared_ptr<Box>& property, bool essential); |
217 | | |
218 | | Result<heif_item_id> add_infe(uint32_t item_type, const uint8_t* data, size_t size); |
219 | | |
220 | | void add_infe_box(heif_item_id, std::shared_ptr<Box_infe> infe); |
221 | | |
222 | | Result<heif_item_id> add_infe_mime(const char* content_type, heif_metadata_compression content_encoding, const uint8_t* data, size_t size); |
223 | | |
224 | | Result<heif_item_id> add_precompressed_infe_mime(const char* content_type, std::string content_encoding, const uint8_t* data, size_t size); |
225 | | |
226 | | Result<heif_item_id> add_infe_uri(const char* item_uri_type, const uint8_t* data, size_t size); |
227 | | |
228 | | Error set_item_data(const std::shared_ptr<Box_infe>& item, const uint8_t* data, size_t size, heif_metadata_compression compression); |
229 | | |
230 | | Error set_precompressed_item_data(const std::shared_ptr<Box_infe>& item, const uint8_t* data, size_t size, std::string content_encoding); |
231 | | |
232 | | void append_iloc_data(heif_item_id id, const std::vector<uint8_t>& nal_packets, uint8_t construction_method); |
233 | | |
234 | | void replace_iloc_data(heif_item_id id, uint64_t offset, const std::vector<uint8_t>& data, uint8_t construction_method = 0); |
235 | | |
236 | | void set_iloc_box(std::shared_ptr<Box_iloc>); |
237 | | |
238 | 0 | std::shared_ptr<Box_iloc> get_iloc_box() { return m_iloc_box; } |
239 | | |
240 | | void set_primary_item_id(heif_item_id id); |
241 | | |
242 | | void add_iref_reference(heif_item_id from, uint32_t type, |
243 | | const std::vector<heif_item_id>& to); |
244 | | |
245 | | void set_iref_reference(heif_item_id from, uint32_t type, int reference_idx, heif_item_id to_item); |
246 | | |
247 | | void add_entity_group_box(const std::shared_ptr<Box>& entity_group_box); |
248 | | |
249 | | void set_auxC_property(heif_item_id id, const std::string& type); |
250 | | |
251 | | #if defined(__MINGW32__) || defined(__MINGW64__) || defined(_MSC_VER) |
252 | | static std::wstring convert_utf8_path_to_utf16(std::string pathutf8); |
253 | | #endif |
254 | | |
255 | | |
256 | | // --- sequences |
257 | | |
258 | 48 | std::shared_ptr<Box_moov> get_moov_box() { return m_moov_box; } |
259 | | |
260 | 0 | std::shared_ptr<Box_mvhd> get_mvhd_box() { return m_mvhd_box; } |
261 | | |
262 | | private: |
263 | | #if ENABLE_PARALLEL_TILE_DECODING |
264 | | mutable std::mutex m_read_mutex; |
265 | | #endif |
266 | | |
267 | | std::shared_ptr<FileLayout> m_file_layout; |
268 | | |
269 | | std::shared_ptr<StreamReader> m_input_stream; |
270 | | |
271 | | std::vector<std::shared_ptr<Box> > m_top_level_boxes; |
272 | | |
273 | | std::shared_ptr<Box_ftyp> m_ftyp_box; |
274 | | std::shared_ptr<Box_hdlr> m_hdlr_box; |
275 | | std::shared_ptr<Box_meta> m_meta_box; |
276 | | std::shared_ptr<Box_mini> m_mini_box; // meta alternative |
277 | | bool m_write_mini_format = false; |
278 | | |
279 | | std::shared_ptr<Box_iloc> m_iloc_box; |
280 | | std::shared_ptr<Box_idat> m_idat_box; |
281 | | std::shared_ptr<Box_iref> m_iref_box; |
282 | | std::shared_ptr<Box_iinf> m_iinf_box; |
283 | | std::shared_ptr<Box_grpl> m_grpl_box; |
284 | | std::shared_ptr<Box_pitm> m_pitm_box; // only non-null if has_images()==true |
285 | | std::shared_ptr<Box_iprp> m_iprp_box; // only non-null if has_images()==true |
286 | | std::shared_ptr<Box_ipco> m_ipco_box; // only non-null if has_images()==true |
287 | | std::shared_ptr<Box_ipma> m_ipma_box; // only non-null if has_images()==true |
288 | | |
289 | | |
290 | | std::map<heif_item_id, std::shared_ptr<Box_infe> > m_infe_boxes; |
291 | | |
292 | | std::unique_ptr<MdatData> m_mdat_data; |
293 | | |
294 | | // returns the position of the first data byte in the file |
295 | | Result<size_t> write_mdat(StreamWriter& writer); |
296 | | |
297 | | // --- sequences |
298 | | |
299 | | std::shared_ptr<Box_moov> m_moov_box; |
300 | | std::shared_ptr<Box_mvhd> m_mvhd_box; |
301 | | |
302 | | const heif_security_limits* m_limits = nullptr; |
303 | | IDCreator m_id_creator; |
304 | | |
305 | | Error parse_heif_file(); |
306 | | |
307 | | Error parse_heif_images(); |
308 | | |
309 | | Error parse_heif_sequences(); |
310 | | |
311 | | Error check_for_ref_cycle(heif_item_id ID, |
312 | | const std::shared_ptr<Box_iref>& iref_box) const; |
313 | | |
314 | | Error check_for_ref_cycle_recursion(heif_item_id ID, |
315 | | const std::shared_ptr<Box_iref>& iref_box, |
316 | | std::unordered_set<heif_item_id>& parent_items) const; |
317 | | }; |
318 | | |
319 | | #endif |