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 73e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenmedia_status_t AMediaExtractor_setDataSourceFd(AMediaExtractor *mData, int fd, off64_t offset, off64_t length) { 740c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen ALOGV("setDataSource(%d, %lld, %lld)", fd, offset, length); 75e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen return translate_error(mData->mImpl->setDataSource(fd, offset, length)); 760c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen} 770c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 783425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT 79e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenmedia_status_t AMediaExtractor_setDataSource(AMediaExtractor *mData, const char *location) { 800c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen ALOGV("setDataSource(%s)", location); 810c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen // TODO: add header support 820c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 830c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen JNIEnv *env = AndroidRuntime::getJNIEnv(); 840c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen jobject service = NULL; 850c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen if (env == NULL) { 860c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen ALOGE("setDataSource(path) must be called from Java thread"); 870c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen env->ExceptionClear(); 88e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen return AMEDIA_ERROR_UNSUPPORTED; 890c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen } 900c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 910c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen jclass mediahttpclass = env->FindClass("android/media/MediaHTTPService"); 920c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen if (mediahttpclass == NULL) { 930c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen ALOGE("can't find MediaHttpService"); 940c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen env->ExceptionClear(); 95e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen return AMEDIA_ERROR_UNSUPPORTED; 960c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen } 970c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 980c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen jmethodID mediaHttpCreateMethod = env->GetStaticMethodID(mediahttpclass, 990c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen "createHttpServiceBinderIfNecessary", "(Ljava/lang/String;)Landroid/os/IBinder;"); 1000c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen if (mediaHttpCreateMethod == NULL) { 1010c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen ALOGE("can't find method"); 1020c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen env->ExceptionClear(); 103e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen return AMEDIA_ERROR_UNSUPPORTED; 1040c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen } 1050c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 1060c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen jstring jloc = env->NewStringUTF(location); 1070c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 1080c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen service = env->CallStaticObjectMethod(mediahttpclass, mediaHttpCreateMethod, jloc); 1090c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen env->DeleteLocalRef(jloc); 1100c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 1110c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen sp<IMediaHTTPService> httpService; 1120c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen if (service != NULL) { 1130c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen sp<IBinder> binder = ibinderForJavaObject(env, service); 1140c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen httpService = interface_cast<IMediaHTTPService>(binder); 1150c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen } 1160c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 117e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen status_t err = mData->mImpl->setDataSource(httpService, location, NULL); 1180c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen env->ExceptionClear(); 119e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen return translate_error(err); 1200c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen} 1210c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 1223425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT 123e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissensize_t AMediaExtractor_getTrackCount(AMediaExtractor *mData) { 1240c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen return mData->mImpl->countTracks(); 1250c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen} 1260c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 1273425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT 1280c3be875376adaee8d8e8dd917c64926e1513b29Marco NelissenAMediaFormat* AMediaExtractor_getTrackFormat(AMediaExtractor *mData, size_t idx) { 1290c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen sp<AMessage> format; 1300c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen mData->mImpl->getTrackFormat(idx, &format); 1310c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen return AMediaFormat_fromMsg(&format); 1320c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen} 1330c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 1343425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT 135e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenmedia_status_t AMediaExtractor_selectTrack(AMediaExtractor *mData, size_t idx) { 13698f28cde0d5d682956b5e6b119823e7e8d40415bMark Salyzyn ALOGV("selectTrack(%zu)", idx); 1370c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen return translate_error(mData->mImpl->selectTrack(idx)); 1380c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen} 1390c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 1403425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT 141e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenmedia_status_t AMediaExtractor_unselectTrack(AMediaExtractor *mData, size_t idx) { 14298f28cde0d5d682956b5e6b119823e7e8d40415bMark Salyzyn ALOGV("unselectTrack(%zu)", idx); 1430c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen return translate_error(mData->mImpl->unselectTrack(idx)); 1440c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen} 1450c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 1463425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT 1470c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenbool AMediaExtractor_advance(AMediaExtractor *mData) { 1480c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen //ALOGV("advance"); 1490c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen return mData->mImpl->advance(); 1500c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen} 1510c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 1523425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT 15379e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissenmedia_status_t AMediaExtractor_seekTo(AMediaExtractor *ex, int64_t seekPosUs, SeekMode mode) { 15479e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen android::MediaSource::ReadOptions::SeekMode sfmode; 15579e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen if (mode == AMEDIAEXTRACTOR_SEEK_PREVIOUS_SYNC) { 15679e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen sfmode = android::MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC; 15779e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen } else if (mode == AMEDIAEXTRACTOR_SEEK_CLOSEST_SYNC) { 15879e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen sfmode = android::MediaSource::ReadOptions::SEEK_CLOSEST_SYNC; 15979e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen } else { 16079e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen sfmode = android::MediaSource::ReadOptions::SEEK_NEXT_SYNC; 16179e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen } 16279e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen 16379e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen return translate_error(ex->mImpl->seekTo(seekPosUs, sfmode)); 16479e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen} 16579e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen 16679e2b622702fb148ccff12d6f38643466555c4ebMarco NelissenEXPORT 167e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenssize_t AMediaExtractor_readSampleData(AMediaExtractor *mData, uint8_t *buffer, size_t capacity) { 1680c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen //ALOGV("readSampleData"); 1690c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen sp<ABuffer> tmp = new ABuffer(buffer, capacity); 1700c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen if (mData->mImpl->readSampleData(tmp) == OK) { 1710c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen return tmp->size(); 1720c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen } 1730c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen return -1; 1740c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen} 1750c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 1763425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT 177e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenuint32_t AMediaExtractor_getSampleFlags(AMediaExtractor *mData) { 1780c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen int sampleFlags = 0; 1790c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen sp<MetaData> meta; 1800c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen status_t err = mData->mImpl->getSampleMeta(&meta); 1810c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen if (err != OK) { 1820c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen return -1; 1830c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen } 1840c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen int32_t val; 1850c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen if (meta->findInt32(kKeyIsSyncFrame, &val) && val != 0) { 186e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen sampleFlags |= AMEDIAEXTRACTOR_SAMPLE_FLAG_SYNC; 1870c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen } 1880c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 1890c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen uint32_t type; 1900c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen const void *data; 1910c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen size_t size; 1920c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen if (meta->findData(kKeyEncryptedSizes, &type, &data, &size)) { 193e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen sampleFlags |= AMEDIAEXTRACTOR_SAMPLE_FLAG_ENCRYPTED; 1940c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen } 1950c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen return sampleFlags; 1960c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen} 1970c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 1983425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT 1990c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenint AMediaExtractor_getSampleTrackIndex(AMediaExtractor *mData) { 2000c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen size_t idx; 2010c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen if (mData->mImpl->getSampleTrackIndex(&idx) != OK) { 2020c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen return -1; 2030c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen } 2040c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen return idx; 2050c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen} 2060c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 2073425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT 208eb4860c305def68c5965474bb43c67c2c9d49bbbMarco Nelissenint64_t AMediaExtractor_getSampleTime(AMediaExtractor *mData) { 2090c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen int64_t time; 2100c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen if (mData->mImpl->getSampleTime(&time) != OK) { 2110c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen return -1; 2120c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen } 2130c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen return time; 2140c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen} 2150c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 2163425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT 217050eb3280d7305b84f723d515be2dc9606dc39d1Marco NelissenPsshInfo* AMediaExtractor_getPsshInfo(AMediaExtractor *ex) { 218050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 219050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen if (ex->mPsshBuf != NULL) { 220050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen return (PsshInfo*) ex->mPsshBuf->data(); 221050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen } 222050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 223050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen sp<AMessage> format; 224050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen ex->mImpl->getFileFormat(&format); 225050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen sp<ABuffer> buffer; 226050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen if(!format->findBuffer("pssh", &buffer)) { 227050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen return NULL; 228050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen } 229050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 230050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // the format of the buffer is 1 or more of: 231050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // { 232050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // 16 byte uuid 233050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // 4 byte data length N 234050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // N bytes of data 235050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // } 236050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 237050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // Determine the number of entries in the source data. 238050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // Since we got the data from stagefright, we trust it is valid and properly formatted. 239050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen const uint8_t* data = buffer->data(); 240050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen size_t len = buffer->size(); 241050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen size_t numentries = 0; 242050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen while (len > 0) { 243050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen numentries++; 244050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 245050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // skip uuid 246050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen data += 16; 247050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen len -= 16; 248050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 249050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // get data length 250050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen uint32_t datalen = *((uint32_t*)data); 251050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen data += 4; 252050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen len -= 4; 253050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 254050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // skip the data 255050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen data += datalen; 256050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen len -= datalen; 257050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen } 258050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 25958344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen // there are <numentries> in the source buffer, we need 26058344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen // (source buffer size) - (sizeof(uint32_t) * numentries) + sizeof(size_t) 26158344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen // + ((sizeof(void*) + sizeof(size_t)) * numentries) bytes for the PsshInfo structure 26258344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen // Or in other words, the data lengths in the source structure are replaced by size_t 26358344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen // (which may be the same size or larger, for 64 bit), and in addition there is an 26458344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen // extra pointer for each entry, and an extra size_t for the entire PsshInfo. 26558344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen size_t newsize = buffer->size() - (sizeof(uint32_t) * numentries) + sizeof(size_t) 26658344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen + ((sizeof(void*) + sizeof(size_t)) * numentries); 267050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen ex->mPsshBuf = new ABuffer(newsize); 268050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen ex->mPsshBuf->setRange(0, newsize); 269050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 270050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // copy data 271050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen const uint8_t* src = buffer->data(); 272050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen uint8_t* dst = ex->mPsshBuf->data(); 27358344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen uint8_t* dstdata = dst + sizeof(size_t) + numentries * sizeof(PsshEntry); 27458344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen *((size_t*)dst) = numentries; 27558344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen dst += sizeof(size_t); 276050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen for (size_t i = 0; i < numentries; i++) { 277050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // copy uuid 278050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen memcpy(dst, src, 16); 279050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen src += 16; 280050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen dst += 16; 281050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 282050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // get/copy data length 283050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen uint32_t datalen = *((uint32_t*)src); 28458344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen *((size_t*)dst) = datalen; 28558344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen src += sizeof(uint32_t); 28658344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen dst += sizeof(size_t); 287050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 288050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // the next entry in the destination is a pointer to the actual data, which we store 289050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // after the array of PsshEntry 29058344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen *((void**)dst) = dstdata; 29158344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen dst += sizeof(void*); 292050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 293050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // copy the actual data 294050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen memcpy(dstdata, src, datalen); 295050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen dstdata += datalen; 296050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen src += datalen; 297050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen } 298050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 299050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen return (PsshInfo*) ex->mPsshBuf->data(); 300050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen} 301050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 3023425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT 303050eb3280d7305b84f723d515be2dc9606dc39d1Marco NelissenAMediaCodecCryptoInfo *AMediaExtractor_getSampleCryptoInfo(AMediaExtractor *ex) { 304050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen sp<MetaData> meta; 305050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen if(ex->mImpl->getSampleMeta(&meta) != 0) { 306050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen return NULL; 307050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen } 308050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 309050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen uint32_t type; 310050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen const void *crypteddata; 311050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen size_t cryptedsize; 312050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen if (!meta->findData(kKeyEncryptedSizes, &type, &crypteddata, &cryptedsize)) { 313050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen return NULL; 314050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen } 315050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen size_t numSubSamples = cryptedsize / sizeof(size_t); 316050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 317050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen const void *cleardata; 318050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen size_t clearsize; 319050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen if (meta->findData(kKeyPlainSizes, &type, &cleardata, &clearsize)) { 320050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen if (clearsize != cryptedsize) { 321050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // The two must be of the same length. 322050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen return NULL; 323050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen } 324050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen } 325050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 326050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen const void *key; 327050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen size_t keysize; 328050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen if (meta->findData(kKeyCryptoIV, &type, &key, &keysize)) { 329050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen if (keysize != 16) { 330050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // IVs must be 16 bytes in length. 331050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen return NULL; 332050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen } 333050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen } 334050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 335050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen const void *iv; 336050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen size_t ivsize; 337050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen if (meta->findData(kKeyCryptoIV, &type, &iv, &ivsize)) { 338050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen if (ivsize != 16) { 339050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen // IVs must be 16 bytes in length. 340050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen return NULL; 341050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen } 342050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen } 343050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 344050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen int32_t mode; 345050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen if (!meta->findInt32(kKeyCryptoMode, &mode)) { 346050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen mode = CryptoPlugin::kMode_AES_CTR; 347050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen } 348050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 349050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen return AMediaCodecCryptoInfo_new( 350050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen numSubSamples, 351050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen (uint8_t*) key, 352050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen (uint8_t*) iv, 35379e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen (cryptoinfo_mode_t) mode, 354050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen (size_t*) cleardata, 355050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen (size_t*) crypteddata); 356050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen} 357050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen 3580c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 3590c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen} // extern "C" 3600c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen 361