1 /* 2 * Copyright (C) 2014 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 //#define LOG_NDEBUG 0 18 #define LOG_TAG "NdkMediaExtractor" 19 20 21 #include <media/NdkMediaError.h> 22 #include <media/NdkMediaExtractor.h> 23 #include <media/NdkMediaErrorPriv.h> 24 #include <media/NdkMediaFormatPriv.h> 25 #include "NdkMediaDataSourcePriv.h" 26 27 28 #include <inttypes.h> 29 #include <utils/Log.h> 30 #include <utils/StrongPointer.h> 31 #include <media/hardware/CryptoAPI.h> 32 #include <media/stagefright/foundation/ABuffer.h> 33 #include <media/stagefright/foundation/AMessage.h> 34 #include <media/stagefright/MetaData.h> 35 #include <media/stagefright/NuMediaExtractor.h> 36 #include <media/IMediaHTTPService.h> 37 #include <android_util_Binder.h> 38 39 #include <jni.h> 40 41 using namespace android; 42 43 struct AMediaExtractor { 44 sp<NuMediaExtractor> mImpl; 45 sp<ABuffer> mPsshBuf; 46 }; 47 48 sp<ABuffer> U32ArrayToSizeBuf(size_t numSubSamples, uint32_t *data) { 49 if (numSubSamples > SIZE_MAX / sizeof(size_t)) { 50 return NULL; 51 } 52 sp<ABuffer> sizebuf = new ABuffer(numSubSamples * sizeof(size_t)); 53 size_t *sizes = (size_t *)sizebuf->data(); 54 for (size_t i = 0; sizes != NULL && i < numSubSamples; i++) { 55 sizes[i] = data[i]; 56 } 57 return sizebuf; 58 } 59 60 extern "C" { 61 62 EXPORT 63 AMediaExtractor* AMediaExtractor_new() { 64 ALOGV("ctor"); 65 AMediaExtractor *mData = new AMediaExtractor(); 66 mData->mImpl = new NuMediaExtractor(); 67 return mData; 68 } 69 70 EXPORT 71 media_status_t AMediaExtractor_delete(AMediaExtractor *mData) { 72 ALOGV("dtor"); 73 delete mData; 74 return AMEDIA_OK; 75 } 76 77 EXPORT 78 media_status_t AMediaExtractor_setDataSourceFd(AMediaExtractor *mData, int fd, off64_t offset, 79 off64_t length) { 80 ALOGV("setDataSource(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length); 81 return translate_error(mData->mImpl->setDataSource(fd, offset, length)); 82 } 83 84 media_status_t AMediaExtractor_setDataSourceWithHeaders(AMediaExtractor *mData, 85 const char *uri, 86 int numheaders, 87 const char * const *keys, 88 const char * const *values) { 89 90 ALOGV("setDataSource(%s)", uri); 91 92 sp<MediaHTTPService> httpService = createMediaHttpService(uri, /* version = */ 1); 93 if (httpService == NULL) { 94 ALOGE("can't create http service"); 95 return AMEDIA_ERROR_UNSUPPORTED; 96 } 97 98 KeyedVector<String8, String8> headers; 99 for (int i = 0; i < numheaders; ++i) { 100 String8 key8(keys[i]); 101 String8 value8(values[i]); 102 headers.add(key8, value8); 103 } 104 105 status_t err; 106 err = mData->mImpl->setDataSource(httpService, uri, numheaders > 0 ? &headers : NULL); 107 return translate_error(err); 108 } 109 110 EXPORT 111 media_status_t AMediaExtractor_setDataSource(AMediaExtractor *mData, const char *location) { 112 return AMediaExtractor_setDataSourceWithHeaders(mData, location, 0, NULL, NULL); 113 } 114 115 EXPORT 116 media_status_t AMediaExtractor_setDataSourceCustom(AMediaExtractor* mData, AMediaDataSource *src) { 117 return translate_error(mData->mImpl->setDataSource(new NdkDataSource(src))); 118 } 119 120 EXPORT 121 AMediaFormat* AMediaExtractor_getFileFormat(AMediaExtractor *mData) { 122 sp<AMessage> format; 123 mData->mImpl->getFileFormat(&format); 124 return AMediaFormat_fromMsg(&format); 125 } 126 127 EXPORT 128 size_t AMediaExtractor_getTrackCount(AMediaExtractor *mData) { 129 return mData->mImpl->countTracks(); 130 } 131 132 EXPORT 133 AMediaFormat* AMediaExtractor_getTrackFormat(AMediaExtractor *mData, size_t idx) { 134 sp<AMessage> format; 135 mData->mImpl->getTrackFormat(idx, &format); 136 return AMediaFormat_fromMsg(&format); 137 } 138 139 EXPORT 140 media_status_t AMediaExtractor_selectTrack(AMediaExtractor *mData, size_t idx) { 141 ALOGV("selectTrack(%zu)", idx); 142 return translate_error(mData->mImpl->selectTrack(idx)); 143 } 144 145 EXPORT 146 media_status_t AMediaExtractor_unselectTrack(AMediaExtractor *mData, size_t idx) { 147 ALOGV("unselectTrack(%zu)", idx); 148 return translate_error(mData->mImpl->unselectTrack(idx)); 149 } 150 151 EXPORT 152 bool AMediaExtractor_advance(AMediaExtractor *mData) { 153 //ALOGV("advance"); 154 status_t err = mData->mImpl->advance(); 155 if (err == ERROR_END_OF_STREAM) { 156 return false; 157 } else if (err != OK) { 158 ALOGE("sf error code: %d", err); 159 return false; 160 } 161 return true; 162 } 163 164 EXPORT 165 media_status_t AMediaExtractor_seekTo(AMediaExtractor *ex, int64_t seekPosUs, SeekMode mode) { 166 android::MediaSource::ReadOptions::SeekMode sfmode; 167 if (mode == AMEDIAEXTRACTOR_SEEK_PREVIOUS_SYNC) { 168 sfmode = android::MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC; 169 } else if (mode == AMEDIAEXTRACTOR_SEEK_CLOSEST_SYNC) { 170 sfmode = android::MediaSource::ReadOptions::SEEK_CLOSEST_SYNC; 171 } else { 172 sfmode = android::MediaSource::ReadOptions::SEEK_NEXT_SYNC; 173 } 174 175 return translate_error(ex->mImpl->seekTo(seekPosUs, sfmode)); 176 } 177 178 EXPORT 179 ssize_t AMediaExtractor_readSampleData(AMediaExtractor *mData, uint8_t *buffer, size_t capacity) { 180 //ALOGV("readSampleData"); 181 sp<ABuffer> tmp = new ABuffer(buffer, capacity); 182 if (mData->mImpl->readSampleData(tmp) == OK) { 183 return tmp->size(); 184 } 185 return -1; 186 } 187 188 EXPORT 189 ssize_t AMediaExtractor_getSampleSize(AMediaExtractor *mData) { 190 size_t sampleSize; 191 status_t err = mData->mImpl->getSampleSize(&sampleSize); 192 if (err != OK) { 193 return -1; 194 } 195 return sampleSize; 196 } 197 198 EXPORT 199 uint32_t AMediaExtractor_getSampleFlags(AMediaExtractor *mData) { 200 int sampleFlags = 0; 201 sp<MetaData> meta; 202 status_t err = mData->mImpl->getSampleMeta(&meta); 203 if (err != OK) { 204 return -1; 205 } 206 int32_t val; 207 if (meta->findInt32(kKeyIsSyncFrame, &val) && val != 0) { 208 sampleFlags |= AMEDIAEXTRACTOR_SAMPLE_FLAG_SYNC; 209 } 210 211 uint32_t type; 212 const void *data; 213 size_t size; 214 if (meta->findData(kKeyEncryptedSizes, &type, &data, &size)) { 215 sampleFlags |= AMEDIAEXTRACTOR_SAMPLE_FLAG_ENCRYPTED; 216 } 217 return sampleFlags; 218 } 219 220 EXPORT 221 int AMediaExtractor_getSampleTrackIndex(AMediaExtractor *mData) { 222 size_t idx; 223 if (mData->mImpl->getSampleTrackIndex(&idx) != OK) { 224 return -1; 225 } 226 return idx; 227 } 228 229 EXPORT 230 int64_t AMediaExtractor_getSampleTime(AMediaExtractor *mData) { 231 int64_t time; 232 if (mData->mImpl->getSampleTime(&time) != OK) { 233 return -1; 234 } 235 return time; 236 } 237 238 EXPORT 239 PsshInfo* AMediaExtractor_getPsshInfo(AMediaExtractor *ex) { 240 241 if (ex->mPsshBuf != NULL) { 242 return (PsshInfo*) ex->mPsshBuf->data(); 243 } 244 245 sp<AMessage> format; 246 ex->mImpl->getFileFormat(&format); 247 sp<ABuffer> buffer; 248 if(!format->findBuffer("pssh", &buffer)) { 249 return NULL; 250 } 251 252 // the format of the buffer is 1 or more of: 253 // { 254 // 16 byte uuid 255 // 4 byte data length N 256 // N bytes of data 257 // } 258 259 // Determine the number of entries in the source data. 260 // Since we got the data from stagefright, we trust it is valid and properly formatted. 261 const uint8_t* data = buffer->data(); 262 size_t len = buffer->size(); 263 size_t numentries = 0; 264 while (len > 0) { 265 numentries++; 266 267 if (len < 16) { 268 ALOGE("invalid PSSH data"); 269 return NULL; 270 } 271 // skip uuid 272 data += 16; 273 len -= 16; 274 275 // get data length 276 if (len < 4) { 277 ALOGE("invalid PSSH data"); 278 return NULL; 279 } 280 uint32_t datalen = *((uint32_t*)data); 281 data += 4; 282 len -= 4; 283 284 if (len < datalen) { 285 ALOGE("invalid PSSH data"); 286 return NULL; 287 } 288 // skip the data 289 data += datalen; 290 len -= datalen; 291 } 292 293 // there are <numentries> in the source buffer, we need 294 // (source buffer size) - (sizeof(uint32_t) * numentries) + sizeof(size_t) 295 // + ((sizeof(void*) + sizeof(size_t)) * numentries) bytes for the PsshInfo structure 296 // Or in other words, the data lengths in the source structure are replaced by size_t 297 // (which may be the same size or larger, for 64 bit), and in addition there is an 298 // extra pointer for each entry, and an extra size_t for the entire PsshInfo. 299 size_t newsize = buffer->size() - (sizeof(uint32_t) * numentries) + sizeof(size_t) 300 + ((sizeof(void*) + sizeof(size_t)) * numentries); 301 if (newsize <= buffer->size()) { 302 ALOGE("invalid PSSH data"); 303 return NULL; 304 } 305 ex->mPsshBuf = new ABuffer(newsize); 306 ex->mPsshBuf->setRange(0, newsize); 307 308 // copy data 309 const uint8_t* src = buffer->data(); 310 uint8_t* dst = ex->mPsshBuf->data(); 311 uint8_t* dstdata = dst + sizeof(size_t) + numentries * sizeof(PsshEntry); 312 *((size_t*)dst) = numentries; 313 dst += sizeof(size_t); 314 for (size_t i = 0; i < numentries; i++) { 315 // copy uuid 316 memcpy(dst, src, 16); 317 src += 16; 318 dst += 16; 319 320 // get/copy data length 321 uint32_t datalen = *((uint32_t*)src); 322 *((size_t*)dst) = datalen; 323 src += sizeof(uint32_t); 324 dst += sizeof(size_t); 325 326 // the next entry in the destination is a pointer to the actual data, which we store 327 // after the array of PsshEntry 328 *((void**)dst) = dstdata; 329 dst += sizeof(void*); 330 331 // copy the actual data 332 memcpy(dstdata, src, datalen); 333 dstdata += datalen; 334 src += datalen; 335 } 336 337 return (PsshInfo*) ex->mPsshBuf->data(); 338 } 339 340 EXPORT 341 AMediaCodecCryptoInfo *AMediaExtractor_getSampleCryptoInfo(AMediaExtractor *ex) { 342 sp<MetaData> meta; 343 if(ex->mImpl->getSampleMeta(&meta) != 0) { 344 return NULL; 345 } 346 347 uint32_t type; 348 const void *crypteddata; 349 size_t cryptedsize; 350 if (!meta->findData(kKeyEncryptedSizes, &type, &crypteddata, &cryptedsize)) { 351 return NULL; 352 } 353 size_t numSubSamples = cryptedsize / sizeof(uint32_t); 354 355 const void *cleardata; 356 size_t clearsize; 357 if (meta->findData(kKeyPlainSizes, &type, &cleardata, &clearsize)) { 358 if (clearsize != cryptedsize) { 359 // The two must be of the same length. 360 return NULL; 361 } 362 } 363 364 const void *key; 365 size_t keysize; 366 if (meta->findData(kKeyCryptoKey, &type, &key, &keysize)) { 367 if (keysize != 16) { 368 // Keys must be 16 bytes in length. 369 return NULL; 370 } 371 } 372 373 const void *iv; 374 size_t ivsize; 375 if (meta->findData(kKeyCryptoIV, &type, &iv, &ivsize)) { 376 if (ivsize != 16) { 377 // IVs must be 16 bytes in length. 378 return NULL; 379 } 380 } 381 382 int32_t mode; 383 if (!meta->findInt32(kKeyCryptoMode, &mode)) { 384 mode = CryptoPlugin::kMode_AES_CTR; 385 } 386 387 if (sizeof(uint32_t) != sizeof(size_t)) { 388 sp<ABuffer> clearbuf = U32ArrayToSizeBuf(numSubSamples, (uint32_t *)cleardata); 389 sp<ABuffer> cryptedbuf = U32ArrayToSizeBuf(numSubSamples, (uint32_t *)crypteddata); 390 cleardata = clearbuf == NULL ? NULL : clearbuf->data(); 391 crypteddata = crypteddata == NULL ? NULL : cryptedbuf->data(); 392 if(crypteddata == NULL || cleardata == NULL) { 393 return NULL; 394 } 395 } 396 397 return AMediaCodecCryptoInfo_new( 398 numSubSamples, 399 (uint8_t*) key, 400 (uint8_t*) iv, 401 (cryptoinfo_mode_t) mode, 402 (size_t*) cleardata, 403 (size_t*) crypteddata); 404 } 405 406 EXPORT 407 int64_t AMediaExtractor_getCachedDuration(AMediaExtractor *ex) { 408 bool eos; 409 int64_t durationUs; 410 if (ex->mImpl->getCachedDuration(&durationUs, &eos)) { 411 return durationUs; 412 } 413 return -1; 414 } 415 416 EXPORT 417 media_status_t AMediaExtractor_getSampleFormat(AMediaExtractor *ex, AMediaFormat *fmt) { 418 if (fmt == NULL) { 419 return AMEDIA_ERROR_INVALID_PARAMETER; 420 } 421 422 sp<MetaData> sampleMeta; 423 status_t err = ex->mImpl->getSampleMeta(&sampleMeta); 424 if (err != OK) { 425 return translate_error(err); 426 } 427 428 sp<AMessage> meta; 429 AMediaFormat_getFormat(fmt, &meta); 430 meta->clear(); 431 432 int32_t layerId; 433 if (sampleMeta->findInt32(kKeyTemporalLayerId, &layerId)) { 434 meta->setInt32(AMEDIAFORMAT_KEY_TEMPORAL_LAYER_ID, layerId); 435 } 436 437 size_t trackIndex; 438 err = ex->mImpl->getSampleTrackIndex(&trackIndex); 439 if (err == OK) { 440 meta->setInt32(AMEDIAFORMAT_KEY_TRACK_INDEX, trackIndex); 441 sp<AMessage> trackFormat; 442 AString mime; 443 err = ex->mImpl->getTrackFormat(trackIndex, &trackFormat); 444 if (err == OK 445 && trackFormat != NULL 446 && trackFormat->findString(AMEDIAFORMAT_KEY_MIME, &mime)) { 447 meta->setString(AMEDIAFORMAT_KEY_MIME, mime); 448 } 449 } 450 451 int64_t durationUs; 452 if (sampleMeta->findInt64(kKeyDuration, &durationUs)) { 453 meta->setInt64(AMEDIAFORMAT_KEY_DURATION, durationUs); 454 } 455 456 uint32_t dataType; // unused 457 const void *seiData; 458 size_t seiLength; 459 if (sampleMeta->findData(kKeySEI, &dataType, &seiData, &seiLength)) { 460 sp<ABuffer> sei = ABuffer::CreateAsCopy(seiData, seiLength);; 461 meta->setBuffer(AMEDIAFORMAT_KEY_SEI, sei); 462 } 463 464 const void *mpegUserDataPointer; 465 size_t mpegUserDataLength; 466 if (sampleMeta->findData( 467 kKeyMpegUserData, &dataType, &mpegUserDataPointer, &mpegUserDataLength)) { 468 sp<ABuffer> mpegUserData = ABuffer::CreateAsCopy(mpegUserDataPointer, mpegUserDataLength); 469 meta->setBuffer(AMEDIAFORMAT_KEY_MPEG_USER_DATA, mpegUserData); 470 } 471 472 const void *audioPresentationsPointer; 473 size_t audioPresentationsLength; 474 if (sampleMeta->findData( 475 kKeyAudioPresentationInfo, &dataType, 476 &audioPresentationsPointer, &audioPresentationsLength)) { 477 sp<ABuffer> audioPresentationsData = ABuffer::CreateAsCopy( 478 audioPresentationsPointer, audioPresentationsLength); 479 meta->setBuffer(AMEDIAFORMAT_KEY_AUDIO_PRESENTATION_INFO, audioPresentationsData); 480 } 481 482 return AMEDIA_OK; 483 } 484 485 } // extern "C" 486 487