| Marco Nelissen | 0b16447 | 2018-05-30 12:16:56 -0700 | [diff] [blame] | 1 | /* | 
 | 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 Nelissen | cec44d0 | 2018-06-17 22:21:09 -0700 | [diff] [blame] | 21 | #include <arpa/inet.h> | 
| Marco Nelissen | 0b16447 | 2018-05-30 12:16:56 -0700 | [diff] [blame] | 22 | #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 |  | 
 | 30 | namespace android { | 
 | 31 |  | 
 | 32 | class DataSourceBase; | 
 | 33 | class MetaDataBase; | 
 | 34 | struct MediaTrack; | 
 | 35 |  | 
| Marco Nelissen | 2a3363a | 2018-09-13 13:15:30 -0700 | [diff] [blame] | 36 |  | 
 | 37 | class MediaTrackHelper { | 
 | 38 | public: | 
 | 39 |     virtual ~MediaTrackHelper() {}; | 
 | 40 |     virtual status_t start(MetaDataBase *params = NULL) = 0; | 
 | 41 |     virtual status_t stop() = 0; | 
 | 42 |     virtual status_t getFormat(MetaDataBase& format) = 0; | 
 | 43 |  | 
 | 44 |     class ReadOptions { | 
 | 45 |     public: | 
 | 46 |         enum SeekMode : int32_t { | 
 | 47 |             SEEK_PREVIOUS_SYNC, | 
 | 48 |             SEEK_NEXT_SYNC, | 
 | 49 |             SEEK_CLOSEST_SYNC, | 
 | 50 |             SEEK_CLOSEST, | 
 | 51 |             SEEK_FRAME_INDEX, | 
 | 52 |         }; | 
 | 53 |  | 
 | 54 |         ReadOptions(uint32_t options, int64_t seekPosUs) { | 
 | 55 |             mOptions = options; | 
 | 56 |             mSeekPosUs = seekPosUs; | 
 | 57 |         } | 
 | 58 |         bool getSeekTo(int64_t *time_us, SeekMode *mode) const { | 
 | 59 |             if ((mOptions & CMediaTrackReadOptions::SEEK) == 0) { | 
 | 60 |                 return false; | 
 | 61 |             } | 
 | 62 |             *time_us = mSeekPosUs; | 
 | 63 |             *mode = (SeekMode) (mOptions & 7); | 
 | 64 |             return true; | 
 | 65 |         } | 
 | 66 |         bool getNonBlocking() const { | 
 | 67 |             return mOptions & CMediaTrackReadOptions::NONBLOCKING; | 
 | 68 |         } | 
 | 69 |     private: | 
 | 70 |         uint32_t mOptions; | 
 | 71 |         int64_t mSeekPosUs; | 
 | 72 |     }; | 
 | 73 |  | 
 | 74 |     virtual status_t read( | 
 | 75 |             MediaBufferBase **buffer, const ReadOptions *options = NULL) = 0; | 
 | 76 |     virtual bool supportsNonBlockingRead() { return false; } | 
 | 77 | }; | 
 | 78 |  | 
 | 79 | inline CMediaTrack *wrap(MediaTrackHelper *track) { | 
 | 80 |     CMediaTrack *wrapper = (CMediaTrack*) malloc(sizeof(CMediaTrack)); | 
 | 81 |     wrapper->data = track; | 
 | 82 |     wrapper->free = [](void *data) -> void { | 
 | 83 |         delete (MediaTrackHelper*)(data); | 
 | 84 |     }; | 
 | 85 |     wrapper->start = [](void *data, MetaDataBase *params) -> status_t { | 
 | 86 |         return ((MediaTrackHelper*)data)->start(params); | 
 | 87 |     }; | 
 | 88 |     wrapper->stop = [](void *data) -> status_t { | 
 | 89 |         return ((MediaTrackHelper*)data)->stop(); | 
 | 90 |     }; | 
 | 91 |     wrapper->getFormat = [](void *data, MetaDataBase &meta) -> status_t { | 
 | 92 |         return ((MediaTrackHelper*)data)->getFormat(meta); | 
 | 93 |     }; | 
 | 94 |     wrapper->read = [](void *data, MediaBufferBase **buffer,  uint32_t options, int64_t seekPosUs) | 
 | 95 |             -> status_t { | 
 | 96 |         MediaTrackHelper::ReadOptions opts(options, seekPosUs); | 
 | 97 |         return ((MediaTrackHelper*)data)->read(buffer, &opts); | 
 | 98 |     }; | 
 | 99 |     wrapper->supportsNonBlockingRead = [](void *data) -> bool { | 
 | 100 |                 return ((MediaTrackHelper*)data)->supportsNonBlockingRead(); | 
 | 101 |     }; | 
 | 102 |     return wrapper; | 
 | 103 | } | 
 | 104 |  | 
| Marco Nelissen | 56f1938 | 2018-09-12 15:30:59 -0700 | [diff] [blame^] | 105 |  | 
 | 106 | class MediaTrackHelperV2 { | 
 | 107 | public: | 
 | 108 |     virtual ~MediaTrackHelperV2() {}; | 
 | 109 |     virtual status_t start(AMediaFormat *params = NULL) = 0; | 
 | 110 |     virtual status_t stop() = 0; | 
 | 111 |     virtual status_t getFormat(AMediaFormat *format) = 0; | 
 | 112 |  | 
 | 113 |     class ReadOptions { | 
 | 114 |     public: | 
 | 115 |         enum SeekMode : int32_t { | 
 | 116 |             SEEK_PREVIOUS_SYNC, | 
 | 117 |             SEEK_NEXT_SYNC, | 
 | 118 |             SEEK_CLOSEST_SYNC, | 
 | 119 |             SEEK_CLOSEST, | 
 | 120 |             SEEK_FRAME_INDEX, | 
 | 121 |         }; | 
 | 122 |  | 
 | 123 |         ReadOptions(uint32_t options, int64_t seekPosUs) { | 
 | 124 |             mOptions = options; | 
 | 125 |             mSeekPosUs = seekPosUs; | 
 | 126 |         } | 
 | 127 |         bool getSeekTo(int64_t *time_us, SeekMode *mode) const { | 
 | 128 |             if ((mOptions & CMediaTrackReadOptions::SEEK) == 0) { | 
 | 129 |                 return false; | 
 | 130 |             } | 
 | 131 |             *time_us = mSeekPosUs; | 
 | 132 |             *mode = (SeekMode) (mOptions & 7); | 
 | 133 |             return true; | 
 | 134 |         } | 
 | 135 |         bool getNonBlocking() const { | 
 | 136 |             return mOptions & CMediaTrackReadOptions::NONBLOCKING; | 
 | 137 |         } | 
 | 138 |     private: | 
 | 139 |         uint32_t mOptions; | 
 | 140 |         int64_t mSeekPosUs; | 
 | 141 |     }; | 
 | 142 |  | 
 | 143 |     virtual status_t read( | 
 | 144 |             MediaBufferBase **buffer, const ReadOptions *options = NULL) = 0; | 
 | 145 |     virtual bool supportsNonBlockingRead() { return false; } | 
 | 146 | }; | 
 | 147 |  | 
 | 148 | inline CMediaTrackV2 *wrapV2(MediaTrackHelperV2 *track) { | 
 | 149 |     CMediaTrackV2 *wrapper = (CMediaTrackV2*) malloc(sizeof(CMediaTrackV2)); | 
 | 150 |     wrapper->data = track; | 
 | 151 |     wrapper->free = [](void *data) -> void { | 
 | 152 |         delete (MediaTrackHelperV2*)(data); | 
 | 153 |     }; | 
 | 154 |     wrapper->start = [](void *data, AMediaFormat *params) -> status_t { | 
 | 155 |         return ((MediaTrackHelperV2*)data)->start(params); | 
 | 156 |     }; | 
 | 157 |     wrapper->stop = [](void *data) -> status_t { | 
 | 158 |         return ((MediaTrackHelperV2*)data)->stop(); | 
 | 159 |     }; | 
 | 160 |     wrapper->getFormat = [](void *data, AMediaFormat *meta) -> status_t { | 
 | 161 |         return ((MediaTrackHelperV2*)data)->getFormat(meta); | 
 | 162 |     }; | 
 | 163 |     wrapper->read = [](void *data, MediaBufferBase **buffer,  uint32_t options, int64_t seekPosUs) | 
 | 164 |             -> status_t { | 
 | 165 |         MediaTrackHelperV2::ReadOptions opts(options, seekPosUs); | 
 | 166 |         return ((MediaTrackHelperV2*)data)->read(buffer, &opts); | 
 | 167 |     }; | 
 | 168 |     wrapper->supportsNonBlockingRead = [](void *data) -> bool { | 
 | 169 |                 return ((MediaTrackHelperV2*)data)->supportsNonBlockingRead(); | 
 | 170 |     }; | 
 | 171 |     return wrapper; | 
 | 172 | } | 
 | 173 |  | 
 | 174 |  | 
 | 175 |  | 
| Marco Nelissen | 0b16447 | 2018-05-30 12:16:56 -0700 | [diff] [blame] | 176 | // extractor plugins can derive from this class which looks remarkably | 
 | 177 | // like MediaExtractor and can be easily wrapped in the required C API | 
 | 178 | class MediaExtractorPluginHelper | 
 | 179 | { | 
 | 180 | public: | 
 | 181 |     virtual ~MediaExtractorPluginHelper() {} | 
 | 182 |     virtual size_t countTracks() = 0; | 
| Marco Nelissen | 2a3363a | 2018-09-13 13:15:30 -0700 | [diff] [blame] | 183 |     virtual MediaTrackHelper *getTrack(size_t index) = 0; | 
| Marco Nelissen | 0b16447 | 2018-05-30 12:16:56 -0700 | [diff] [blame] | 184 |  | 
 | 185 |     enum GetTrackMetaDataFlags { | 
 | 186 |         kIncludeExtensiveMetaData = 1 | 
 | 187 |     }; | 
 | 188 |     virtual status_t getTrackMetaData( | 
 | 189 |             MetaDataBase& meta, | 
 | 190 |             size_t index, uint32_t flags = 0) = 0; | 
 | 191 |  | 
 | 192 |     // Return container specific meta-data. The default implementation | 
 | 193 |     // returns an empty metadata object. | 
 | 194 |     virtual status_t getMetaData(MetaDataBase& meta) = 0; | 
 | 195 |  | 
 | 196 |     enum Flags { | 
 | 197 |         CAN_SEEK_BACKWARD  = 1,  // the "seek 10secs back button" | 
 | 198 |         CAN_SEEK_FORWARD   = 2,  // the "seek 10secs forward button" | 
 | 199 |         CAN_PAUSE          = 4, | 
 | 200 |         CAN_SEEK           = 8,  // the "seek bar" | 
 | 201 |     }; | 
 | 202 |  | 
 | 203 |     // If subclasses do _not_ override this, the default is | 
 | 204 |     // CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK | CAN_PAUSE | 
 | 205 |     virtual uint32_t flags() const { | 
 | 206 |         return CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK | CAN_PAUSE; | 
 | 207 |     }; | 
 | 208 |  | 
 | 209 |     virtual status_t setMediaCas(const uint8_t* /*casToken*/, size_t /*size*/) { | 
 | 210 |         return INVALID_OPERATION; | 
 | 211 |     } | 
 | 212 |  | 
 | 213 |     virtual const char * name() { return "<unspecified>"; } | 
 | 214 |  | 
 | 215 | protected: | 
 | 216 |     MediaExtractorPluginHelper() {} | 
 | 217 |  | 
 | 218 | private: | 
 | 219 |     MediaExtractorPluginHelper(const MediaExtractorPluginHelper &); | 
 | 220 |     MediaExtractorPluginHelper &operator=(const MediaExtractorPluginHelper &); | 
 | 221 | }; | 
 | 222 |  | 
 | 223 | inline CMediaExtractor *wrap(MediaExtractorPluginHelper *extractor) { | 
 | 224 |     CMediaExtractor *wrapper = (CMediaExtractor*) malloc(sizeof(CMediaExtractor)); | 
 | 225 |     wrapper->data = extractor; | 
 | 226 |     wrapper->free = [](void *data) -> void { | 
 | 227 |         delete (MediaExtractorPluginHelper*)(data); | 
 | 228 |     }; | 
 | 229 |     wrapper->countTracks = [](void *data) -> size_t { | 
 | 230 |         return ((MediaExtractorPluginHelper*)data)->countTracks(); | 
 | 231 |     }; | 
| Marco Nelissen | 2a3363a | 2018-09-13 13:15:30 -0700 | [diff] [blame] | 232 |     wrapper->getTrack = [](void *data, size_t index) -> CMediaTrack* { | 
 | 233 |         return wrap(((MediaExtractorPluginHelper*)data)->getTrack(index)); | 
| Marco Nelissen | 0b16447 | 2018-05-30 12:16:56 -0700 | [diff] [blame] | 234 |     }; | 
 | 235 |     wrapper->getTrackMetaData = []( | 
 | 236 |             void *data, | 
 | 237 |             MetaDataBase& meta, | 
 | 238 |             size_t index, uint32_t flags) -> status_t { | 
 | 239 |         return ((MediaExtractorPluginHelper*)data)->getTrackMetaData(meta, index, flags); | 
 | 240 |     }; | 
 | 241 |     wrapper->getMetaData = []( | 
 | 242 |             void *data, | 
 | 243 |             MetaDataBase& meta) -> status_t { | 
 | 244 |         return ((MediaExtractorPluginHelper*)data)->getMetaData(meta); | 
 | 245 |     }; | 
 | 246 |     wrapper->flags = []( | 
 | 247 |             void *data) -> uint32_t { | 
 | 248 |         return ((MediaExtractorPluginHelper*)data)->flags(); | 
 | 249 |     }; | 
 | 250 |     wrapper->setMediaCas = []( | 
 | 251 |             void *data, const uint8_t *casToken, size_t size) -> status_t { | 
 | 252 |         return ((MediaExtractorPluginHelper*)data)->setMediaCas(casToken, size); | 
 | 253 |     }; | 
 | 254 |     wrapper->name = []( | 
 | 255 |             void *data) -> const char * { | 
 | 256 |         return ((MediaExtractorPluginHelper*)data)->name(); | 
 | 257 |     }; | 
 | 258 |     return wrapper; | 
 | 259 | } | 
 | 260 |  | 
