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:
Binary file not shown.
Binary file not shown.
@@ -70,6 +70,7 @@ typedef void (*WVSocketInfoCallback)(int fd, int status, void * context);
|
|||||||
// [in] dts - Decode timestamp, 90 KHz clock
|
// [in] dts - Decode timestamp, 90 KHz clock
|
||||||
// [in] pts - Presentation timestamp, 90 KHz clock
|
// [in] pts - Presentation timestamp, 90 KHz clock
|
||||||
// [in] au_end - Indicates end of Access Unit (last CU in frame)
|
// [in] au_end - Indicates end of Access Unit (last CU in frame)
|
||||||
|
// [in] context - Client context established from WV_Setup
|
||||||
//
|
//
|
||||||
// Returns:
|
// Returns:
|
||||||
// - WV_Status_OK: Decryption succeeded
|
// - 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.
|
// - Error code indicating problem. Causes playback to halt.
|
||||||
//
|
//
|
||||||
typedef WVStatus (*WVDecryptCallback)(WVEsSelector es_type, void* input, void* output, size_t length,
|
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 {
|
enum WVDecryptCallbackMode {
|
||||||
WVDecryptCallbackMode_MultiCU = 0, // WVDecryptCallback called repeatedly until buffer exhausted
|
WVDecryptCallbackMode_MultiCU = 0, // WVDecryptCallback called repeatedly until buffer exhausted
|
||||||
|
|||||||
Binary file not shown.
@@ -98,7 +98,8 @@ WVMExtractorImpl::WVMExtractorImpl(sp<DataSource> dataSource)
|
|||||||
mIsLiveStream(false),
|
mIsLiveStream(false),
|
||||||
mSession(NULL),
|
mSession(NULL),
|
||||||
mSetupStatus(OK),
|
mSetupStatus(OK),
|
||||||
mUIDIsSet(false)
|
mUIDIsSet(false),
|
||||||
|
mCryptoPluginMode(false)
|
||||||
{
|
{
|
||||||
dataSource->getDrmInfo(sDecryptHandle, &sDrmManagerClient);
|
dataSource->getDrmInfo(sDecryptHandle, &sDrmManagerClient);
|
||||||
|
|
||||||
@@ -340,12 +341,18 @@ status_t WVMExtractorImpl::readMetaData()
|
|||||||
|
|
||||||
mVideoSource->delegateDataSource(mDataSource);
|
mVideoSource->delegateDataSource(mDataSource);
|
||||||
|
|
||||||
mFileMetaData->setCString(kKeyMIMEType, "video/mp4");
|
mFileMetaData->setCString(kKeyMIMEType, "video/wvm");
|
||||||
|
|
||||||
mHaveMetaData = true;
|
mHaveMetaData = true;
|
||||||
|
|
||||||
mInfoListener->configureHeartbeat();
|
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;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -514,6 +521,18 @@ bool WVMExtractorImpl::getAdaptiveStreamingMode() const
|
|||||||
return mUseAdaptiveStreaming;
|
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)
|
void WVMExtractorImpl::setUID(uid_t uid)
|
||||||
{
|
{
|
||||||
//ALOGD("WVMExtractorImpl::setUID(%d)", (uint32_t)uid);
|
//ALOGD("WVMExtractorImpl::setUID(%d)", (uint32_t)uid);
|
||||||
|
|||||||
@@ -11,6 +11,8 @@
|
|||||||
#include "media/stagefright/foundation/ADebug.h"
|
#include "media/stagefright/foundation/ADebug.h"
|
||||||
#include "media/stagefright/MediaErrors.h"
|
#include "media/stagefright/MediaErrors.h"
|
||||||
#include "media/stagefright/MediaDefs.h"
|
#include "media/stagefright/MediaDefs.h"
|
||||||
|
#include "media/stagefright/MetaData.h"
|
||||||
|
#include "media/hardware/CryptoAPI.h"
|
||||||
#include "AndroidHooks.h"
|
#include "AndroidHooks.h"
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
@@ -112,19 +114,11 @@ status_t WVMMediaSource::start(MetaData *)
|
|||||||
ALOGE("WV_Play returned status %d in WVMMediaSource::start\n", result);
|
ALOGE("WV_Play returned status %d in WVMMediaSource::start\n", result);
|
||||||
return ERROR_IO;
|
return ERROR_IO;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef REQUIRE_SECURE_BUFFERS
|
|
||||||
allocBufferGroup();
|
|
||||||
#else
|
|
||||||
if (mIsLiveStream) {
|
|
||||||
allocBufferGroup();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
// audio
|
|
||||||
allocBufferGroup();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!mGroup)
|
||||||
|
allocBufferGroup();
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,7 +233,8 @@ status_t WVMMediaSource::read(MediaBuffer **buffer, const ReadOptions *options)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef REQUIRE_SECURE_BUFFERS
|
#ifdef REQUIRE_SECURE_BUFFERS
|
||||||
sDecryptContext[mESSelector].Initialize(mediaBuf);
|
mDecryptContext.Initialize(mediaBuf);
|
||||||
|
mEncryptedSizes.clear();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
size_t bytesRead;
|
size_t bytesRead;
|
||||||
@@ -302,7 +297,7 @@ status_t WVMMediaSource::read(MediaBuffer **buffer, const ReadOptions *options)
|
|||||||
|
|
||||||
#ifdef REQUIRE_SECURE_BUFFERS
|
#ifdef REQUIRE_SECURE_BUFFERS
|
||||||
if (mESSelector == WV_EsSelector_Video && !mIsLiveStream) {
|
if (mESSelector == WV_EsSelector_Video && !mIsLiveStream) {
|
||||||
bytesRead = sDecryptContext[mESSelector].mOffset;
|
bytesRead = mDecryptContext.mOffset;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -326,7 +321,8 @@ status_t WVMMediaSource::read(MediaBuffer **buffer, const ReadOptions *options)
|
|||||||
// drop frames up to next sync if requested
|
// drop frames up to next sync if requested
|
||||||
usleep(10000);
|
usleep(10000);
|
||||||
#ifdef REQUIRE_SECURE_BUFFERS
|
#ifdef REQUIRE_SECURE_BUFFERS
|
||||||
sDecryptContext[mESSelector].Initialize(mediaBuf);
|
mDecryptContext.Initialize(mediaBuf);
|
||||||
|
mEncryptedSizes.clear();
|
||||||
#endif
|
#endif
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -365,6 +361,14 @@ status_t WVMMediaSource::read(MediaBuffer **buffer, const ReadOptions *options)
|
|||||||
|
|
||||||
mediaBuf->set_range(0, bytesRead + offset);
|
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
|
#if 0
|
||||||
// debug code - log packets to files
|
// debug code - log packets to files
|
||||||
char filename[32];
|
char filename[32];
|
||||||
@@ -397,41 +401,54 @@ status_t WVMMediaSource::read(MediaBuffer **buffer, const ReadOptions *options)
|
|||||||
|
|
||||||
#ifdef REQUIRE_SECURE_BUFFERS
|
#ifdef REQUIRE_SECURE_BUFFERS
|
||||||
|
|
||||||
WVMMediaSource::DecryptContext WVMMediaSource::sDecryptContext[2] = {};
|
|
||||||
|
|
||||||
WVStatus WVMMediaSource::DecryptCallback(WVEsSelector esType, void* input, void* output, size_t length,
|
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",
|
//ALOGD("DecryptCallback(type=%d, in=%p, out=%p, len=%d, key=%d\n",
|
||||||
// (int)esType, input, output, length, key);
|
// (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;
|
OEMCrypto_UINT32 copied = length;
|
||||||
OEMCryptoResult result;
|
OEMCryptoResult result;
|
||||||
WVStatus status;
|
WVStatus status = WV_Status_OK;
|
||||||
unsigned char *iv = NULL;
|
unsigned char *iv = NULL;
|
||||||
|
|
||||||
if (key)
|
if (extractor->getCryptoPluginMode()) {
|
||||||
iv = context.mIV;
|
// just determine crypto unit boundaries
|
||||||
|
if (key) {
|
||||||
if (esType == WV_EsSelector_Video) {
|
source->addEncryptedSize(length);
|
||||||
result = OEMCrypto_DecryptVideo(iv, (OEMCrypto_UINT8 *)input, length,
|
}
|
||||||
(OEMCrypto_UINT32)(char *)context.mMediaBuf->data(),
|
|
||||||
context.mOffset, &copied);
|
|
||||||
} else {
|
} else {
|
||||||
result = OEMCrypto_DecryptAudio(iv, (OEMCrypto_UINT8 *)input, length,
|
// do decrypt
|
||||||
(OEMCrypto_UINT8 *)context.mMediaBuf->data() + context.mOffset,
|
if (key)
|
||||||
&copied);
|
iv = context.mIV;
|
||||||
}
|
|
||||||
|
|
||||||
if (result == OEMCrypto_SUCCESS) {
|
if (esType == WV_EsSelector_Video) {
|
||||||
status = WV_Status_OK;
|
result = OEMCrypto_DecryptVideo(iv, (OEMCrypto_UINT8 *)input, length,
|
||||||
}
|
(OEMCrypto_UINT32)(char *)context.mMediaBuf->data(),
|
||||||
else {
|
context.mOffset, &copied);
|
||||||
status = WV_Status_Unknown;
|
} else {
|
||||||
ALOGD("OEMCrypto decrypt failure: %d", result);
|
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;
|
return status;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,11 +34,18 @@ public:
|
|||||||
|
|
||||||
virtual sp<MetaData> getMetaData();
|
virtual sp<MetaData> getMetaData();
|
||||||
virtual int64_t getCachedDurationUs(status_t *finalStatus);
|
virtual int64_t getCachedDurationUs(status_t *finalStatus);
|
||||||
|
|
||||||
virtual void setAdaptiveStreamingMode(bool adaptive);
|
virtual void setAdaptiveStreamingMode(bool adaptive);
|
||||||
bool getAdaptiveStreamingMode() const;
|
bool getAdaptiveStreamingMode() const;
|
||||||
|
|
||||||
|
virtual void setCryptoPluginMode(bool cryptoPluginMode);
|
||||||
|
bool getCryptoPluginMode() const;
|
||||||
|
|
||||||
virtual void setUID(uid_t uid);
|
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 SocketInfoCallback(int fd, int op, void *context);
|
||||||
static void cleanup();
|
static void cleanup();
|
||||||
|
|
||||||
@@ -69,6 +76,14 @@ private:
|
|||||||
bool mUIDIsSet;
|
bool mUIDIsSet;
|
||||||
uid_t mUID;
|
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();
|
status_t readMetaData();
|
||||||
|
|
||||||
const static size_t kStreamCacheSize = 10 * 1024 * 1024;
|
const static size_t kStreamCacheSize = 10 * 1024 * 1024;
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ public:
|
|||||||
virtual status_t setBuffers(const Vector<MediaBuffer *> &buffers);
|
virtual status_t setBuffers(const Vector<MediaBuffer *> &buffers);
|
||||||
virtual status_t read(MediaBuffer **buffer, const ReadOptions *options = NULL);
|
virtual status_t read(MediaBuffer **buffer, const ReadOptions *options = NULL);
|
||||||
|
|
||||||
|
void addEncryptedSize(size_t size) { mEncryptedSizes.push_back(size); }
|
||||||
|
|
||||||
static int sLastError;
|
static int sLastError;
|
||||||
|
|
||||||
#ifdef REQUIRE_SECURE_BUFFERS
|
#ifdef REQUIRE_SECURE_BUFFERS
|
||||||
@@ -53,10 +55,13 @@ public:
|
|||||||
static const int kCryptoBlockSize = 16;
|
static const int kCryptoBlockSize = 16;
|
||||||
unsigned char mIV[kCryptoBlockSize];
|
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
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -74,6 +79,7 @@ private:
|
|||||||
bool mLogOnce;
|
bool mLogOnce;
|
||||||
bool mIsLiveStream;
|
bool mIsLiveStream;
|
||||||
bool mNewSegment;
|
bool mNewSegment;
|
||||||
|
bool mCryptoPluginMode;
|
||||||
|
|
||||||
MediaBufferGroup *mGroup;
|
MediaBufferGroup *mGroup;
|
||||||
|
|
||||||
@@ -83,6 +89,8 @@ private:
|
|||||||
sp<WVMFileSource> mFileSource;
|
sp<WVMFileSource> mFileSource;
|
||||||
sp<DataSource> mDataSource;
|
sp<DataSource> mDataSource;
|
||||||
|
|
||||||
|
Vector<size_t> mEncryptedSizes;
|
||||||
|
|
||||||
void allocBufferGroup();
|
void allocBufferGroup();
|
||||||
|
|
||||||
WVMMediaSource(const WVMMediaSource &);
|
WVMMediaSource(const WVMMediaSource &);
|
||||||
|
|||||||
Reference in New Issue
Block a user