diff --git a/proprietary/drmwvmplugin/lib/libwvocs_L1.a b/proprietary/drmwvmplugin/lib/libwvocs_L1.a index 26f6ac60..6e55cdd7 100644 Binary files a/proprietary/drmwvmplugin/lib/libwvocs_L1.a and b/proprietary/drmwvmplugin/lib/libwvocs_L1.a differ diff --git a/proprietary/streamcontrol/lib/libWVStreamControlAPI_L1.so b/proprietary/streamcontrol/lib/libWVStreamControlAPI_L1.so index 2b348aa5..3d359163 100644 Binary files a/proprietary/streamcontrol/lib/libWVStreamControlAPI_L1.so and b/proprietary/streamcontrol/lib/libWVStreamControlAPI_L1.so differ diff --git a/proprietary/wvm/WVMExtractorImpl.cpp b/proprietary/wvm/WVMExtractorImpl.cpp index 9857c486..b2f1f49b 100644 --- a/proprietary/wvm/WVMExtractorImpl.cpp +++ b/proprietary/wvm/WVMExtractorImpl.cpp @@ -114,8 +114,25 @@ void WVMExtractorImpl::Initialize() { //LOGD("WVMExtractorImpl::Initialize(%d)\n", getAdaptiveStreamingMode()); WVCredentials credentials; + WVStatus result; + + if (mDataSource->getUri().size() > 0 && getAdaptiveStreamingMode()) { + mIsLiveStream = (mDataSource->getUri().getPathExtension().find(".m3u8") == 0); + } + +#ifdef REQUIRE_SECURE_BUFFERS + if (!mIsLiveStream) { + LOGD("Not live, using decrypt callback"); + WVCallbacks callbacks = {NULL, NULL, NULL, NULL, NULL, NULL, WVMMediaSource::DecryptCallback}; + result = WV_Initialize(&callbacks); + } else { + LOGD("Live, NOT using decrypt callback"); + result = WV_Initialize(NULL); + } +#else + result = WV_Initialize(NULL); +#endif - WVStatus result = WV_Initialize(NULL); if (result != WV_Status_OK) { LOGE("WV_Initialize returned status %d\n", result); mSetupStatus = ERROR_IO; @@ -128,8 +145,6 @@ void WVMExtractorImpl::Initialize() result = WV_Setup(mSession, mDataSource->getUri().string(), "RAW/RAW/RAW;destination=getdata", credentials, WV_OutputFormat_ES, kStreamCacheSize); - - mIsLiveStream = (mDataSource->getUri().getPathExtension().find(".m3u8") == 0); } else { // No URI supplied or not adaptive, pull data from the stagefright data source. mFileSource = new WVMFileSource(mDataSource); diff --git a/proprietary/wvm/WVMMediaSource.cpp b/proprietary/wvm/WVMMediaSource.cpp index a806c30a..50b57682 100644 --- a/proprietary/wvm/WVMMediaSource.cpp +++ b/proprietary/wvm/WVMMediaSource.cpp @@ -48,6 +48,11 @@ WVMMediaSource::WVMMediaSource(WVSession *session, WVEsSelector esSelector, mPts(0) { _ah010(_cb); +#ifdef REQUIRE_SECURE_BUFFERS + if (esSelector == WV_EsSelector_Video) { + OEMCrypto_Initialize(); + } +#endif } // Since the WVMExtractor lifetime is short, we delegate ownership of some resources @@ -246,6 +251,10 @@ status_t WVMMediaSource::read(MediaBuffer **buffer, const ReadOptions *options) return err; } +#ifdef REQUIRE_SECURE_BUFFERS + sDecryptContext[mESSelector].Initialize(mediaBuf); +#endif + size_t bytesRead; bool auStart; size_t offset = 0; @@ -332,12 +341,21 @@ status_t WVMMediaSource::read(MediaBuffer **buffer, const ReadOptions *options) if (seekNextSync && ((keyTime < seekTimeUs) || !syncFrame)) { // drop frames up to next sync if requested usleep(10000); +#ifdef REQUIRE_SECURE_BUFFERS + sDecryptContext[mESSelector].Initialize(mediaBuf); +#endif continue; } if (offset + bytesRead < mediaBuf->size()) break; +#ifdef REQUIRE_SECURE_BUFFERS + LOGD("buffer overflow"); + mediaBuf->release(); + return ERROR_IO; +#endif + //LOGD("Resizing..."); // This buffer is too small, allocate a larger buffer twice the size @@ -391,6 +409,42 @@ status_t WVMMediaSource::read(MediaBuffer **buffer, const ReadOptions *options) return OK; } +#ifdef REQUIRE_SECURE_BUFFERS + +WVMMediaSource::DecryptContext WVMMediaSource::sDecryptContext[2] = {}; + +void WVMMediaSource::DecryptCallback(WVEsSelector esType, void* input, void* output, + size_t length, int key) +{ + //LOGD("DecryptCallback(type=%d, in=%p, out=%p, len=%d, key=%d\n", + // (int)esType, input, output, length, key); + DecryptContext &context = sDecryptContext[esType]; + OEMCrypto_UINT32 copied = length; + OEMCryptoResult result; + unsigned char *iv = NULL; + + if (key) + iv = context.mIV; + + if (esType == WV_EsSelector_Video) { + result = OEMCrypto_DecryptVideo(iv, (OEMCrypto_UINT8 *)input, length, + (OEMCrypto_UINT32)(char *)context.mMediaBuf->data(), + context.mOffset, &copied); + } else { + result = OEMCrypto_DecryptAudio(iv, (OEMCrypto_UINT8 *)input, length, + (OEMCrypto_UINT8 *)context.mMediaBuf->data() + context.mOffset, + &copied); + } + + if (result != OEMCrypto_SUCCESS) { + LOGD("OEMCrypto decrypt failure: %d", result); + } + + context.mOffset += copied; +} +#endif + + WVMMediaSource::~WVMMediaSource() { //LOGD("WVMMediaSource::~WVMMediaSource()"); @@ -402,6 +456,9 @@ WVMMediaSource::~WVMMediaSource() if (mESSelector == WV_EsSelector_Video) { if (mSession != NULL) { WV_Teardown(mSession); +#ifdef REQUIRE_SECURE_BUFFERS + OEMCrypto_Terminate(); +#endif } WVMExtractorImpl::cleanup(); } diff --git a/proprietary/wvm/include/OEMCrypto_L1.h b/proprietary/wvm/include/OEMCrypto_L1.h new file mode 100755 index 00000000..87a2b34e --- /dev/null +++ b/proprietary/wvm/include/OEMCrypto_L1.h @@ -0,0 +1,49 @@ +/******************************************************************************* + * + * Subset of the OEMCrypto APIs required for L1 support since they are called + * from libwvm. + * + ******************************************************************************/ + +#ifndef _OEMCRYPTO_L1_H +#define _OEMCRYPTO_L1_H + +typedef unsigned char OEMCrypto_UINT8; +typedef char OEMCrypto_INT8; +typedef unsigned int OEMCrypto_UINT32; +typedef unsigned int OEMCrypto_SECURE_BUFFER; + + +typedef enum OEMCryptoResult { + OEMCrypto_SUCCESS = 0 +} OEMCryptoResult; + + +#ifdef __cplusplus +extern "C" { +#endif + +#define OEMCrypto_Initialize _oec01 +#define OEMCrypto_Terminate _oec02 +#define OEMCrypto_DecryptVideo _oec05 +#define OEMCrypto_DecryptAudio _oec06 + +OEMCryptoResult OEMCrypto_Initialize(void); +OEMCryptoResult OEMCrypto_Terminate(void); +OEMCryptoResult OEMCrypto_DecryptVideo(const OEMCrypto_UINT8*, + const OEMCrypto_UINT8*, const OEMCrypto_UINT32, + OEMCrypto_UINT32, OEMCrypto_UINT32, OEMCrypto_UINT32 *); + + +OEMCryptoResult OEMCrypto_DecryptAudio(const OEMCrypto_UINT8*, + const OEMCrypto_UINT8*, const OEMCrypto_UINT32, + OEMCrypto_UINT8 *, OEMCrypto_UINT32 *); + + +#ifdef __cplusplus +} +#endif + +#endif + +/***************************** End of File *****************************/ diff --git a/proprietary/wvm/include/WVMMediaSource.h b/proprietary/wvm/include/WVMMediaSource.h index 50d7820b..c308c753 100644 --- a/proprietary/wvm/include/WVMMediaSource.h +++ b/proprietary/wvm/include/WVMMediaSource.h @@ -24,6 +24,9 @@ #include #include #include +#ifdef REQUIRE_SECURE_BUFFERS +#include "OEMCrypto_L1.h" +#endif namespace android { @@ -48,6 +51,24 @@ public: static int sLastError; +#ifdef REQUIRE_SECURE_BUFFERS + class DecryptContext { + public: + void Initialize(MediaBuffer *mediaBuf) { + mMediaBuf = mediaBuf; + mOffset = 0; + memset(mIV, 0, sizeof(mIV)); + } + MediaBuffer *mMediaBuf; + size_t mOffset; + static const int kCryptoBlockSize = 16; + unsigned char mIV[kCryptoBlockSize]; + }; + static void DecryptCallback(WVEsSelector esType, void* input, void* output, + size_t length, int key); + static DecryptContext sDecryptContext[2]; // audio vs. video +#endif + protected: virtual ~WVMMediaSource();