| Marco Nelissen | 56f1938 | 2018-09-12 15:30:59 -0700 | [diff] [blame^] | 261 | class MediaExtractorPluginHelperV2 | 
 | 262 | { | 
 | 263 | public: | 
 | 264 |     virtual ~MediaExtractorPluginHelperV2() {} | 
 | 265 |     virtual size_t countTracks() = 0; | 
 | 266 |     virtual MediaTrackHelperV2 *getTrack(size_t index) = 0; | 
 | 267 |  | 
 | 268 |     enum GetTrackMetaDataFlags { | 
 | 269 |         kIncludeExtensiveMetaData = 1 | 
 | 270 |     }; | 
 | 271 |     virtual status_t getTrackMetaData( | 
 | 272 |             AMediaFormat *meta, | 
 | 273 |             size_t index, uint32_t flags = 0) = 0; | 
 | 274 |  | 
 | 275 |     // Return container specific meta-data. The default implementation | 
 | 276 |     // returns an empty metadata object. | 
 | 277 |     virtual status_t getMetaData(AMediaFormat *meta) = 0; | 
 | 278 |  | 
 | 279 |     enum Flags { | 
 | 280 |         CAN_SEEK_BACKWARD  = 1,  // the "seek 10secs back button" | 
 | 281 |         CAN_SEEK_FORWARD   = 2,  // the "seek 10secs forward button" | 
 | 282 |         CAN_PAUSE          = 4, | 
 | 283 |         CAN_SEEK           = 8,  // the "seek bar" | 
 | 284 |     }; | 
 | 285 |  | 
 | 286 |     // If subclasses do _not_ override this, the default is | 
 | 287 |     // CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK | CAN_PAUSE | 
 | 288 |     virtual uint32_t flags() const { | 
 | 289 |         return CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK | CAN_PAUSE; | 
 | 290 |     }; | 
 | 291 |  | 
 | 292 |     virtual status_t setMediaCas(const uint8_t* /*casToken*/, size_t /*size*/) { | 
 | 293 |         return INVALID_OPERATION; | 
 | 294 |     } | 
 | 295 |  | 
 | 296 |     virtual const char * name() { return "<unspecified>"; } | 
 | 297 |  | 
 | 298 | protected: | 
 | 299 |     MediaExtractorPluginHelperV2() {} | 
 | 300 |  | 
 | 301 | private: | 
 | 302 |     MediaExtractorPluginHelperV2(const MediaExtractorPluginHelperV2 &); | 
 | 303 |     MediaExtractorPluginHelperV2 &operator=(const MediaExtractorPluginHelperV2 &); | 
 | 304 | }; | 
 | 305 |  | 
 | 306 | inline CMediaExtractorV2 *wrapV2(MediaExtractorPluginHelperV2 *extractor) { | 
 | 307 |     CMediaExtractorV2 *wrapper = (CMediaExtractorV2*) malloc(sizeof(CMediaExtractorV2)); | 
 | 308 |     wrapper->data = extractor; | 
 | 309 |     wrapper->free = [](void *data) -> void { | 
 | 310 |         delete (MediaExtractorPluginHelperV2*)(data); | 
 | 311 |     }; | 
 | 312 |     wrapper->countTracks = [](void *data) -> size_t { | 
 | 313 |         return ((MediaExtractorPluginHelperV2*)data)->countTracks(); | 
 | 314 |     }; | 
 | 315 |     wrapper->getTrack = [](void *data, size_t index) -> CMediaTrackV2* { | 
 | 316 |         return wrapV2(((MediaExtractorPluginHelperV2*)data)->getTrack(index)); | 
 | 317 |     }; | 
 | 318 |     wrapper->getTrackMetaData = []( | 
 | 319 |             void *data, | 
 | 320 |             AMediaFormat *meta, | 
 | 321 |             size_t index, uint32_t flags) -> status_t { | 
 | 322 |         return ((MediaExtractorPluginHelperV2*)data)->getTrackMetaData(meta, index, flags); | 
 | 323 |     }; | 
 | 324 |     wrapper->getMetaData = []( | 
 | 325 |             void *data, | 
 | 326 |             AMediaFormat *meta) -> status_t { | 
 | 327 |         return ((MediaExtractorPluginHelperV2*)data)->getMetaData(meta); | 
 | 328 |     }; | 
 | 329 |     wrapper->flags = []( | 
 | 330 |             void *data) -> uint32_t { | 
 | 331 |         return ((MediaExtractorPluginHelperV2*)data)->flags(); | 
 | 332 |     }; | 
 | 333 |     wrapper->setMediaCas = []( | 
 | 334 |             void *data, const uint8_t *casToken, size_t size) -> status_t { | 
 | 335 |         return ((MediaExtractorPluginHelperV2*)data)->setMediaCas(casToken, size); | 
 | 336 |     }; | 
 | 337 |     wrapper->name = []( | 
 | 338 |             void *data) -> const char * { | 
 | 339 |         return ((MediaExtractorPluginHelperV2*)data)->name(); | 
 | 340 |     }; | 
 | 341 |     return wrapper; | 
 | 342 | } | 
 | 343 |  | 
