diff options
author | Marco Nelissen <marcone@google.com> | 2014-05-09 15:10:23 -0700 |
---|---|---|
committer | Marco Nelissen <marcone@google.com> | 2014-05-13 15:03:04 -0700 |
commit | 050eb3280d7305b84f723d515be2dc9606dc39d1 (patch) | |
tree | 110716a883abc7e41f3507f86973224dc4bc0adb /media/ndk/NdkMediaExtractor.cpp | |
parent | 021cf9634ab09c0753a40b7c9ef4ba603be5c3da (diff) | |
download | frameworks_av-050eb3280d7305b84f723d515be2dc9606dc39d1.zip frameworks_av-050eb3280d7305b84f723d515be2dc9606dc39d1.tar.gz frameworks_av-050eb3280d7305b84f723d515be2dc9606dc39d1.tar.bz2 |
Some crypto stuff, error codes
Add crypto/drm related functions, define some media errors
instead of using magic numbers in the code.
Change-Id: I5924cba0bfcdb3623073c9182a646b70f4ead5a5
Diffstat (limited to 'media/ndk/NdkMediaExtractor.cpp')
-rw-r--r-- | media/ndk/NdkMediaExtractor.cpp | 148 |
1 files changed, 143 insertions, 5 deletions
diff --git a/media/ndk/NdkMediaExtractor.cpp b/media/ndk/NdkMediaExtractor.cpp index 681633a..0a66988 100644 --- a/media/ndk/NdkMediaExtractor.cpp +++ b/media/ndk/NdkMediaExtractor.cpp @@ -18,12 +18,14 @@ #define LOG_TAG "NdkMediaExtractor" +#include "NdkMediaError.h" #include "NdkMediaExtractor.h" #include "NdkMediaFormatPriv.h" #include <utils/Log.h> #include <utils/StrongPointer.h> +#include <media/hardware/CryptoAPI.h> #include <media/stagefright/foundation/ABuffer.h> #include <media/stagefright/foundation/AMessage.h> #include <media/stagefright/MetaData.h> @@ -41,11 +43,12 @@ static int translate_error(status_t err) { return OK; } ALOGE("sf error code: %d", err); - return -1000; + return AMEDIAERROR_GENERIC; } struct AMediaExtractor { sp<NuMediaExtractor> mImpl; + sp<ABuffer> mPsshBuf; }; @@ -79,14 +82,14 @@ int AMediaExtractor_setDataSource(AMediaExtractor *mData, const char *location) if (env == NULL) { ALOGE("setDataSource(path) must be called from Java thread"); env->ExceptionClear(); - return -1; + return AMEDIAERROR_UNSUPPORTED; } jclass mediahttpclass = env->FindClass("android/media/MediaHTTPService"); if (mediahttpclass == NULL) { ALOGE("can't find MediaHttpService"); env->ExceptionClear(); - return -1; + return AMEDIAERROR_UNSUPPORTED; } jmethodID mediaHttpCreateMethod = env->GetStaticMethodID(mediahttpclass, @@ -94,7 +97,7 @@ int AMediaExtractor_setDataSource(AMediaExtractor *mData, const char *location) if (mediaHttpCreateMethod == NULL) { ALOGE("can't find method"); env->ExceptionClear(); - return -1; + return AMEDIAERROR_UNSUPPORTED; } jstring jloc = env->NewStringUTF(location); @@ -110,7 +113,7 @@ int AMediaExtractor_setDataSource(AMediaExtractor *mData, const char *location) mData->mImpl->setDataSource(httpService, location, NULL); env->ExceptionClear(); - return 0; + return OK; } int AMediaExtractor_getTrackCount(AMediaExtractor *mData) { @@ -184,6 +187,141 @@ int64_t AMediaExtractor_getSampletime(AMediaExtractor *mData) { return time; } +PsshInfo* AMediaExtractor_getPsshInfo(AMediaExtractor *ex) { + + if (ex->mPsshBuf != NULL) { + return (PsshInfo*) ex->mPsshBuf->data(); + } + + sp<AMessage> format; + ex->mImpl->getFileFormat(&format); + sp<ABuffer> buffer; + if(!format->findBuffer("pssh", &buffer)) { + return NULL; + } + + // the format of the buffer is 1 or more of: + // { + // 16 byte uuid + // 4 byte data length N + // N bytes of data + // } + + // Determine the number of entries in the source data. + // Since we got the data from stagefright, we trust it is valid and properly formatted. + const uint8_t* data = buffer->data(); + size_t len = buffer->size(); + size_t numentries = 0; + while (len > 0) { + numentries++; + + // skip uuid + data += 16; + len -= 16; + + // get data length + uint32_t datalen = *((uint32_t*)data); + data += 4; + len -= 4; + + // skip the data + data += datalen; + len -= datalen; + } + + // there are <numentries> in the buffer, we need + // (source buffer size) + 4 + (4 * numentries) bytes for the PsshInfo structure + size_t newsize = buffer->size() + 4 + (4 * numentries); + ex->mPsshBuf = new ABuffer(newsize); + ex->mPsshBuf->setRange(0, newsize); + + // copy data + const uint8_t* src = buffer->data(); + uint8_t* dst = ex->mPsshBuf->data(); + uint8_t* dstdata = dst + 4 + numentries * sizeof(PsshEntry); + *((uint32_t*)dst) = numentries; + dst += 4; + for (size_t i = 0; i < numentries; i++) { + // copy uuid + memcpy(dst, src, 16); + src += 16; + dst += 16; + + // get/copy data length + uint32_t datalen = *((uint32_t*)src); + memcpy(dst, src, 4); + src += 4; + dst += 4; + + // the next entry in the destination is a pointer to the actual data, which we store + // after the array of PsshEntry + memcpy(dst, &dstdata, sizeof(dstdata)); + dst += 4; + + // copy the actual data + memcpy(dstdata, src, datalen); + dstdata += datalen; + src += datalen; + } + + return (PsshInfo*) ex->mPsshBuf->data(); +} + +AMediaCodecCryptoInfo *AMediaExtractor_getSampleCryptoInfo(AMediaExtractor *ex) { + sp<MetaData> meta; + if(ex->mImpl->getSampleMeta(&meta) != 0) { + return NULL; + } + + uint32_t type; + const void *crypteddata; + size_t cryptedsize; + if (!meta->findData(kKeyEncryptedSizes, &type, &crypteddata, &cryptedsize)) { + return NULL; + } + size_t numSubSamples = cryptedsize / sizeof(size_t); + + const void *cleardata; + size_t clearsize; + if (meta->findData(kKeyPlainSizes, &type, &cleardata, &clearsize)) { + if (clearsize != cryptedsize) { + // The two must be of the same length. + return NULL; + } + } + + const void *key; + size_t keysize; + if (meta->findData(kKeyCryptoIV, &type, &key, &keysize)) { + if (keysize != 16) { + // IVs must be 16 bytes in length. + return NULL; + } + } + + const void *iv; + size_t ivsize; + if (meta->findData(kKeyCryptoIV, &type, &iv, &ivsize)) { + if (ivsize != 16) { + // IVs must be 16 bytes in length. + return NULL; + } + } + + int32_t mode; + if (!meta->findInt32(kKeyCryptoMode, &mode)) { + mode = CryptoPlugin::kMode_AES_CTR; + } + + return AMediaCodecCryptoInfo_new( + numSubSamples, + (uint8_t*) key, + (uint8_t*) iv, + mode, + (size_t*) cleardata, + (size_t*) crypteddata); +} + } // extern "C" |