blob: a659660865690dcdccaf4d83af6ee062b97c0268 [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
Marco Nelissenc2b10b32018-09-24 13:19:43 -0700132 virtual ~DataSourceHelper() {}
133
134 virtual ssize_t readAt(off64_t offset, void *data, size_t size) {
Marco Nelissencec44d02018-06-17 22:21:09 -0700135 return mSource->readAt(mSource->handle, offset, data, size);
136 }
137
Marco Nelissenc2b10b32018-09-24 13:19:43 -0700138 virtual status_t getSize(off64_t *size) {
Marco Nelissencec44d02018-06-17 22:21:09 -0700139 return mSource->getSize(mSource->handle, size);
140 }
141
142 bool getUri(char *uriString, size_t bufferSize) {
143 return mSource->getUri(mSource->handle, uriString, bufferSize);
144 }
145
Marco Nelissenc2b10b32018-09-24 13:19:43 -0700146 virtual uint32_t flags() {
Marco Nelissencec44d02018-06-17 22:21:09 -0700147 return mSource->flags(mSource->handle);
148 }
149
150 // Convenience methods:
151 bool getUInt16(off64_t offset, uint16_t *x) {
152 *x = 0;
153
154 uint8_t byte[2];
155 if (readAt(offset, byte, 2) != 2) {
156 return false;
157 }
158
159 *x = (byte[0] << 8) | byte[1];
160
161 return true;
162 }
163
164 // 3 byte int, returned as a 32-bit int
165 bool getUInt24(off64_t offset, uint32_t *x) {
166 *x = 0;
167
168 uint8_t byte[3];
169 if (readAt(offset, byte, 3) != 3) {
170 return false;
171 }
172
173 *x = (byte[0] << 16) | (byte[1] << 8) | byte[2];
174
175 return true;
176 }
177
178 bool getUInt32(off64_t offset, uint32_t *x) {
179 *x = 0;
180
181 uint32_t tmp;
182 if (readAt(offset, &tmp, 4) != 4) {
183 return false;
184 }
185
186 *x = ntohl(tmp);
187
188 return true;
189 }
190
191 bool getUInt64(off64_t offset, uint64_t *x) {
192 *x = 0;
193
194 uint64_t tmp;
195 if (readAt(offset, &tmp, 8) != 8) {
196 return false;
197 }
198
199 *x = ((uint64_t)ntohl(tmp & 0xffffffff) << 32) | ntohl(tmp >> 32);
200
201 return true;
202 }
203
204 // read either int<N> or int<2N> into a uint<2N>_t, size is the int size in bytes.
205 bool getUInt16Var(off64_t offset, uint16_t *x, size_t size) {
206 if (size == 2) {
207 return getUInt16(offset, x);
208 }
209 if (size == 1) {
210 uint8_t tmp;
211 if (readAt(offset, &tmp, 1) == 1) {
212 *x = tmp;
213 return true;
214 }
215 }
216 return false;
217 }
218
219 bool getUInt32Var(off64_t offset, uint32_t *x, size_t size) {
220 if (size == 4) {
221 return getUInt32(offset, x);
222 }
223 if (size == 2) {
224 uint16_t tmp;
225 if (getUInt16(offset, &tmp)) {
226 *x = tmp;
227 return true;
228 }
229 }
230 return false;
231 }
232
233 bool getUInt64Var(off64_t offset, uint64_t *x, size_t size) {
234 if (size == 8) {
235 return getUInt64(offset, x);
236 }
237 if (size == 4) {
238 uint32_t tmp;
239 if (getUInt32(offset, &tmp)) {
240 *x = tmp;
241 return true;
242 }
243 }
244 return false;
245 }
246
247protected:
248 CDataSource *mSource;
249};
250
251
252
Marco Nelissen0b164472018-05-30 12:16:56 -0700253// helpers to create a media_uuid_t from a string literal
254
255// purposely not defined anywhere so that this will fail to link if
256// expressions below are not evaluated at compile time
257int invalid_uuid_string(const char *);
258
259template <typename T, size_t N>
260constexpr uint8_t _digitAt_(const T (&s)[N], const size_t n) {
261 return s[n] >= '0' && s[n] <= '9' ? s[n] - '0'
262 : s[n] >= 'a' && s[n] <= 'f' ? s[n] - 'a' + 10
263 : s[n] >= 'A' && s[n] <= 'F' ? s[n] - 'A' + 10
264 : invalid_uuid_string("uuid: bad digits");
265}
266
267template <typename T, size_t N>
268constexpr uint8_t _hexByteAt_(const T (&s)[N], size_t n) {
269 return (_digitAt_(s, n) << 4) + _digitAt_(s, n + 1);
270}
271
272constexpr bool _assertIsDash_(char c) {
273 return c == '-' ? true : invalid_uuid_string("Wrong format");
274}
275
276template <size_t N>
277constexpr media_uuid_t constUUID(const char (&s) [N]) {
278 static_assert(N == 37, "uuid: wrong length");
279 return
280 _assertIsDash_(s[8]),
281 _assertIsDash_(s[13]),
282 _assertIsDash_(s[18]),
283 _assertIsDash_(s[23]),
284 media_uuid_t {{
285 _hexByteAt_(s, 0),
286 _hexByteAt_(s, 2),
287 _hexByteAt_(s, 4),
288 _hexByteAt_(s, 6),
289 _hexByteAt_(s, 9),
290 _hexByteAt_(s, 11),
291 _hexByteAt_(s, 14),
292 _hexByteAt_(s, 16),
293 _hexByteAt_(s, 19),
294 _hexByteAt_(s, 21),
295 _hexByteAt_(s, 24),
296 _hexByteAt_(s, 26),
297 _hexByteAt_(s, 28),
298 _hexByteAt_(s, 30),
299 _hexByteAt_(s, 32),
300 _hexByteAt_(s, 34),
301 }};
302}
303// Convenience macro to create a media_uuid_t from a string literal, which should
304// be formatted as "12345678-1234-1234-1234-123456789abc", as generated by
305// e.g. https://www.uuidgenerator.net/ or the 'uuidgen' linux command.
306// Hex digits may be upper or lower case.
307//
308// The macro call is otherwise equivalent to specifying the structure directly
309// (e.g. UUID("7d613858-5837-4a38-84c5-332d1cddee27") is the same as
310// {{0x7d, 0x61, 0x38, 0x58, 0x58, 0x37, 0x4a, 0x38,
311// 0x84, 0xc5, 0x33, 0x2d, 0x1c, 0xdd, 0xee, 0x27}})
312
313#define UUID(str) []{ constexpr media_uuid_t uuid = constUUID(str); return uuid; }()
314
315} // namespace android
316
317#endif // MEDIA_EXTRACTOR_PLUGIN_HELPER_H_