| Marco Nelissen | cec44d0 | 2018-06-17 22:21:09 -0700 | [diff] [blame] | 344 | /* adds some convience methods */ | 
 | 345 | class DataSourceHelper { | 
 | 346 | public: | 
 | 347 |     explicit DataSourceHelper(CDataSource *csource) { | 
 | 348 |         mSource = csource; | 
 | 349 |     } | 
 | 350 |  | 
 | 351 |     explicit DataSourceHelper(DataSourceHelper *source) { | 
 | 352 |         mSource = source->mSource; | 
 | 353 |     } | 
 | 354 |  | 
| Marco Nelissen | c2b10b3 | 2018-09-24 13:19:43 -0700 | [diff] [blame] | 355 |     virtual ~DataSourceHelper() {} | 
 | 356 |  | 
 | 357 |     virtual ssize_t readAt(off64_t offset, void *data, size_t size) { | 
| Marco Nelissen | cec44d0 | 2018-06-17 22:21:09 -0700 | [diff] [blame] | 358 |         return mSource->readAt(mSource->handle, offset, data, size); | 
 | 359 |     } | 
 | 360 |  | 
| Marco Nelissen | c2b10b3 | 2018-09-24 13:19:43 -0700 | [diff] [blame] | 361 |     virtual status_t getSize(off64_t *size) { | 
| Marco Nelissen | cec44d0 | 2018-06-17 22:21:09 -0700 | [diff] [blame] | 362 |         return mSource->getSize(mSource->handle, size); | 
 | 363 |     } | 
 | 364 |  | 
 | 365 |     bool getUri(char *uriString, size_t bufferSize) { | 
 | 366 |         return mSource->getUri(mSource->handle, uriString, bufferSize); | 
 | 367 |     } | 
 | 368 |  | 
| Marco Nelissen | c2b10b3 | 2018-09-24 13:19:43 -0700 | [diff] [blame] | 369 |     virtual uint32_t flags() { | 
| Marco Nelissen | cec44d0 | 2018-06-17 22:21:09 -0700 | [diff] [blame] | 370 |         return mSource->flags(mSource->handle); | 
 | 371 |     } | 
 | 372 |  | 
 | 373 |     // Convenience methods: | 
 | 374 |     bool getUInt16(off64_t offset, uint16_t *x) { | 
 | 375 |         *x = 0; | 
 | 376 |  | 
 | 377 |         uint8_t byte[2]; | 
 | 378 |         if (readAt(offset, byte, 2) != 2) { | 
 | 379 |             return false; | 
 | 380 |         } | 
 | 381 |  | 
 | 382 |         *x = (byte[0] << 8) | byte[1]; | 
 | 383 |  | 
 | 384 |         return true; | 
 | 385 |     } | 
 | 386 |  | 
 | 387 |     // 3 byte int, returned as a 32-bit int | 
 | 388 |     bool getUInt24(off64_t offset, uint32_t *x) { | 
 | 389 |         *x = 0; | 
 | 390 |  | 
 | 391 |         uint8_t byte[3]; | 
 | 392 |         if (readAt(offset, byte, 3) != 3) { | 
 | 393 |             return false; | 
 | 394 |         } | 
 | 395 |  | 
 | 396 |         *x = (byte[0] << 16) | (byte[1] << 8) | byte[2]; | 
 | 397 |  | 
 | 398 |         return true; | 
 | 399 |     } | 
 | 400 |  | 
 | 401 |     bool getUInt32(off64_t offset, uint32_t *x) { | 
 | 402 |         *x = 0; | 
 | 403 |  | 
 | 404 |         uint32_t tmp; | 
 | 405 |         if (readAt(offset, &tmp, 4) != 4) { | 
 | 406 |             return false; | 
 | 407 |         } | 
 | 408 |  | 
 | 409 |         *x = ntohl(tmp); | 
 | 410 |  | 
 | 411 |         return true; | 
 | 412 |     } | 
 | 413 |  | 
 | 414 |     bool getUInt64(off64_t offset, uint64_t *x) { | 
 | 415 |         *x = 0; | 
 | 416 |  | 
 | 417 |         uint64_t tmp; | 
 | 418 |         if (readAt(offset, &tmp, 8) != 8) { | 
 | 419 |             return false; | 
 | 420 |         } | 
 | 421 |  | 
 | 422 |         *x = ((uint64_t)ntohl(tmp & 0xffffffff) << 32) | ntohl(tmp >> 32); | 
 | 423 |  | 
 | 424 |         return true; | 
 | 425 |     } | 
 | 426 |  | 
 | 427 |     // read either int<N> or int<2N> into a uint<2N>_t, size is the int size in bytes. | 
 | 428 |     bool getUInt16Var(off64_t offset, uint16_t *x, size_t size) { | 
 | 429 |         if (size == 2) { | 
 | 430 |             return getUInt16(offset, x); | 
 | 431 |         } | 
 | 432 |         if (size == 1) { | 
 | 433 |             uint8_t tmp; | 
 | 434 |             if (readAt(offset, &tmp, 1) == 1) { | 
 | 435 |                 *x = tmp; | 
 | 436 |                 return true; | 
 | 437 |             } | 
 | 438 |         } | 
 | 439 |         return false; | 
 | 440 |     } | 
 | 441 |  | 
 | 442 |     bool getUInt32Var(off64_t offset, uint32_t *x, size_t size) { | 
 | 443 |         if (size == 4) { | 
 | 444 |             return getUInt32(offset, x); | 
 | 445 |         } | 
 | 446 |         if (size == 2) { | 
 | 447 |             uint16_t tmp; | 
 | 448 |             if (getUInt16(offset, &tmp)) { | 
 | 449 |                 *x = tmp; | 
 | 450 |                 return true; | 
 | 451 |             } | 
 | 452 |         } | 
 | 453 |         return false; | 
 | 454 |     } | 
 | 455 |  | 
 | 456 |     bool getUInt64Var(off64_t offset, uint64_t *x, size_t size) { | 
 | 457 |         if (size == 8) { | 
 | 458 |             return getUInt64(offset, x); | 
 | 459 |         } | 
 | 460 |         if (size == 4) { | 
 | 461 |             uint32_t tmp; | 
 | 462 |             if (getUInt32(offset, &tmp)) { | 
 | 463 |                 *x = tmp; | 
 | 464 |                 return true; | 
 | 465 |             } | 
 | 466 |         } | 
 | 467 |         return false; | 
 | 468 |     } | 
 | 469 |  | 
 | 470 | protected: | 
 | 471 |     CDataSource *mSource; | 
 | 472 | }; | 
 | 473 |  | 
 | 474 |  | 
 | 475 |  | 
