blob: 292ec93ee8da6c2e7819d2b38defaa156f3a609a [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>
Marco Nelissen0e043b62018-11-14 11:26:05 -080023#include <map>
Marco Nelissen0b164472018-05-30 12:16:56 -070024
25#include <utils/Errors.h>
26#include <utils/Log.h>
27#include <utils/RefBase.h>
28#include <media/MediaExtractorPluginApi.h>
Marco Nelissen0e043b62018-11-14 11:26:05 -080029#include <media/NdkMediaFormat.h>
Marco Nelissen0b164472018-05-30 12:16:56 -070030
31namespace android {
32
33class DataSourceBase;
34class MetaDataBase;
35struct MediaTrack;
36
Marco Nelissen2a3363a2018-09-13 13:15:30 -070037
38class MediaTrackHelper {
39public:
40 virtual ~MediaTrackHelper() {};
Marco Nelissen3db2dcc2018-10-03 14:09:37 -070041 virtual status_t start() = 0;
Marco Nelissen2a3363a2018-09-13 13:15:30 -070042 virtual status_t stop() = 0;
43 virtual status_t getFormat(MetaDataBase& format) = 0;
44
45 class ReadOptions {
46 public:
47 enum SeekMode : int32_t {
48 SEEK_PREVIOUS_SYNC,
49 SEEK_NEXT_SYNC,
50 SEEK_CLOSEST_SYNC,
51 SEEK_CLOSEST,
52 SEEK_FRAME_INDEX,
53 };
54
55 ReadOptions(uint32_t options, int64_t seekPosUs) {
56 mOptions = options;
57 mSeekPosUs = seekPosUs;
58 }
59 bool getSeekTo(int64_t *time_us, SeekMode *mode) const {
60 if ((mOptions & CMediaTrackReadOptions::SEEK) == 0) {
61 return false;
62 }
63 *time_us = mSeekPosUs;
64 *mode = (SeekMode) (mOptions & 7);
65 return true;
66 }
67 bool getNonBlocking() const {
68 return mOptions & CMediaTrackReadOptions::NONBLOCKING;
69 }
70 private:
71 uint32_t mOptions;
72 int64_t mSeekPosUs;
73 };
74
75 virtual status_t read(
76 MediaBufferBase **buffer, const ReadOptions *options = NULL) = 0;
77 virtual bool supportsNonBlockingRead() { return false; }
78};
79
80inline CMediaTrack *wrap(MediaTrackHelper *track) {
81 CMediaTrack *wrapper = (CMediaTrack*) malloc(sizeof(CMediaTrack));
82 wrapper->data = track;
83 wrapper->free = [](void *data) -> void {
84 delete (MediaTrackHelper*)(data);
85 };
Marco Nelissen3db2dcc2018-10-03 14:09:37 -070086 wrapper->start = [](void *data) -> status_t {
87 return ((MediaTrackHelper*)data)->start();
Marco Nelissen2a3363a2018-09-13 13:15:30 -070088 };
89 wrapper->stop = [](void *data) -> status_t {
90 return ((MediaTrackHelper*)data)->stop();
91 };
92 wrapper->getFormat = [](void *data, MetaDataBase &meta) -> status_t {
93 return ((MediaTrackHelper*)data)->getFormat(meta);
94 };
95 wrapper->read = [](void *data, MediaBufferBase **buffer, uint32_t options, int64_t seekPosUs)
96 -> status_t {
97 MediaTrackHelper::ReadOptions opts(options, seekPosUs);
98 return ((MediaTrackHelper*)data)->read(buffer, &opts);
99 };
100 wrapper->supportsNonBlockingRead = [](void *data) -> bool {
101 return ((MediaTrackHelper*)data)->supportsNonBlockingRead();
102 };
103 return wrapper;
104}
105
Marco Nelissen56f19382018-09-12 15:30:59 -0700106
107class MediaTrackHelperV2 {
108public:
109 virtual ~MediaTrackHelperV2() {};
Marco Nelissen5dcf85a2018-10-11 09:49:02 -0700110 virtual media_status_t start() = 0;
111 virtual media_status_t stop() = 0;
112 virtual media_status_t getFormat(AMediaFormat *format) = 0;
Marco Nelissen56f19382018-09-12 15:30:59 -0700113
114 class ReadOptions {
115 public:
116 enum SeekMode : int32_t {
117 SEEK_PREVIOUS_SYNC,
118 SEEK_NEXT_SYNC,
119 SEEK_CLOSEST_SYNC,
120 SEEK_CLOSEST,
121 SEEK_FRAME_INDEX,
122 };
123
124 ReadOptions(uint32_t options, int64_t seekPosUs) {
125 mOptions = options;
126 mSeekPosUs = seekPosUs;
127 }
128 bool getSeekTo(int64_t *time_us, SeekMode *mode) const {
129 if ((mOptions & CMediaTrackReadOptions::SEEK) == 0) {
130 return false;
131 }
132 *time_us = mSeekPosUs;
133 *mode = (SeekMode) (mOptions & 7);
134 return true;
135 }
136 bool getNonBlocking() const {
137 return mOptions & CMediaTrackReadOptions::NONBLOCKING;
138 }
139 private:
140 uint32_t mOptions;
141 int64_t mSeekPosUs;
142 };
143
Marco Nelissen5dcf85a2018-10-11 09:49:02 -0700144 virtual media_status_t read(
Marco Nelissen56f19382018-09-12 15:30:59 -0700145 MediaBufferBase **buffer, const ReadOptions *options = NULL) = 0;
146 virtual bool supportsNonBlockingRead() { return false; }
147};
148
149inline CMediaTrackV2 *wrapV2(MediaTrackHelperV2 *track) {
150 CMediaTrackV2 *wrapper = (CMediaTrackV2*) malloc(sizeof(CMediaTrackV2));
151 wrapper->data = track;
152 wrapper->free = [](void *data) -> void {
153 delete (MediaTrackHelperV2*)(data);
154 };
Marco Nelissen5dcf85a2018-10-11 09:49:02 -0700155 wrapper->start = [](void *data) -> media_status_t {
Marco Nelissen3db2dcc2018-10-03 14:09:37 -0700156 return ((MediaTrackHelperV2*)data)->start();
Marco Nelissen56f19382018-09-12 15:30:59 -0700157 };
Marco Nelissen5dcf85a2018-10-11 09:49:02 -0700158 wrapper->stop = [](void *data) -> media_status_t {
Marco Nelissen56f19382018-09-12 15:30:59 -0700159 return ((MediaTrackHelperV2*)data)->stop();
160 };
Marco Nelissen5dcf85a2018-10-11 09:49:02 -0700161 wrapper->getFormat = [](void *data, AMediaFormat *meta) -> media_status_t {
Marco Nelissen56f19382018-09-12 15:30:59 -0700162 return ((MediaTrackHelperV2*)data)->getFormat(meta);
163 };
164 wrapper->read = [](void *data, MediaBufferBase **buffer, uint32_t options, int64_t seekPosUs)
Marco Nelissen5dcf85a2018-10-11 09:49:02 -0700165 -> media_status_t {
Marco Nelissen56f19382018-09-12 15:30:59 -0700166 MediaTrackHelperV2::ReadOptions opts(options, seekPosUs);
167 return ((MediaTrackHelperV2*)data)->read(buffer, &opts);
168 };
169 wrapper->supportsNonBlockingRead = [](void *data) -> bool {
170 return ((MediaTrackHelperV2*)data)->supportsNonBlockingRead();
171 };
172 return wrapper;
173}
174
Marco Nelissen0e043b62018-11-14 11:26:05 -0800175class MediaTrackHelperV3;
176
177class MediaBufferHelperV3 {
178private:
179 friend CMediaTrackV3 *wrapV3(MediaTrackHelperV3 *);
180 CMediaBufferV3 *mBuffer;
181public:
182 MediaBufferHelperV3(CMediaBufferV3 *buf) {
183 mBuffer = buf;
184 }
185
186 ~MediaBufferHelperV3() {}
187
188 void release() {
189 mBuffer->release(mBuffer->handle);
190 }
191
192 void* data() {
193 return mBuffer->data(mBuffer->handle);
194 }
195
196 size_t size() {
197 return mBuffer->size(mBuffer->handle);
198 }
199
200 size_t range_offset() {
201 return mBuffer->range_offset(mBuffer->handle);
202 }
203
204 size_t range_length() {
205 return mBuffer->range_length(mBuffer->handle);
206 }
207
208 void set_range(size_t offset, size_t length) {
209 mBuffer->set_range(mBuffer->handle, offset, length);
210 }
211 AMediaFormat *meta_data() {
212 return mBuffer->meta_data(mBuffer->handle);
213 }
214};
215
216class MediaBufferGroupHelperV3 {
217private:
218 CMediaBufferGroupV3 *mGroup;
219 std::map<CMediaBufferV3*, MediaBufferHelperV3*> mBufferHelpers;
220public:
221 MediaBufferGroupHelperV3(CMediaBufferGroupV3 *group) {
222 mGroup = group;
223 }
224 ~MediaBufferGroupHelperV3() {
225 // delete all entries in map
226 ALOGV("buffergroup %p map has %zu entries", this, mBufferHelpers.size());
227 for (auto it = mBufferHelpers.begin(); it != mBufferHelpers.end(); ++it) {
228 delete it->second;
229 }
230 }
231 bool init(size_t buffers, size_t buffer_size, size_t growthLimit = 0) {
232 return mGroup->init(mGroup->handle, buffers, buffer_size, growthLimit);
233 }
234 void add_buffer(size_t size) {
235 mGroup->add_buffer(mGroup->handle, size);
236 }
237 media_status_t acquire_buffer(
238 MediaBufferHelperV3 **buffer, bool nonBlocking = false, size_t requestedSize = 0) {
239 CMediaBufferV3 *buf = nullptr;
240 media_status_t ret =
241 mGroup->acquire_buffer(mGroup->handle, &buf, nonBlocking, requestedSize);
242 if (ret == AMEDIA_OK && buf != nullptr) {
243 auto helper = mBufferHelpers.find(buf);
244 if (helper == mBufferHelpers.end()) {
245 MediaBufferHelperV3* newHelper = new MediaBufferHelperV3(buf);
246 mBufferHelpers.insert(std::make_pair(buf, newHelper));
247 *buffer = newHelper;
248 } else {
249 *buffer = helper->second;
250 }
251 } else {
252 *buffer = nullptr;
253 }
254 return ret;
255 }
256 bool has_buffers() {
257 return mGroup->has_buffers(mGroup->handle);
258 }
259};
260
261class MediaTrackHelperV3 {
262public:
263 MediaTrackHelperV3() : mBufferGroup(nullptr) {
264 }
265 virtual ~MediaTrackHelperV3() {
266 delete mBufferGroup;
267 }
268 virtual media_status_t start() = 0;
269 virtual media_status_t stop() = 0;
270 virtual media_status_t getFormat(AMediaFormat *format) = 0;
271
272 class ReadOptions {
273 public:
274 enum SeekMode : int32_t {
275 SEEK_PREVIOUS_SYNC,
276 SEEK_NEXT_SYNC,
277 SEEK_CLOSEST_SYNC,
278 SEEK_CLOSEST,
279 SEEK_FRAME_INDEX,
280 };
281
282 ReadOptions(uint32_t options, int64_t seekPosUs) {
283 mOptions = options;
284 mSeekPosUs = seekPosUs;
285 }
286 bool getSeekTo(int64_t *time_us, SeekMode *mode) const {
287 if ((mOptions & CMediaTrackReadOptions::SEEK) == 0) {
288 return false;
289 }
290 *time_us = mSeekPosUs;
291 *mode = (SeekMode) (mOptions & 7);
292 return true;
293 }
294 bool getNonBlocking() const {
295 return mOptions & CMediaTrackReadOptions::NONBLOCKING;
296 }
297 private:
298 uint32_t mOptions;
299 int64_t mSeekPosUs;
300 };
301
302 virtual media_status_t read(
303 MediaBufferHelperV3 **buffer, const ReadOptions *options = NULL) = 0;
304 virtual bool supportsNonBlockingRead() { return false; }
305protected:
306 friend CMediaTrackV3 *wrapV3(MediaTrackHelperV3 *track);
307 MediaBufferGroupHelperV3 *mBufferGroup;
308};
309
310inline CMediaTrackV3 *wrapV3(MediaTrackHelperV3 *track) {
311 CMediaTrackV3 *wrapper = (CMediaTrackV3*) malloc(sizeof(CMediaTrackV3));
312 wrapper->data = track;
313 wrapper->free = [](void *data) -> void {
314 delete (MediaTrackHelperV3*)(data);
315 };
316 wrapper->start = [](void *data, CMediaBufferGroupV3 *bufferGroup) -> media_status_t {
317 if (((MediaTrackHelperV3*)data)->mBufferGroup) {
318 // this shouldn't happen, but handle it anyway
319 delete ((MediaTrackHelperV3*)data)->mBufferGroup;
320 }
321 ((MediaTrackHelperV3*)data)->mBufferGroup = new MediaBufferGroupHelperV3(bufferGroup);
322 return ((MediaTrackHelperV3*)data)->start();
323 };
324 wrapper->stop = [](void *data) -> media_status_t {
325 return ((MediaTrackHelperV3*)data)->stop();
326 };
327 wrapper->getFormat = [](void *data, AMediaFormat *meta) -> media_status_t {
328 return ((MediaTrackHelperV3*)data)->getFormat(meta);
329 };
330 wrapper->read = [](void *data, CMediaBufferV3 **buffer, uint32_t options, int64_t seekPosUs)
331 -> media_status_t {
332 MediaTrackHelperV3::ReadOptions opts(options, seekPosUs);
333 MediaBufferHelperV3 *buf = NULL;
334 media_status_t ret = ((MediaTrackHelperV3*)data)->read(&buf, &opts);
335 if (ret == AMEDIA_OK && buf != nullptr) {
336 *buffer = buf->mBuffer;
337 }
338 return ret;
339 };
340 wrapper->supportsNonBlockingRead = [](void *data) -> bool {
341 return ((MediaTrackHelperV3*)data)->supportsNonBlockingRead();
342 };
343 return wrapper;
344}
Marco Nelissen56f19382018-09-12 15:30:59 -0700345
346
Marco Nelissen0b164472018-05-30 12:16:56 -0700347// extractor plugins can derive from this class which looks remarkably
348// like MediaExtractor and can be easily wrapped in the required C API
349class MediaExtractorPluginHelper
350{
351public:
352 virtual ~MediaExtractorPluginHelper() {}
353 virtual size_t countTracks() = 0;
Marco Nelissen2a3363a2018-09-13 13:15:30 -0700354 virtual MediaTrackHelper *getTrack(size_t index) = 0;
Marco Nelissen0b164472018-05-30 12:16:56 -0700355
356 enum GetTrackMetaDataFlags {
357 kIncludeExtensiveMetaData = 1
358 };
359 virtual status_t getTrackMetaData(
360 MetaDataBase& meta,
361 size_t index, uint32_t flags = 0) = 0;
362
363 // Return container specific meta-data. The default implementation
364 // returns an empty metadata object.
365 virtual status_t getMetaData(MetaDataBase& meta) = 0;
366
367 enum Flags {
368 CAN_SEEK_BACKWARD = 1, // the "seek 10secs back button"
369 CAN_SEEK_FORWARD = 2, // the "seek 10secs forward button"
370 CAN_PAUSE = 4,
371 CAN_SEEK = 8, // the "seek bar"
372 };
373
374 // If subclasses do _not_ override this, the default is
375 // CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK | CAN_PAUSE
376 virtual uint32_t flags() const {
377 return CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK | CAN_PAUSE;
378 };
379
380 virtual status_t setMediaCas(const uint8_t* /*casToken*/, size_t /*size*/) {
381 return INVALID_OPERATION;
382 }
383
384 virtual const char * name() { return "<unspecified>"; }
385
386protected:
387 MediaExtractorPluginHelper() {}
388
389private:
390 MediaExtractorPluginHelper(const MediaExtractorPluginHelper &);
391 MediaExtractorPluginHelper &operator=(const MediaExtractorPluginHelper &);
392};
393
394inline CMediaExtractor *wrap(MediaExtractorPluginHelper *extractor) {
395 CMediaExtractor *wrapper = (CMediaExtractor*) malloc(sizeof(CMediaExtractor));
396 wrapper->data = extractor;
397 wrapper->free = [](void *data) -> void {
398 delete (MediaExtractorPluginHelper*)(data);
399 };
400 wrapper->countTracks = [](void *data) -> size_t {
401 return ((MediaExtractorPluginHelper*)data)->countTracks();
402 };
Marco Nelissen2a3363a2018-09-13 13:15:30 -0700403 wrapper->getTrack = [](void *data, size_t index) -> CMediaTrack* {
404 return wrap(((MediaExtractorPluginHelper*)data)->getTrack(index));
Marco Nelissen0b164472018-05-30 12:16:56 -0700405 };
406 wrapper->getTrackMetaData = [](
407 void *data,
408 MetaDataBase& meta,
409 size_t index, uint32_t flags) -> status_t {
410 return ((MediaExtractorPluginHelper*)data)->getTrackMetaData(meta, index, flags);
411 };
412 wrapper->getMetaData = [](
413 void *data,
414 MetaDataBase& meta) -> status_t {
415 return ((MediaExtractorPluginHelper*)data)->getMetaData(meta);
416 };
417 wrapper->flags = [](
418 void *data) -> uint32_t {
419 return ((MediaExtractorPluginHelper*)data)->flags();
420 };
421 wrapper->setMediaCas = [](
422 void *data, const uint8_t *casToken, size_t size) -> status_t {
423 return ((MediaExtractorPluginHelper*)data)->setMediaCas(casToken, size);
424 };
425 wrapper->name = [](
426 void *data) -> const char * {
427 return ((MediaExtractorPluginHelper*)data)->name();
428 };
429 return wrapper;
430}
431
Marco Nelissen56f19382018-09-12 15:30:59 -0700432class MediaExtractorPluginHelperV2
433{
434public:
435 virtual ~MediaExtractorPluginHelperV2() {}
436 virtual size_t countTracks() = 0;
437 virtual MediaTrackHelperV2 *getTrack(size_t index) = 0;
438
439 enum GetTrackMetaDataFlags {
440 kIncludeExtensiveMetaData = 1
441 };
Marco Nelissen5dcf85a2018-10-11 09:49:02 -0700442 virtual media_status_t getTrackMetaData(
Marco Nelissen56f19382018-09-12 15:30:59 -0700443 AMediaFormat *meta,
444 size_t index, uint32_t flags = 0) = 0;
445
446 // Return container specific meta-data. The default implementation
447 // returns an empty metadata object.
Marco Nelissen5dcf85a2018-10-11 09:49:02 -0700448 virtual media_status_t getMetaData(AMediaFormat *meta) = 0;
Marco Nelissen56f19382018-09-12 15:30:59 -0700449
450 enum Flags {
451 CAN_SEEK_BACKWARD = 1, // the "seek 10secs back button"
452 CAN_SEEK_FORWARD = 2, // the "seek 10secs forward button"
453 CAN_PAUSE = 4,
454 CAN_SEEK = 8, // the "seek bar"
455 };
456
457 // If subclasses do _not_ override this, the default is
458 // CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK | CAN_PAUSE
459 virtual uint32_t flags() const {
460 return CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK | CAN_PAUSE;
461 };
462
Marco Nelissen5dcf85a2018-10-11 09:49:02 -0700463 virtual media_status_t setMediaCas(const uint8_t* /*casToken*/, size_t /*size*/) {
464 return AMEDIA_ERROR_INVALID_OPERATION;
Marco Nelissen56f19382018-09-12 15:30:59 -0700465 }
466
467 virtual const char * name() { return "<unspecified>"; }
468
469protected:
470 MediaExtractorPluginHelperV2() {}
471
472private:
473 MediaExtractorPluginHelperV2(const MediaExtractorPluginHelperV2 &);
474 MediaExtractorPluginHelperV2 &operator=(const MediaExtractorPluginHelperV2 &);
475};
476
477inline CMediaExtractorV2 *wrapV2(MediaExtractorPluginHelperV2 *extractor) {
478 CMediaExtractorV2 *wrapper = (CMediaExtractorV2*) malloc(sizeof(CMediaExtractorV2));
479 wrapper->data = extractor;
480 wrapper->free = [](void *data) -> void {
481 delete (MediaExtractorPluginHelperV2*)(data);
482 };
483 wrapper->countTracks = [](void *data) -> size_t {
484 return ((MediaExtractorPluginHelperV2*)data)->countTracks();
485 };
486 wrapper->getTrack = [](void *data, size_t index) -> CMediaTrackV2* {
487 return wrapV2(((MediaExtractorPluginHelperV2*)data)->getTrack(index));
488 };
489 wrapper->getTrackMetaData = [](
490 void *data,
491 AMediaFormat *meta,
Marco Nelissen5dcf85a2018-10-11 09:49:02 -0700492 size_t index, uint32_t flags) -> media_status_t {
Marco Nelissen56f19382018-09-12 15:30:59 -0700493 return ((MediaExtractorPluginHelperV2*)data)->getTrackMetaData(meta, index, flags);
494 };
495 wrapper->getMetaData = [](
496 void *data,
Marco Nelissen5dcf85a2018-10-11 09:49:02 -0700497 AMediaFormat *meta) -> media_status_t {
Marco Nelissen56f19382018-09-12 15:30:59 -0700498 return ((MediaExtractorPluginHelperV2*)data)->getMetaData(meta);
499 };
500 wrapper->flags = [](
501 void *data) -> uint32_t {
502 return ((MediaExtractorPluginHelperV2*)data)->flags();
503 };
504 wrapper->setMediaCas = [](
Marco Nelissen5dcf85a2018-10-11 09:49:02 -0700505 void *data, const uint8_t *casToken, size_t size) -> media_status_t {
Marco Nelissen56f19382018-09-12 15:30:59 -0700506 return ((MediaExtractorPluginHelperV2*)data)->setMediaCas(casToken, size);
507 };
508 wrapper->name = [](
509 void *data) -> const char * {
510 return ((MediaExtractorPluginHelperV2*)data)->name();
511 };
512 return wrapper;
513}
514
Marco Nelissen0e043b62018-11-14 11:26:05 -0800515class MediaExtractorPluginHelperV3
516{
517public:
518 virtual ~MediaExtractorPluginHelperV3() {}
519 virtual size_t countTracks() = 0;
520 virtual MediaTrackHelperV3 *getTrack(size_t index) = 0;
521
522 enum GetTrackMetaDataFlags {
523 kIncludeExtensiveMetaData = 1
524 };
525 virtual media_status_t getTrackMetaData(
526 AMediaFormat *meta,
527 size_t index, uint32_t flags = 0) = 0;
528
529 // Return container specific meta-data. The default implementation
530 // returns an empty metadata object.
531 virtual media_status_t getMetaData(AMediaFormat *meta) = 0;
532
533 enum Flags {
534 CAN_SEEK_BACKWARD = 1, // the "seek 10secs back button"
535 CAN_SEEK_FORWARD = 2, // the "seek 10secs forward button"
536 CAN_PAUSE = 4,
537 CAN_SEEK = 8, // the "seek bar"
538 };
539
540 // If subclasses do _not_ override this, the default is
541 // CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK | CAN_PAUSE
542 virtual uint32_t flags() const {
543 return CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK | CAN_PAUSE;
544 };
545
546 virtual media_status_t setMediaCas(const uint8_t* /*casToken*/, size_t /*size*/) {
547 return AMEDIA_ERROR_INVALID_OPERATION;
548 }
549
550 virtual const char * name() { return "<unspecified>"; }
551
552protected:
553 MediaExtractorPluginHelperV3() {}
554
555private:
556 MediaExtractorPluginHelperV3(const MediaExtractorPluginHelperV2 &);
557 MediaExtractorPluginHelperV3 &operator=(const MediaExtractorPluginHelperV2 &);
558};
559
560inline CMediaExtractorV3 *wrapV3(MediaExtractorPluginHelperV3 *extractor) {
561 CMediaExtractorV3 *wrapper = (CMediaExtractorV3*) malloc(sizeof(CMediaExtractorV3));
562 wrapper->data = extractor;
563 wrapper->free = [](void *data) -> void {
564 delete (MediaExtractorPluginHelperV3*)(data);
565 };
566 wrapper->countTracks = [](void *data) -> size_t {
567 return ((MediaExtractorPluginHelperV3*)data)->countTracks();
568 };
569 wrapper->getTrack = [](void *data, size_t index) -> CMediaTrackV3* {
570 return wrapV3(((MediaExtractorPluginHelperV3*)data)->getTrack(index));
571 };
572 wrapper->getTrackMetaData = [](
573 void *data,
574 AMediaFormat *meta,
575 size_t index, uint32_t flags) -> media_status_t {
576 return ((MediaExtractorPluginHelperV3*)data)->getTrackMetaData(meta, index, flags);
577 };
578 wrapper->getMetaData = [](
579 void *data,
580 AMediaFormat *meta) -> media_status_t {
581 return ((MediaExtractorPluginHelperV3*)data)->getMetaData(meta);
582 };
583 wrapper->flags = [](
584 void *data) -> uint32_t {
585 return ((MediaExtractorPluginHelperV3*)data)->flags();
586 };
587 wrapper->setMediaCas = [](
588 void *data, const uint8_t *casToken, size_t size) -> media_status_t {
589 return ((MediaExtractorPluginHelperV3*)data)->setMediaCas(casToken, size);
590 };
591 wrapper->name = [](
592 void *data) -> const char * {
593 return ((MediaExtractorPluginHelperV3*)data)->name();
594 };
595 return wrapper;
596}
597
Marco Nelissencec44d02018-06-17 22:21:09 -0700598/* adds some convience methods */
599class DataSourceHelper {
600public:
601 explicit DataSourceHelper(CDataSource *csource) {
602 mSource = csource;
603 }
604
605 explicit DataSourceHelper(DataSourceHelper *source) {
606 mSource = source->mSource;
607 }
608
Marco Nelissenc2b10b32018-09-24 13:19:43 -0700609 virtual ~DataSourceHelper() {}
610
611 virtual ssize_t readAt(off64_t offset, void *data, size_t size) {
Marco Nelissencec44d02018-06-17 22:21:09 -0700612 return mSource->readAt(mSource->handle, offset, data, size);
613 }
614
Marco Nelissenc2b10b32018-09-24 13:19:43 -0700615 virtual status_t getSize(off64_t *size) {
Marco Nelissencec44d02018-06-17 22:21:09 -0700616 return mSource->getSize(mSource->handle, size);
617 }
618
619 bool getUri(char *uriString, size_t bufferSize) {
620 return mSource->getUri(mSource->handle, uriString, bufferSize);
621 }
622
Marco Nelissenc2b10b32018-09-24 13:19:43 -0700623 virtual uint32_t flags() {
Marco Nelissencec44d02018-06-17 22:21:09 -0700624 return mSource->flags(mSource->handle);
625 }
626
627 // Convenience methods:
628 bool getUInt16(off64_t offset, uint16_t *x) {
629 *x = 0;
630
631 uint8_t byte[2];
632 if (readAt(offset, byte, 2) != 2) {
633 return false;
634 }
635
636 *x = (byte[0] << 8) | byte[1];
637
638 return true;
639 }
640
641 // 3 byte int, returned as a 32-bit int
642 bool getUInt24(off64_t offset, uint32_t *x) {
643 *x = 0;
644
645 uint8_t byte[3];
646 if (readAt(offset, byte, 3) != 3) {
647 return false;
648 }
649
650 *x = (byte[0] << 16) | (byte[1] << 8) | byte[2];
651
652 return true;
653 }
654
655 bool getUInt32(off64_t offset, uint32_t *x) {
656 *x = 0;
657
658 uint32_t tmp;
659 if (readAt(offset, &tmp, 4) != 4) {
660 return false;
661 }
662
663 *x = ntohl(tmp);
664
665 return true;
666 }
667
668 bool getUInt64(off64_t offset, uint64_t *x) {
669 *x = 0;
670
671 uint64_t tmp;
672 if (readAt(offset, &tmp, 8) != 8) {
673 return false;
674 }
675
676 *x = ((uint64_t)ntohl(tmp & 0xffffffff) << 32) | ntohl(tmp >> 32);
677
678 return true;
679 }
680
681 // read either int<N> or int<2N> into a uint<2N>_t, size is the int size in bytes.
682 bool getUInt16Var(off64_t offset, uint16_t *x, size_t size) {
683 if (size == 2) {
684 return getUInt16(offset, x);
685 }
686 if (size == 1) {
687 uint8_t tmp;
688 if (readAt(offset, &tmp, 1) == 1) {
689 *x = tmp;
690 return true;
691 }
692 }
693 return false;
694 }
695
696 bool getUInt32Var(off64_t offset, uint32_t *x, size_t size) {
697 if (size == 4) {
698 return getUInt32(offset, x);
699 }
700 if (size == 2) {
701 uint16_t tmp;
702 if (getUInt16(offset, &tmp)) {
703 *x = tmp;
704 return true;
705 }
706 }
707 return false;
708 }
709
710 bool getUInt64Var(off64_t offset, uint64_t *x, size_t size) {
711 if (size == 8) {
712 return getUInt64(offset, x);
713 }
714 if (size == 4) {
715 uint32_t tmp;
716 if (getUInt32(offset, &tmp)) {
717 *x = tmp;
718 return true;
719 }
720 }
721 return false;
722 }
723
724protected:
725 CDataSource *mSource;
726};
727
728
729
Marco Nelissen0b164472018-05-30 12:16:56 -0700730// helpers to create a media_uuid_t from a string literal
731
732// purposely not defined anywhere so that this will fail to link if
733// expressions below are not evaluated at compile time
734int invalid_uuid_string(const char *);
735
736template <typename T, size_t N>
737constexpr uint8_t _digitAt_(const T (&s)[N], const size_t n) {
738 return s[n] >= '0' && s[n] <= '9' ? s[n] - '0'
739 : s[n] >= 'a' && s[n] <= 'f' ? s[n] - 'a' + 10
740 : s[n] >= 'A' && s[n] <= 'F' ? s[n] - 'A' + 10
741 : invalid_uuid_string("uuid: bad digits");
742}
743
744template <typename T, size_t N>
745constexpr uint8_t _hexByteAt_(const T (&s)[N], size_t n) {
746 return (_digitAt_(s, n) << 4) + _digitAt_(s, n + 1);
747}
748
749constexpr bool _assertIsDash_(char c) {
750 return c == '-' ? true : invalid_uuid_string("Wrong format");
751}
752
753template <size_t N>
754constexpr media_uuid_t constUUID(const char (&s) [N]) {
755 static_assert(N == 37, "uuid: wrong length");
756 return
757 _assertIsDash_(s[8]),
758 _assertIsDash_(s[13]),
759 _assertIsDash_(s[18]),
760 _assertIsDash_(s[23]),
761 media_uuid_t {{
762 _hexByteAt_(s, 0),
763 _hexByteAt_(s, 2),
764 _hexByteAt_(s, 4),
765 _hexByteAt_(s, 6),
766 _hexByteAt_(s, 9),
767 _hexByteAt_(s, 11),
768 _hexByteAt_(s, 14),
769 _hexByteAt_(s, 16),
770 _hexByteAt_(s, 19),
771 _hexByteAt_(s, 21),
772 _hexByteAt_(s, 24),
773 _hexByteAt_(s, 26),
774 _hexByteAt_(s, 28),
775 _hexByteAt_(s, 30),
776 _hexByteAt_(s, 32),
777 _hexByteAt_(s, 34),
778 }};
779}
780// Convenience macro to create a media_uuid_t from a string literal, which should
781// be formatted as "12345678-1234-1234-1234-123456789abc", as generated by
782// e.g. https://www.uuidgenerator.net/ or the 'uuidgen' linux command.
783// Hex digits may be upper or lower case.
784//
785// The macro call is otherwise equivalent to specifying the structure directly
786// (e.g. UUID("7d613858-5837-4a38-84c5-332d1cddee27") is the same as
787// {{0x7d, 0x61, 0x38, 0x58, 0x58, 0x37, 0x4a, 0x38,
788// 0x84, 0xc5, 0x33, 0x2d, 0x1c, 0xdd, 0xee, 0x27}})
789
790#define UUID(str) []{ constexpr media_uuid_t uuid = constUUID(str); return uuid; }()
791
792} // namespace android
793
794#endif // MEDIA_EXTRACTOR_PLUGIN_HELPER_H_