10c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen/* 20c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen * Copyright (C) 2014 The Android Open Source Project 30c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen * 40c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen * Licensed under the Apache License, Version 2.0 (the "License"); 50c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen * you may not use this file except in compliance with the License. 60c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen * You may obtain a copy of the License at 70c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen * 80c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen * http://www.apache.org/licenses/LICENSE-2.0 90c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen * 100c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen * Unless required by applicable law or agreed to in writing, software 110c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen * distributed under the License is distributed on an "AS IS" BASIS, 120c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen * See the License for the specific language governing permissions and 140c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen * limitations under the License. 150c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen */ 160c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 17c7a11b2208aa8f1e6a39eb70a136fbc0dafd3260Marco Nelissen//#define LOG_NDEBUG 0 180c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#define LOG_TAG "NdkMediaExtractor" 190c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 200c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 21050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen#include "NdkMediaError.h" 220c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include "NdkMediaExtractor.h" 230c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include "NdkMediaFormatPriv.h" 240c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 250c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 260c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include <utils/Log.h> 270c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include <utils/StrongPointer.h> 28050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen#include <media/hardware/CryptoAPI.h> 290c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include <media/stagefright/foundation/ABuffer.h> 300c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include <media/stagefright/foundation/AMessage.h> 310c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include <media/stagefright/MetaData.h> 320c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include <media/stagefright/NuMediaExtractor.h> 330c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include <media/IMediaHTTPService.h> 340c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include <android_runtime/AndroidRuntime.h> 350c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include <android_util_Binder.h> 360c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 370c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include <jni.h> 380c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 390c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenusing namespace android; 400c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 41e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenstatic media_status_t translate_error(status_t err) { 420c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen if (err == OK) { 43e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen return AMEDIA_OK; 440c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen } 450c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen ALOGE("sf error code: %d", err); 46e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen return AMEDIA_ERROR_UNKNOWN; 470c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen} 480c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 490c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenstruct AMediaExtractor { 500c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen sp<NuMediaExtractor> mImpl; 51050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen sp<ABuffer> mPsshBuf; 520c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 530c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}; 540c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 550c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenextern "C" { 560c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 573425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT 580c3be875376adaee8d8e8dd917c64926e1513b29Marco NelissenAMediaExtractor* AMediaExtractor_new() { 590c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen ALOGV("ctor"); 600c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen AMediaExtractor *mData = new AMediaExtractor(); 610c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen mData->mImpl = new NuMediaExtractor(); 620c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen return mData; 630c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen} 640c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 653425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT 66e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenmedia_status_t AMediaExtractor_delete(AMediaExtractor *mData) { 670c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen ALOGV("dtor"); 680c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen delete mData; 69e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen return AMEDIA_OK; 700c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen} 710c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 723425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT 73b187de1ada34a9023c05d020a4592686ba761278Glenn Kastenmedia_status_t AMediaExtractor_setDataSourceFd(AMediaExtractor *mData, int fd, off64_t offset, 74b187de1ada34a9023c05d020a4592686ba761278Glenn Kasten off64_t length) { 750c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen ALOGV("setDataSource(%d, %lld, %lld)", fd, offset, length); 76e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen return translate_error(mData->mImpl->setDataSource(fd, offset, length)); 770c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen} 780c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 793425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT 80e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenmedia_status_t AMediaExtractor_setDataSource(AMediaExtractor *mData, const char *location) { 810c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen ALOGV("setDataSource(%s)", location); 820c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen // TODO: add header support 830c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 840c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen JNIEnv *env = AndroidRuntime::getJNIEnv(); 850c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen jobject service = NULL; 860c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen if (env == NULL) { 870c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen ALOGE("setDataSource(path) must be called from Java thread"); 880c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen env->ExceptionClear(); 89e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen return AMEDIA_ERROR_UNSUPPORTED; 900c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen } 910c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 920c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen jclass mediahttpclass = env->FindClass("android/media/MediaHTTPService"); 930c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen if (mediahttpclass == NULL) { 940c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen ALOGE("can't find MediaHttpService"); 950c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen env->ExceptionClear(); 96e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen return AMEDIA_ERROR_UNSUPPORTED; 970c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen } 980c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 990c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen jmethodID mediaHttpCreateMethod = env->GetStaticMethodID(mediahttpclass, 1000c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen "createHttpServiceBinderIfNecessary", "(Ljava/lang/String;)Landroid/os/IBinder;"); 1010c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen if (mediaHttpCreateMethod == NULL) { 1020c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen ALOGE("can't find method"); 1030c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen env->ExceptionClear(); 104e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen return AMEDIA_ERROR_UNSUPPORTED; 1050c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen } 1060c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 1070c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen jstring jloc = env->NewStringUTF(location); 1080c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 1090c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen service = env->CallStaticObjectMethod(mediahttpclass, mediaHttpCreateMethod, jloc); 1100c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen env->DeleteLocalRef(jloc); 1110c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 1120c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen sp<IMediaHTTPService> httpService; 1130c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen if (service != NULL) { 1140c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen sp<IBinder> binder = ibinderForJavaObject(env, service); 1150c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen httpService = interface_cast<IMediaHTTPService>(binder); 1160c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen } 1170c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 118e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen status_t err = mData->mImpl->setDataSource(httpService, location, NULL); 1190c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen env->ExceptionClear(); 120e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen return translate_error(err); 1210c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen} 1220c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 1233425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT 124e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissensize_t AMediaExtractor_getTrackCount(AMediaExtractor *mData) { 1250c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen return mData->mImpl->countTracks(); 1260c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen} 1270c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 1283425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT 1290c3be875376adaee8d8e8dd917c64926e1513b29Marco NelissenAMediaFormat* AMediaExtractor_getTrackFormat(AMediaExtractor *mData, size_t idx) { 1300c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen sp<AMessage> format; 1310c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen mData->mImpl->getTrackFormat(idx, &format); 1320c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen return AMediaFormat_fromMsg(&format); 1330c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen} 1340c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 1353425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT 136e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenmedia_status_t AMediaExtractor_selectTrack(AMediaExtractor *mData, size_t idx) { 13798f28cde0d5d682956b5e6b119823e7e8d40415bMark Salyzyn ALOGV("selectTrack(%zu)", idx); 1380c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen return translate_error(mData->mImpl->selectTrack(idx)); 1390c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen} 1400c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 1413425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT 142e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenmedia_status_t AMediaExtractor_unselectTrack(AMediaExtractor *mData, size_t idx) { 14398f28cde0d5d682956b5e6b119823e7e8d40415bMark Salyzyn ALOGV("unselectTrack(%zu)", idx); 1440c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen return translate_error(mData->mImpl->unselectTrack(idx)); 1450c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen} 1460c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 1473425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT 1480c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenbool AMediaExtractor_advance(AMediaExtractor *mData) { 1490c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen //ALOGV("advance"); 1500c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen return mData->mImpl->advance(); 1510c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen} 1520c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 1533425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT 15479e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissenmedia_status_t AMediaExtractor_seekTo(AMediaExtractor *ex, int64_t seekPosUs, SeekMode mode) { 15579e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen android::MediaSource::ReadOptions::SeekMode sfmode; 15679e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen if (mode == AMEDIAEXTRACTOR_SEEK_PREVIOUS_SYNC) { 15779e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen sfmode = android::MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC; 15879e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen } else if (mode == AMEDIAEXTRACTOR_SEEK_CLOSEST_SYNC) { 15979e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen sfmode = android::MediaSource::ReadOptions::SEEK_CLOSEST_SYNC; 16079e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen } else { 16179e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen sfmode = android::MediaSource::ReadOptions::SEEK_NEXT_SYNC; 16279e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen } 16379e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen 16479e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen return translate_error(ex->mImpl->seekTo(seekPosUs, sfmode)); 16579e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen} 16679e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen 16779e2b622702fb148ccff12d6f38643466555c4ebMarco NelissenEXPORT 168e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenssize_t AMediaExtractor_readSampleData(AMediaExtractor *mData, uint8_t *buffer, size_t capacity) { 1690c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen //ALOGV("readSampleData"); 1700c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen sp<ABuffer> tmp = new ABuffer(buffer, capacity); 1710c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen if (mData->mImpl->readSampleData(tmp) == OK) { 1720c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen return tmp->size(); 1730c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen } 1740c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen return -1; 1750c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen} 1760c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 1773425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT 178e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenuint32_t AMediaExtractor_getSampleFlags(AMediaExtractor *mData) { 1790c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen int sampleFlags = 0; 1800c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen sp<MetaData> meta; 1810c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen status_t err = mData->mImpl->getSampleMeta(&meta); 1820c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen if (err != OK) { 1830c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen return -1; 1840c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen } 1850c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen int32_t val; 1860c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen if (meta->findInt32(kKeyIsSyncFrame, &val) && val != 0) { 187e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen sampleFlags |= AMEDIAEXTRACTOR_SAMPLE_FLAG_SYNC; 1880c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen } 1890c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 1900c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen uint32_t type; 1910c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen const void *data; 1920c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen size_t size; 1930c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen if (meta->findData(kKeyEncryptedSizes, &type, &data, &size)) { 194e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen sampleFlags |= AMEDIAEXTRACTOR_SAMPLE_FLAG_ENCRYPTED; 1950c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen } 1960c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen return sampleFlags; 1970c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen} 1980c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 1993425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT 2000c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenint AMediaExtractor_getSampleTrackIndex(AMediaExtractor *mData) { 2010c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen size_t idx; 2020c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen if (mData->mImpl->getSampleTrackIndex(&idx) != OK) { 2030c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen return -1; 2040c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen } 2050c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen return idx; 2060c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen} 2070c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 2083425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT 209eb4860c305def68c5965474bb43c67c2c9d49bbbMarco Nelissenint64_t AMediaExtractor_getSampleTime(AMediaExtractor *mData) { 2100c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen int64_t time; 2110c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen if (mData->mImpl->getSampleTime(&time) != OK) { 2120c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen return -1; 2130c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen } 2140c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen return time; 2150c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen} 2160c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 2173425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT 218050eb3280d7305b84f723d515be2dc9606dc39d1Marco NelissenPsshInfo* AMediaExtractor_getPsshInfo(AMediaExtractor *ex) { 219050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 220050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen if (ex->mPsshBuf != NULL) { 221050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen return (PsshInfo*) ex->mPsshBuf->data(); 222050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen } 223050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 224050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen sp<AMessage> format; 225050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen ex->mImpl->getFileFormat(&format); 226050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen sp<ABuffer> buffer; 227050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen if(!format->findBuffer("pssh", &buffer)) { 228050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen return NULL; 229050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen } 230050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 231050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // the format of the buffer is 1 or more of: 232050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // { 233050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // 16 byte uuid 234050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // 4 byte data length N 235050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // N bytes of data 236050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // } 237050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 238050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // Determine the number of entries in the source data. 239050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // Since we got the data from stagefright, we trust it is valid and properly formatted. 240050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen const uint8_t* data = buffer->data(); 241050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen size_t len = buffer->size(); 242050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen size_t numentries = 0; 243050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen while (len > 0) { 244050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen numentries++; 245050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 246050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // skip uuid 247050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen data += 16; 248050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen len -= 16; 249050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 250050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // get data length 251050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen uint32_t datalen = *((uint32_t*)data); 252050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen data += 4; 253050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen len -= 4; 254050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 255050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // skip the data 256050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen data += datalen; 257050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen len -= datalen; 258050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen } 259050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 26058344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen // there are <numentries> in the source buffer, we need 26158344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen // (source buffer size) - (sizeof(uint32_t) * numentries) + sizeof(size_t) 26258344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen // + ((sizeof(void*) + sizeof(size_t)) * numentries) bytes for the PsshInfo structure 26358344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen // Or in other words, the data lengths in the source structure are replaced by size_t 26458344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen // (which may be the same size or larger, for 64 bit), and in addition there is an 26558344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen // extra pointer for each entry, and an extra size_t for the entire PsshInfo. 26658344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen size_t newsize = buffer->size() - (sizeof(uint32_t) * numentries) + sizeof(size_t) 26758344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen + ((sizeof(void*) + sizeof(size_t)) * numentries); 268050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen ex->mPsshBuf = new ABuffer(newsize); 269050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen ex->mPsshBuf->setRange(0, newsize); 270050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 271050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // copy data 272050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen const uint8_t* src = buffer->data(); 273050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen uint8_t* dst = ex->mPsshBuf->data(); 27458344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen uint8_t* dstdata = dst + sizeof(size_t) + numentries * sizeof(PsshEntry); 27558344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen *((size_t*)dst) = numentries; 27658344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen dst += sizeof(size_t); 277050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen for (size_t i = 0; i < numentries; i++) { 278050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // copy uuid 279050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen memcpy(dst, src, 16); 280050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen src += 16; 281050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen dst += 16; 282050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 283050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // get/copy data length 284050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen uint32_t datalen = *((uint32_t*)src); 28558344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen *((size_t*)dst) = datalen; 28658344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen src += sizeof(uint32_t); 28758344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen dst += sizeof(size_t); 288050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 289050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // the next entry in the destination is a pointer to the actual data, which we store 290050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // after the array of PsshEntry 29158344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen *((void**)dst) = dstdata; 29258344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen dst += sizeof(void*); 293050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 294050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // copy the actual data 295050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen memcpy(dstdata, src, datalen); 296050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen dstdata += datalen; 297050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen src += datalen; 298050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen } 299050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 300050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen return (PsshInfo*) ex->mPsshBuf->data(); 301050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen} 302050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 3033425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT 304050eb3280d7305b84f723d515be2dc9606dc39d1Marco NelissenAMediaCodecCryptoInfo *AMediaExtractor_getSampleCryptoInfo(AMediaExtractor *ex) { 305050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen sp<MetaData> meta; 306050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen if(ex->mImpl->getSampleMeta(&meta) != 0) { 307050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen return NULL; 308050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen } 309050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 310050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen uint32_t type; 311050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen const void *crypteddata; 312050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen size_t cryptedsize; 313050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen if (!meta->findData(kKeyEncryptedSizes, &type, &crypteddata, &cryptedsize)) { 314050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen return NULL; 315050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen } 316050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen size_t numSubSamples = cryptedsize / sizeof(size_t); 317050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 318050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen const void *cleardata; 319050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen size_t clearsize; 320050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen if (meta->findData(kKeyPlainSizes, &type, &cleardata, &clearsize)) { 321050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen if (clearsize != cryptedsize) { 322050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // The two must be of the same length. 323050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen return NULL; 324050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen } 325050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen } 326050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 327050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen const void *key; 328050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen size_t keysize; 329050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen if (meta->findData(kKeyCryptoIV, &type, &key, &keysize)) { 330050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen if (keysize != 16) { 331050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // IVs must be 16 bytes in length. 332050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen return NULL; 333050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen } 334050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen } 335050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 336050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen const void *iv; 337050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen size_t ivsize; 338050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen if (meta->findData(kKeyCryptoIV, &type, &iv, &ivsize)) { 339050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen if (ivsize != 16) { 340050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // IVs must be 16 bytes in length. 341050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen return NULL; 342050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen } 343050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen } 344050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 345050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen int32_t mode; 346050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen if (!meta->findInt32(kKeyCryptoMode, &mode)) { 347050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen mode = CryptoPlugin::kMode_AES_CTR; 348050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen } 349050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 350050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen return AMediaCodecCryptoInfo_new( 351050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen numSubSamples, 352050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen (uint8_t*) key, 353050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen (uint8_t*) iv, 35479e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen (cryptoinfo_mode_t) mode, 355050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen (size_t*) cleardata, 356050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen (size_t*) crypteddata); 357050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen} 358050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 3590c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 3600c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen} // extern "C" 3610c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 362