| Marco Nelissen | 0b16447 | 2018-05-30 12:16:56 -0700 | [diff] [blame] | 476 | // helpers to create a media_uuid_t from a string literal | 
 | 477 |  | 
 | 478 | // purposely not defined anywhere so that this will fail to link if | 
 | 479 | // expressions below are not evaluated at compile time | 
 | 480 | int invalid_uuid_string(const char *); | 
 | 481 |  | 
 | 482 | template <typename T, size_t N> | 
 | 483 | constexpr uint8_t _digitAt_(const T (&s)[N], const size_t n) { | 
 | 484 |     return s[n] >= '0' && s[n] <= '9' ? s[n] - '0' | 
 | 485 |             : s[n] >= 'a' && s[n] <= 'f' ? s[n] - 'a' + 10 | 
 | 486 |                     : s[n] >= 'A' && s[n] <= 'F' ? s[n] - 'A' + 10 | 
 | 487 |                             : invalid_uuid_string("uuid: bad digits"); | 
 | 488 | } | 
 | 489 |  | 
 | 490 | template <typename T, size_t N> | 
 | 491 | constexpr uint8_t _hexByteAt_(const T (&s)[N], size_t n) { | 
 | 492 |     return (_digitAt_(s, n) << 4) + _digitAt_(s, n + 1); | 
 | 493 | } | 
 | 494 |  | 
 | 495 | constexpr bool _assertIsDash_(char c) { | 
 | 496 |     return c == '-' ? true : invalid_uuid_string("Wrong format"); | 
 | 497 | } | 
 | 498 |  | 
 | 499 | template <size_t N> | 
 | 500 | constexpr media_uuid_t constUUID(const char (&s) [N]) { | 
 | 501 |     static_assert(N == 37, "uuid: wrong length"); | 
 | 502 |     return | 
 | 503 |             _assertIsDash_(s[8]), | 
 | 504 |             _assertIsDash_(s[13]), | 
 | 505 |             _assertIsDash_(s[18]), | 
 | 506 |             _assertIsDash_(s[23]), | 
 | 507 |             media_uuid_t {{ | 
 | 508 |                 _hexByteAt_(s, 0), | 
 | 509 |                 _hexByteAt_(s, 2), | 
 | 510 |                 _hexByteAt_(s, 4), | 
 | 511 |                 _hexByteAt_(s, 6), | 
 | 512 |                 _hexByteAt_(s, 9), | 
 | 513 |                 _hexByteAt_(s, 11), | 
 | 514 |                 _hexByteAt_(s, 14), | 
 | 515 |                 _hexByteAt_(s, 16), | 
 | 516 |                 _hexByteAt_(s, 19), | 
 | 517 |                 _hexByteAt_(s, 21), | 
 | 518 |                 _hexByteAt_(s, 24), | 
 | 519 |                 _hexByteAt_(s, 26), | 
 | 520 |                 _hexByteAt_(s, 28), | 
 | 521 |                 _hexByteAt_(s, 30), | 
 | 522 |                 _hexByteAt_(s, 32), | 
 | 523 |                 _hexByteAt_(s, 34), | 
 | 524 |             }}; | 
 | 525 | } | 
 | 526 | // Convenience macro to create a media_uuid_t from a string literal, which should | 
 | 527 | // be formatted as "12345678-1234-1234-1234-123456789abc", as generated by | 
 | 528 | // e.g. https://www.uuidgenerator.net/ or the 'uuidgen' linux command. | 
 | 529 | // Hex digits may be upper or lower case. | 
 | 530 | // | 
 | 531 | // The macro call is otherwise equivalent to specifying the structure directly | 
 | 532 | // (e.g. UUID("7d613858-5837-4a38-84c5-332d1cddee27") is the same as | 
 | 533 | //       {{0x7d, 0x61, 0x38, 0x58, 0x58, 0x37, 0x4a, 0x38, | 
 | 534 | //         0x84, 0xc5, 0x33, 0x2d, 0x1c, 0xdd, 0xee, 0x27}}) | 
 | 535 |  | 
 | 536 | #define UUID(str) []{ constexpr media_uuid_t uuid = constUUID(str); return uuid; }() | 
 | 537 |  | 
 | 538 | }  // namespace android | 
 | 539 |  | 
 | 540 | #endif  // MEDIA_EXTRACTOR_PLUGIN_HELPER_H_ |