blob: c817b30764aeb7bd86a1a161d9e1ea5a92f54b6a [file] [log] [blame]
Marco Nelissen0b164472018-05-30 12:16:56 -07001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef MEDIA_EXTRACTOR_PLUGIN_HELPER_H_
18
19#define MEDIA_EXTRACTOR_PLUGIN_HELPER_H_
20
Marco Nelissencec44d02018-06-17 22:21:09 -070021#include <arpa/inet.h>
Marco Nelissen0b164472018-05-30 12:16:56 -070022#include <stdio.h>
23#include <vector>
24
25#include <utils/Errors.h>
26#include <utils/Log.h>
27#include <utils/RefBase.h>
28#include <media/MediaExtractorPluginApi.h>
29
30namespace android {
31
32class DataSourceBase;
33class MetaDataBase;
34struct MediaTrack;
35
36// extractor plugins can derive from this class which looks remarkably
37// like MediaExtractor and can be easily wrapped in the required C API
38class MediaExtractorPluginHelper
39{
40public:
41 virtual ~MediaExtractorPluginHelper() {}
42 virtual size_t countTracks() = 0;
43 virtual MediaTrack *getTrack(size_t index) = 0;
44
45 enum GetTrackMetaDataFlags {
46 kIncludeExtensiveMetaData = 1
47 };
48 virtual status_t getTrackMetaData(
49 MetaDataBase& meta,
50 size_t index, uint32_t flags = 0) = 0;
51
52 // Return container specific meta-data. The default implementation
53 // returns an empty metadata object.
54 virtual status_t getMetaData(MetaDataBase& meta) = 0;
55
56 enum Flags {
57 CAN_SEEK_BACKWARD = 1, // the "seek 10secs back button"
58 CAN_SEEK_FORWARD = 2, // the "seek 10secs forward button"
59 CAN_PAUSE = 4,
60 CAN_SEEK = 8, // the "seek bar"
61 };
62
63 // If subclasses do _not_ override this, the default is
64 // CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK | CAN_PAUSE
65 virtual uint32_t flags() const {
66 return CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK | CAN_PAUSE;
67 };
68
69 virtual status_t setMediaCas(const uint8_t* /*casToken*/, size_t /*size*/) {
70 return INVALID_OPERATION;
71 }
72
73 virtual const char * name() { return "<unspecified>"; }
74
75protected:
76 MediaExtractorPluginHelper() {}
77
78private:
79 MediaExtractorPluginHelper(const MediaExtractorPluginHelper &);
80 MediaExtractorPluginHelper &operator=(const MediaExtractorPluginHelper &);
81};
82
83inline CMediaExtractor *wrap(MediaExtractorPluginHelper *extractor) {
84 CMediaExtractor *wrapper = (CMediaExtractor*) malloc(sizeof(CMediaExtractor));
85 wrapper->data = extractor;
86 wrapper->free = [](void *data) -> void {
87 delete (MediaExtractorPluginHelper*)(data);
88 };
89 wrapper->countTracks = [](void *data) -> size_t {
90 return ((MediaExtractorPluginHelper*)data)->countTracks();
91 };
92 wrapper->getTrack = [](void *data, size_t index) -> MediaTrack* {
93 return ((MediaExtractorPluginHelper*)data)->getTrack(index);
94 };
95 wrapper->getTrackMetaData = [](
96 void *data,
97 MetaDataBase& meta,
98 size_t index, uint32_t flags) -> status_t {
99 return ((MediaExtractorPluginHelper*)data)->getTrackMetaData(meta, index, flags);
100 };
101 wrapper->getMetaData = [](
102 void *data,
103 MetaDataBase& meta) -> status_t {
104 return ((MediaExtractorPluginHelper*)data)->getMetaData(meta);
105 };
106 wrapper->flags = [](
107 void *data) -> uint32_t {
108 return ((MediaExtractorPluginHelper*)data)->flags();
109 };
110 wrapper->setMediaCas = [](
111 void *data, const uint8_t *casToken, size_t size) -> status_t {
112 return ((MediaExtractorPluginHelper*)data)->setMediaCas(casToken, size);
113 };
114 wrapper->name = [](
115 void *data) -> const char * {
116 return ((MediaExtractorPluginHelper*)data)->name();
117 };
118 return wrapper;
119}
120
Marco Nelissencec44d02018-06-17 22:21:09 -0700121/* adds some convience methods */
122class DataSourceHelper {
123public:
124 explicit DataSourceHelper(CDataSource *csource) {
125 mSource = csource;
126 }
127
128 explicit DataSourceHelper(DataSourceHelper *source) {
129 mSource = source->mSource;
130 }
131
132 ssize_t readAt(off64_t offset, void *data, size_t size) {
133 return mSource->readAt(mSource->handle, offset, data, size);
134 }
135
136 status_t getSize(off64_t *size) {
137 return mSource->getSize(mSource->handle, size);
138 }
139
140 bool getUri(char *uriString, size_t bufferSize) {
141 return mSource->getUri(mSource->handle, uriString, bufferSize);
142 }
143
144 uint32_t flags() {
145 return mSource->flags(mSource->handle);
146 }
147
148 // Convenience methods:
149 bool getUInt16(off64_t offset, uint16_t *x) {
150 *x = 0;
151
152 uint8_t byte[2];
153 if (readAt(offset, byte, 2) != 2) {
154 return false;
155 }
156
157 *x = (byte[0] << 8) | byte[1];
158
159 return true;
160 }
161
162 // 3 byte int, returned as a 32-bit int
163 bool getUInt24(off64_t offset, uint32_t *x) {
164 *x = 0;
165
166 uint8_t byte[3];
167 if (readAt(offset, byte, 3) != 3) {
168 return false;
169 }
170
171 *x = (byte[0] << 16) | (byte[1] << 8) | byte[2];
172
173 return true;
174 }
175
176 bool getUInt32(off64_t offset, uint32_t *x) {
177 *x = 0;
178
179 uint32_t tmp;
180 if (readAt(offset, &tmp, 4) != 4) {
181 return false;
182 }
183
184 *x = ntohl(tmp);
185
186 return true;
187 }
188
189 bool getUInt64(off64_t offset, uint64_t *x) {
190 *x = 0;
191
192 uint64_t tmp;
193 if (readAt(offset, &tmp, 8) != 8) {
194 return false;
195 }
196
197 *x = ((uint64_t)ntohl(tmp & 0xffffffff) << 32) | ntohl(tmp >> 32);
198
199 return true;
200 }
201
202 // read either int<N> or int<2N> into a uint<2N>_t, size is the int size in bytes.
203 bool getUInt16Var(off64_t offset, uint16_t *x, size_t size) {
204 if (size == 2) {
205 return getUInt16(offset, x);
206 }
207 if (size == 1) {
208 uint8_t tmp;
209 if (readAt(offset, &tmp, 1) == 1) {
210 *x = tmp;
211 return true;
212 }
213 }
214 return false;
215 }
216
217 bool getUInt32Var(off64_t offset, uint32_t *x, size_t size) {
218 if (size == 4) {
219 return getUInt32(offset, x);
220 }
221 if (size == 2) {
222 uint16_t tmp;
223 if (getUInt16(offset, &tmp)) {
224 *x = tmp;
225 return true;
226 }
227 }
228 return false;
229 }
230
231 bool getUInt64Var(off64_t offset, uint64_t *x, size_t size) {
232 if (size == 8) {
233 return getUInt64(offset, x);
234 }
235 if (size == 4) {
236 uint32_t tmp;
237 if (getUInt32(offset, &tmp)) {
238 *x = tmp;
239 return true;
240 }
241 }
242 return false;
243 }
244
245protected:
246 CDataSource *mSource;
247};
248
249
250
Marco Nelissen0b164472018-05-30 12:16:56 -0700251// helpers to create a media_uuid_t from a string literal
252
253// purposely not defined anywhere so that this will fail to link if
254// expressions below are not evaluated at compile time
255int invalid_uuid_string(const char *);
256
257template <typename T, size_t N>
258constexpr uint8_t _digitAt_(const T (&s)[N], const size_t n) {
259 return s[n] >= '0' && s[n] <= '9' ? s[n] - '0'
260 : s[n] >= 'a' && s[n] <= 'f' ? s[n] - 'a' + 10
261 : s[n] >= 'A' && s[n] <= 'F' ? s[n] - 'A' + 10
262 : invalid_uuid_string("uuid: bad digits");
263}
264
265template <typename T, size_t N>
266constexpr uint8_t _hexByteAt_(const T (&s)[N], size_t n) {
267 return (_digitAt_(s, n) << 4) + _digitAt_(s, n + 1);
268}
269
270constexpr bool _assertIsDash_(char c) {
271 return c == '-' ? true : invalid_uuid_string("Wrong format");
272}
273
274template <size_t N>
275constexpr media_uuid_t constUUID(const char (&s) [N]) {
276 static_assert(N == 37, "uuid: wrong length");
277 return
278 _assertIsDash_(s[8]),
279 _assertIsDash_(s[13]),
280 _assertIsDash_(s[18]),
281 _assertIsDash_(s[23]),
282 media_uuid_t {{
283 _hexByteAt_(s, 0),
284 _hexByteAt_(s, 2),
285 _hexByteAt_(s, 4),
286 _hexByteAt_(s, 6),
287 _hexByteAt_(s, 9),
288 _hexByteAt_(s, 11),
289 _hexByteAt_(s, 14),
290 _hexByteAt_(s, 16),
291 _hexByteAt_(s, 19),
292 _hexByteAt_(s, 21),
293 _hexByteAt_(s, 24),
294 _hexByteAt_(s, 26),
295 _hexByteAt_(s, 28),
296 _hexByteAt_(s, 30),
297 _hexByteAt_(s, 32),
298 _hexByteAt_(s, 34),
299 }};
300}
301// Convenience macro to create a media_uuid_t from a string literal, which should
302// be formatted as "12345678-1234-1234-1234-123456789abc", as generated by
303// e.g. https://www.uuidgenerator.net/ or the 'uuidgen' linux command.
304// Hex digits may be upper or lower case.
305//
306// The macro call is otherwise equivalent to specifying the structure directly
307// (e.g. UUID("7d613858-5837-4a38-84c5-332d1cddee27") is the same as
308// {{0x7d, 0x61, 0x38, 0x58, 0x58, 0x37, 0x4a, 0x38,
309// 0x84, 0xc5, 0x33, 0x2d, 0x1c, 0xdd, 0xee, 0x27}})
310
311#define UUID(str) []{ constexpr media_uuid_t uuid = constUUID(str); return uuid; }()
312
313} // namespace android
314
315#endif // MEDIA_EXTRACTOR_PLUGIN_HELPER_H_