libopenraw  0.3.7
isomediacontainer.cpp
1 /* -*- tab-width:4; c-basic-offset:4; indent-tabs-mode:nil; -*- */
2 /*
3  * libopenraw - isomediacontainer.cpp
4  *
5  * Copyright (C) 2018-2020 Hubert Figuiere
6  *
7  * This library is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * as published by the Free Software Foundation, either version 3 of
10  * the License, or (at your option) any later version.
11  *
12  * This library 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 GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library. If not, see
19  * <http://www.gnu.org/licenses/>.
20  */
21 
22 #include "isomediacontainer.hpp"
23 #include "trace.hpp"
24 #include "io/memstream.hpp"
25 
26 namespace OpenRaw {
27 namespace Internals {
28 
29 
30 IsoMediaContainer::IsoMediaContainer(const IO::Stream::Ptr &file)
31  : RawContainer(file, 0)
32  , m_mp4io{ &IsoMediaContainer::read_callback, static_cast<void*>(file.get()) }
33  , m_parser(nullptr)
34 {
35  setEndian(ENDIAN_BIG);
36  m_file->seek(0, SEEK_SET);
37  auto status = mp4parse_new(&m_mp4io, &m_parser);
38  if (status != MP4PARSE_STATUS_OK) {
39  LOGERR("IsoM: failed to create parser: %d\n", status);
40  }
41 }
42 
43 IsoMediaContainer::~IsoMediaContainer()
44 {
45  if (m_parser) {
46  mp4parse_free(m_parser);
47  }
48 }
49 
50 uint32_t IsoMediaContainer::count_tracks()
51 {
52  uint32_t count = 0;
53  auto status = mp4parse_get_track_count(m_parser, &count);
54  if (status != MP4PARSE_STATUS_OK) {
55  LOGERR("IsoM: get_track_count() failed %d\n", status);
56  return 0;
57  }
58 
59  return count;
60 }
61 
63 IsoMediaContainer::get_track(uint32_t index)
64 {
65  Mp4parseTrackInfo info;
66  auto status = mp4parse_get_track_info(m_parser, index, &info);
67  if (status != MP4PARSE_STATUS_OK) {
68  return OptionNone();
69  }
70  return option_some(std::move(info));
71 }
72 
74 IsoMediaContainer::get_raw_track(uint32_t index)
75 {
77  auto status = mp4parse_get_track_raw_info(m_parser, index, &info);
78  if (status != MP4PARSE_STATUS_OK) {
79  return OptionNone();
80  }
81  return option_some(std::move(info));
82 }
83 
85 IsoMediaContainer::get_craw_header()
86 {
87  Mp4parseCrawHeader header;
88  auto status = mp4parse_get_craw_header(m_parser, &header);
89  if (status != MP4PARSE_STATUS_OK) {
90  return OptionNone();
91  }
92  return option_some(std::move(header));
93 }
94 
96 IsoMediaContainer::get_offsets_at(uint32_t index)
97 {
98  std::pair<uint64_t, uint64_t> entry;
99  auto status = mp4parse_get_craw_table_entry(m_parser, index,
100  &entry.first, &entry.second);
101  if (status != MP4PARSE_STATUS_OK) {
102  return OptionNone();
103  }
104  return option_some(std::move(entry));
105 }
106 
108 IsoMediaContainer::get_preview_desc()
109 {
110  auto preview_offset = get_offsets_at(1);
111  if (preview_offset) {
112  auto offset = (*preview_offset).first;
113  // box (24) + content (8) + prvw box (8) + unknown (4)
114  // We need to skip the "boxes" (ISO container)
115  // And skip a short (16bits) value.
116  offset += 44 + 2;
117  m_file->seek(offset, SEEK_SET);
118  auto width = readUInt16(m_file, m_endian);
119  auto height = readUInt16(m_file, m_endian);
120  skip(2);
121  auto jpeg_size = readUInt32(m_file, m_endian);
122  if (width && height && jpeg_size) {
123  return option_some(
124  std::move(ThumbDesc(*width, *height, OR_DATA_TYPE_JPEG,
125  offset + 10, *jpeg_size)));
126  }
127  }
128  return OptionNone();
129 }
130 
131 std::shared_ptr<IfdFileContainer>
132 IsoMediaContainer::get_metadata_block(uint32_t idx)
133 {
134  if (m_meta_ifd.empty()) {
135  auto craw = get_craw_header();
136  if (!craw) {
137  return std::shared_ptr<IfdFileContainer>();
138  }
139 
140  m_meta_ifd.resize(4);
141  if ((*craw).meta1.length) {
142  auto mem = std::make_shared<IO::MemStream>(
143  (*craw).meta1.data, (*craw).meta1.length);
144  m_meta_ifd[0] = std::make_shared<IfdFileContainer>(mem, 0);
145  } else {
146  m_meta_ifd[0] = std::shared_ptr<IfdFileContainer>();
147  }
148  if ((*craw).meta2.length) {
149  auto mem = std::make_shared<IO::MemStream>(
150  (*craw).meta2.data, (*craw).meta2.length);
151  m_meta_ifd[1] = std::make_shared<IfdFileContainer>(mem, 0);
152  } else {
153  m_meta_ifd[1] = std::shared_ptr<IfdFileContainer>();
154  }
155  if ((*craw).meta3.length) {
156  auto mem = std::make_shared<IO::MemStream>(
157  (*craw).meta3.data, (*craw).meta3.length);
158  m_meta_ifd[2] = std::make_shared<IfdFileContainer>(mem, 0);
159  } else {
160  m_meta_ifd[2] = std::shared_ptr<IfdFileContainer>();
161  }
162  if ((*craw).meta4.length) {
163  auto mem = std::make_shared<IO::MemStream>(
164  (*craw).meta4.data, (*craw).meta4.length);
165  m_meta_ifd[3] = std::make_shared<IfdFileContainer>(mem, 0);
166  } else {
167  m_meta_ifd[3] = std::shared_ptr<IfdFileContainer>();
168  }
169  }
170  if (idx < m_meta_ifd.size()) {
171  return m_meta_ifd.at(idx);
172  }
173  return std::shared_ptr<IfdFileContainer>();
174 }
175 
176 intptr_t
177 IsoMediaContainer::read_callback(uint8_t* buf, uintptr_t len, void* self)
178 {
179  IO::Stream* stream = static_cast<IO::Stream*>(self);
180  return stream->read(buf, len);
181 }
182 
183 }
184 }
std::shared_ptr< Stream > Ptr
Definition: stream.hpp:47
Tag class to help create an empty Option.
Definition: option.hpp:41
An option type inspired by Rust.
Definition: option.hpp:47
Option< T > option_some(T &&value)
Create an Option<T> is some value.
Definition: option.hpp:131
@ OR_DATA_TYPE_JPEG
Definition: consts.h:84
Global namespace for libopenraw.
Definition: arwfile.cpp:29