Add CryptoPluginMode to WV extractor

Allows the WV extractor to run in a mode that is compatible with
the DRM CryptoPlugin HAL API, where decryption is deferred
until the encrypted data is sent through the CryptoPlugin to
the codec.

This patch does:
 (1) Adds a flag mCryptoPluginMode that controls this behavior
     [Note: need framework support to enable/disable this]
 (2) Accumulates information in track metadata to delineate
     crypto unit boundaries for the CryptoPlugin

related-to-bug: 5986621

Change-Id: I3318d5cde38c7b02a7bdb56aca9aece852c9781c
This commit is contained in:
Jeff Tinker
2012-04-13 00:01:05 -07:00
parent aaa8479c34
commit a9f82e979f
8 changed files with 105 additions and 44 deletions

View File

@@ -70,6 +70,7 @@ typedef void (*WVSocketInfoCallback)(int fd, int status, void * context);
// [in] dts - Decode timestamp, 90 KHz clock
// [in] pts - Presentation timestamp, 90 KHz clock
// [in] au_end - Indicates end of Access Unit (last CU in frame)
// [in] context - Client context established from WV_Setup
//
// Returns:
// - WV_Status_OK: Decryption succeeded
@@ -78,7 +79,8 @@ typedef void (*WVSocketInfoCallback)(int fd, int status, void * context);
// - Error code indicating problem. Causes playback to halt.
//
typedef WVStatus (*WVDecryptCallback)(WVEsSelector es_type, void* input, void* output, size_t length,
int key, unsigned long long dts, unsigned long long pts, bool au_end);
int key, unsigned long long dts, unsigned long long pts,
bool au_end, void *context);
enum WVDecryptCallbackMode {
WVDecryptCallbackMode_MultiCU = 0, // WVDecryptCallback called repeatedly until buffer exhausted

View File

@@ -98,7 +98,8 @@ WVMExtractorImpl::WVMExtractorImpl(sp<DataSource> dataSource)
mIsLiveStream(false),
mSession(NULL),
mSetupStatus(OK),
mUIDIsSet(false)
mUIDIsSet(false),
mCryptoPluginMode(false)
{
dataSource->getDrmInfo(sDecryptHandle, &sDrmManagerClient);
@@ -340,12 +341,18 @@ status_t WVMExtractorImpl::readMetaData()
mVideoSource->delegateDataSource(mDataSource);
mFileMetaData->setCString(kKeyMIMEType, "video/mp4");
mFileMetaData->setCString(kKeyMIMEType, "video/wvm");
mHaveMetaData = true;
mInfoListener->configureHeartbeat();
if (mCryptoPluginMode) {
// In crypto plugin mode, need to trigger the drm plugin to begin
// license use on playback since the media player isn't involved.
sDrmManagerClient->setPlaybackStatus(sDecryptHandle, Playback::START, 0);
}
return OK;
}
@@ -514,6 +521,18 @@ bool WVMExtractorImpl::getAdaptiveStreamingMode() const
return mUseAdaptiveStreaming;
}
void WVMExtractorImpl::setCryptoPluginMode(bool cryptoPluginMode)
{
//ALOGD("WVMExtractorImpl::setCryptoPluginMode(%d)", cryptoPluginMode);
mCryptoPluginMode = cryptoPluginMode;
}
bool WVMExtractorImpl::getCryptoPluginMode() const
{
//ALOGD("WVMExtractorImpl::getCryptoPluginMode - %d", mCryptoPluginMode);
return mCryptoPluginMode;
}
void WVMExtractorImpl::setUID(uid_t uid)
{
//ALOGD("WVMExtractorImpl::setUID(%d)", (uint32_t)uid);

View File

@@ -11,6 +11,8 @@
#include "media/stagefright/foundation/ADebug.h"
#include "media/stagefright/MediaErrors.h"
#include "media/stagefright/MediaDefs.h"
#include "media/stagefright/MetaData.h"
#include "media/hardware/CryptoAPI.h"
#include "AndroidHooks.h"
namespace android {
@@ -112,19 +114,11 @@ status_t WVMMediaSource::start(MetaData *)
ALOGE("WV_Play returned status %d in WVMMediaSource::start\n", result);
return ERROR_IO;
}
#ifndef REQUIRE_SECURE_BUFFERS
allocBufferGroup();
#else
if (mIsLiveStream) {
allocBufferGroup();
}
#endif
} else {
// audio
allocBufferGroup();
}
if (!mGroup)
allocBufferGroup();
return OK;
}
@@ -239,7 +233,8 @@ status_t WVMMediaSource::read(MediaBuffer **buffer, const ReadOptions *options)
}
#ifdef REQUIRE_SECURE_BUFFERS
sDecryptContext[mESSelector].Initialize(mediaBuf);
mDecryptContext.Initialize(mediaBuf);
mEncryptedSizes.clear();
#endif
size_t bytesRead;
@@ -302,7 +297,7 @@ status_t WVMMediaSource::read(MediaBuffer **buffer, const ReadOptions *options)
#ifdef REQUIRE_SECURE_BUFFERS
if (mESSelector == WV_EsSelector_Video && !mIsLiveStream) {
bytesRead = sDecryptContext[mESSelector].mOffset;
bytesRead = mDecryptContext.mOffset;
}
#endif
@@ -326,7 +321,8 @@ status_t WVMMediaSource::read(MediaBuffer **buffer, const ReadOptions *options)
// drop frames up to next sync if requested
usleep(10000);
#ifdef REQUIRE_SECURE_BUFFERS
sDecryptContext[mESSelector].Initialize(mediaBuf);
mDecryptContext.Initialize(mediaBuf);
mEncryptedSizes.clear();
#endif
continue;
}
@@ -365,6 +361,14 @@ status_t WVMMediaSource::read(MediaBuffer **buffer, const ReadOptions *options)
mediaBuf->set_range(0, bytesRead + offset);
#ifdef REQUIRE_SECURE_BUFFERS
if (!mIsLiveStream && mEncryptedSizes.size()) {
mediaBuf->meta_data()->setData(kKeyEncryptedSizes, 0, &mEncryptedSizes[0],
mEncryptedSizes.size() * sizeof(size_t));
mediaBuf->meta_data()->setInt32(kKeyCryptoMode, CryptoPlugin::kMode_AES_WV);
}
#endif
#if 0
// debug code - log packets to files
char filename[32];
@@ -397,41 +401,54 @@ status_t WVMMediaSource::read(MediaBuffer **buffer, const ReadOptions *options)
#ifdef REQUIRE_SECURE_BUFFERS
WVMMediaSource::DecryptContext WVMMediaSource::sDecryptContext[2] = {};
WVStatus WVMMediaSource::DecryptCallback(WVEsSelector esType, void* input, void* output, size_t length,
int key, unsigned long long dts, unsigned long long pts, bool au_end)
int key, unsigned long long dts, unsigned long long pts, bool au_end,
void *obj)
{
//ALOGD("DecryptCallback(type=%d, in=%p, out=%p, len=%d, key=%d\n",
// (int)esType, input, output, length, key);
DecryptContext &context = sDecryptContext[esType];
WVMExtractorImpl *extractor = (WVMExtractorImpl *)obj;
sp<WVMMediaSource> source;
if (esType == WV_EsSelector_Video)
source = extractor->getVideoSource();
else
source = extractor->getAudioSource();
DecryptContext &context = source->getDecryptContext();
OEMCrypto_UINT32 copied = length;
OEMCryptoResult result;
WVStatus status;
WVStatus status = WV_Status_OK;
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);
if (extractor->getCryptoPluginMode()) {
// just determine crypto unit boundaries
if (key) {
source->addEncryptedSize(length);
}
} else {
result = OEMCrypto_DecryptAudio(iv, (OEMCrypto_UINT8 *)input, length,
(OEMCrypto_UINT8 *)context.mMediaBuf->data() + context.mOffset,
&copied);
}
// do decrypt
if (key)
iv = context.mIV;
if (result == OEMCrypto_SUCCESS) {
status = WV_Status_OK;
}
else {
status = WV_Status_Unknown;
ALOGD("OEMCrypto decrypt failure: %d", result);
}
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);
}
context.mOffset += copied;
if (result == OEMCrypto_SUCCESS) {
status = WV_Status_OK;
} else {
status = WV_Status_Unknown;
ALOGD("OEMCrypto decrypt failure: %d", result);
}
context.mOffset += copied;
}
return status;
}

View File

@@ -34,11 +34,18 @@ public:
virtual sp<MetaData> getMetaData();
virtual int64_t getCachedDurationUs(status_t *finalStatus);
virtual void setAdaptiveStreamingMode(bool adaptive);
bool getAdaptiveStreamingMode() const;
virtual void setCryptoPluginMode(bool cryptoPluginMode);
bool getCryptoPluginMode() const;
virtual void setUID(uid_t uid);
sp<WVMMediaSource> getAudioSource() const { return mAudioSource; }
sp<WVMMediaSource> getVideoSource() const { return mVideoSource; }
static void SocketInfoCallback(int fd, int op, void *context);
static void cleanup();
@@ -69,6 +76,14 @@ private:
bool mUIDIsSet;
uid_t mUID;
//
// if in CryptoPlugin mode, the extractor doesn't decrypt,
// it just accumulates the ranges of data requiring decryption
// into the MediaBuffer's metadata, the decryption happens
// later via the CryptoPlugin
//
bool mCryptoPluginMode;
status_t readMetaData();
const static size_t kStreamCacheSize = 10 * 1024 * 1024;

View File

@@ -38,6 +38,8 @@ public:
virtual status_t setBuffers(const Vector<MediaBuffer *> &buffers);
virtual status_t read(MediaBuffer **buffer, const ReadOptions *options = NULL);
void addEncryptedSize(size_t size) { mEncryptedSizes.push_back(size); }
static int sLastError;
#ifdef REQUIRE_SECURE_BUFFERS
@@ -53,10 +55,13 @@ public:
static const int kCryptoBlockSize = 16;
unsigned char mIV[kCryptoBlockSize];
};
static WVStatus DecryptCallback(WVEsSelector esType, void* input, void* output, size_t length,
int key, unsigned long long dts, unsigned long long pts, bool au_end);
static DecryptContext sDecryptContext[2]; // audio vs. video
static WVStatus DecryptCallback(WVEsSelector esType, void* input, void* output, size_t length,
int key, unsigned long long dts, unsigned long long pts,
bool au_end, void *context);
DecryptContext& getDecryptContext() { return mDecryptContext; }
private:
DecryptContext mDecryptContext;
#endif
protected:
@@ -74,6 +79,7 @@ private:
bool mLogOnce;
bool mIsLiveStream;
bool mNewSegment;
bool mCryptoPluginMode;
MediaBufferGroup *mGroup;
@@ -83,6 +89,8 @@ private:
sp<WVMFileSource> mFileSource;
sp<DataSource> mDataSource;
Vector<size_t> mEncryptedSizes;
void allocBufferGroup();
WVMMediaSource(const WVMMediaSource &);