Move all Widevine code which have dependency on vendor modules from framework/base to vendor/widevine
Change-Id: I2b43e90c279391436f1bbb18ebd64961bec4f9ee
This commit is contained in:
Binary file not shown.
Binary file not shown.
48
proprietary/drmwvmplugin/Android.mk
Normal file
48
proprietary/drmwvmplugin/Android.mk
Normal file
@@ -0,0 +1,48 @@
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
ifeq ($(TARGET_ARCH),arm)
|
||||
|
||||
LOCAL_SRC_FILES:= \
|
||||
src/WVMDrmPlugin.cpp \
|
||||
src/WVMLogging.cpp
|
||||
|
||||
LOCAL_C_INCLUDES:= \
|
||||
bionic \
|
||||
bionic/libstdc++/include \
|
||||
external/stlport/stlport \
|
||||
vendor/widevine/proprietary/streamcontrol/include \
|
||||
vendor/widevine/proprietary/drmwvmplugin/include
|
||||
|
||||
LOCAL_MODULE := libdrmwvmplugin
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/drm
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := \
|
||||
libdrmframeworkcommon
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libutils \
|
||||
libcutils \
|
||||
libstlport \
|
||||
libz \
|
||||
libwvdrm \
|
||||
libWVStreamControlAPI
|
||||
|
||||
ifeq ($(TARGET_SIMULATOR),true)
|
||||
LOCAL_LDLIBS += -ldl
|
||||
else
|
||||
LOCAL_SHARED_LIBRARIES += libdl
|
||||
endif
|
||||
|
||||
LOCAL_PRELINK_MODULE := false
|
||||
|
||||
LOCAL_C_INCLUDES += \
|
||||
$(TOP)/frameworks/base/drm/libdrmframework/include \
|
||||
$(TOP)/frameworks/base/drm/libdrmframework/plugins/common/include \
|
||||
$(TOP)/frameworks/base/include
|
||||
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
endif
|
||||
111
proprietary/drmwvmplugin/include/WVMDrmPlugin.h
Normal file
111
proprietary/drmwvmplugin/include/WVMDrmPlugin.h
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __WVMDRMPLUGIN_H__
|
||||
#define __WVMDRMPLUGIN_H__
|
||||
|
||||
|
||||
#include <AndroidConfig.h>
|
||||
#include <DrmEngineBase.h>
|
||||
|
||||
#include "WVDRMPluginAPI.h"
|
||||
|
||||
|
||||
namespace android {
|
||||
|
||||
class WVMDrmPlugin : public DrmEngineBase
|
||||
{
|
||||
|
||||
public:
|
||||
WVMDrmPlugin();
|
||||
virtual ~WVMDrmPlugin();
|
||||
|
||||
protected:
|
||||
DrmConstraints* onGetConstraints(int uniqueId, const String8* path, int action);
|
||||
|
||||
DrmMetadata* onGetMetadata(int uniqueId, const String8* path);
|
||||
|
||||
status_t onInitialize(int uniqueId);
|
||||
|
||||
status_t onSetOnInfoListener(int uniqueId, const IDrmEngine::OnInfoListener* infoListener);
|
||||
|
||||
status_t onTerminate(int uniqueId);
|
||||
|
||||
bool onCanHandle(int uniqueId, const String8& path);
|
||||
|
||||
DrmInfoStatus* onProcessDrmInfo(int uniqueId, const DrmInfo* drmInfo);
|
||||
|
||||
status_t onSaveRights(int uniqueId, const DrmRights& drmRights,
|
||||
const String8& rightsPath, const String8& contentPath);
|
||||
|
||||
DrmInfo* onAcquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest);
|
||||
|
||||
String8 onGetOriginalMimeType(int uniqueId, const String8& path);
|
||||
|
||||
int onGetDrmObjectType(int uniqueId, const String8& path, const String8& mimeType);
|
||||
|
||||
int onCheckRightsStatus(int uniqueId, const String8& path, int action);
|
||||
|
||||
status_t onConsumeRights(int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve);
|
||||
|
||||
status_t onSetPlaybackStatus(
|
||||
int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, off64_t position);
|
||||
|
||||
bool onValidateAction(
|
||||
int uniqueId, const String8& path, int action, const ActionDescription& description);
|
||||
|
||||
status_t onRemoveRights(int uniqueId, const String8& path);
|
||||
|
||||
status_t onRemoveAllRights(int uniqueId);
|
||||
|
||||
status_t onOpenConvertSession(int uniqueId, int convertId);
|
||||
|
||||
DrmConvertedStatus* onConvertData(int uniqueId, int convertId, const DrmBuffer* inputData);
|
||||
|
||||
DrmConvertedStatus* onCloseConvertSession(int uniqueId, int convertId);
|
||||
|
||||
DrmSupportInfo* onGetSupportInfo(int uniqueId);
|
||||
|
||||
status_t onOpenDecryptSession(int uniqueId, DecryptHandle *decryptHandle,
|
||||
int fd, off64_t offset, off64_t length);
|
||||
|
||||
status_t onOpenDecryptSession(int uniqueId, DecryptHandle *decryptHandle,
|
||||
const char *uri);
|
||||
|
||||
status_t onCloseDecryptSession(int uniqueId, DecryptHandle* decryptHandle);
|
||||
|
||||
status_t onInitializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
|
||||
int decryptUnitId, const DrmBuffer* headerInfo);
|
||||
|
||||
status_t onDecrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
|
||||
const DrmBuffer* encBuffer, DrmBuffer** decBuffer,
|
||||
DrmBuffer *ivBuffer);
|
||||
|
||||
|
||||
status_t onFinalizeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId);
|
||||
|
||||
ssize_t onPread(int uniqueId, DecryptHandle* decryptHandle,
|
||||
void* buffer, ssize_t numBytes, off64_t offset);
|
||||
|
||||
private:
|
||||
const IDrmEngine::OnInfoListener *mOnInfoListener;
|
||||
WVDRMPluginAPI *mDrmPluginImpl;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif /* __WVMDRMPLUGIN__ */
|
||||
|
||||
22
proprietary/drmwvmplugin/include/WVMLogging.h
Normal file
22
proprietary/drmwvmplugin/include/WVMLogging.h
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __WVMLOGGING_H__
|
||||
#define __WVMLOGGING_H__
|
||||
|
||||
void android_printbuf(const char *buf);
|
||||
|
||||
#endif
|
||||
726
proprietary/drmwvmplugin/src/WVMDrmPlugin.cpp
Normal file
726
proprietary/drmwvmplugin/src/WVMDrmPlugin.cpp
Normal file
@@ -0,0 +1,726 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#define LOG_NDEBUG 0
|
||||
#define LOG_TAG "WVMDrmPlugIn"
|
||||
#include <utils/Log.h>
|
||||
#include <vector>
|
||||
|
||||
#include <drm/DrmRights.h>
|
||||
#include <drm/DrmConstraints.h>
|
||||
#include <drm/DrmInfo.h>
|
||||
#include <drm/DrmInfoStatus.h>
|
||||
#include <drm/DrmConvertedStatus.h>
|
||||
#include <drm/DrmInfoRequest.h>
|
||||
#include <drm/DrmSupportInfo.h>
|
||||
#include <drm/DrmMetadata.h>
|
||||
|
||||
#include "WVMDrmPlugin.h"
|
||||
#include "WVMLogging.h"
|
||||
#include "AndroidHooks.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace android;
|
||||
|
||||
|
||||
// This extern "C" is mandatory to be managed by TPlugInManager
|
||||
extern "C" IDrmEngine* create() {
|
||||
return new WVMDrmPlugin();
|
||||
}
|
||||
|
||||
// This extern "C" is mandatory to be managed by TPlugInManager
|
||||
extern "C" void destroy(IDrmEngine* pPlugIn) {
|
||||
delete pPlugIn;
|
||||
}
|
||||
|
||||
WVMDrmPlugin::WVMDrmPlugin()
|
||||
: DrmEngineBase(),
|
||||
mOnInfoListener(NULL),
|
||||
mDrmPluginImpl(WVDRMPluginAPI::create())
|
||||
{
|
||||
}
|
||||
|
||||
WVMDrmPlugin::~WVMDrmPlugin() {
|
||||
WVDRMPluginAPI::destroy(mDrmPluginImpl);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize plug-in
|
||||
*
|
||||
* @param[in] uniqueId Unique identifier for a session
|
||||
* @return status_t
|
||||
* Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
|
||||
*/
|
||||
status_t WVMDrmPlugin::onInitialize(int uniqueId) {
|
||||
//LOGD("WVMDrmPlugin::onInitialize : %d", uniqueId);
|
||||
AndroidSetLogCallout(android_printbuf);
|
||||
return DRM_NO_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Terminate the plug-in
|
||||
* and release resource bound to plug-in
|
||||
*
|
||||
* @param[in] uniqueId Unique identifier for a session
|
||||
* @return status_t
|
||||
* Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
|
||||
*/
|
||||
status_t WVMDrmPlugin::onTerminate(int uniqueId) {
|
||||
//LOGD("WVMDrmPlugin::onTerminate : %d", uniqueId);
|
||||
return DRM_NO_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a callback to be invoked when the caller required to
|
||||
* receive necessary information
|
||||
*
|
||||
* @param[in] uniqueId Unique identifier for a session
|
||||
* @param[in] infoListener Listener
|
||||
* @return status_t
|
||||
* Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
|
||||
*/
|
||||
status_t WVMDrmPlugin::onSetOnInfoListener(
|
||||
int uniqueId, const IDrmEngine::OnInfoListener* infoListener) {
|
||||
//LOGD("WVMDrmPlugin::onSetOnInfoListener : %d", uniqueId);
|
||||
mOnInfoListener = infoListener;
|
||||
return DRM_NO_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves necessary information for registration, unregistration or rights
|
||||
* acquisition information.
|
||||
*
|
||||
* @param[in] uniqueId Unique identifier for a session
|
||||
* @param[in] drmInfoRequest Request information to retrieve drmInfo
|
||||
* @return DrmInfo
|
||||
* instance as a result of processing given input
|
||||
*/
|
||||
DrmInfo* WVMDrmPlugin::onAcquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) {
|
||||
//LOGD("WVMDrmPlugin::onAcquireDrmInfo : %d", uniqueId);
|
||||
DrmInfo* drmInfo = NULL;
|
||||
|
||||
std::string assetPath;
|
||||
|
||||
if (NULL != drmInfoRequest) {
|
||||
switch(drmInfoRequest->getInfoType()) {
|
||||
case DrmInfoRequest::TYPE_RIGHTS_ACQUISITION_INFO: {
|
||||
|
||||
assetPath = drmInfoRequest->get(String8("WVAssetURIKey")).string();
|
||||
|
||||
WVCredentials credentials;
|
||||
|
||||
// creates a data store object per each portal
|
||||
credentials.portal = drmInfoRequest->get(String8("WVPortalKey")).string();
|
||||
if ( (assetPath.size() == 0) || (credentials.portal.size() == 0) ) {
|
||||
LOGE("onAcquireDrmInfo: Empty asset path or portal string, must specify both");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
std::string assetDbPath = drmInfoRequest->get(String8("WVAssetDBPathKey")).string();
|
||||
//LOGV("onAcquireDrmInfo: portal=%s, dsPath=%s", credentials.portal.c_str(), assetDbPath.c_str());
|
||||
|
||||
credentials.drmServerURL = drmInfoRequest->get(String8("WVDRMServerKey")).string();
|
||||
credentials.userData = drmInfoRequest->get(String8("WVCAUserDataKey")).string();
|
||||
credentials.deviceID = drmInfoRequest->get(String8("WVDeviceIDKey")).string();
|
||||
credentials.streamID = drmInfoRequest->get(String8("WVStreamIDKey")).string();
|
||||
|
||||
string systemIdStr = drmInfoRequest->get(String8("WVSystemIDKey")).string();
|
||||
string assetIdStr = drmInfoRequest->get(String8("WVAssetIDKey")).string();
|
||||
string keyIdStr = drmInfoRequest->get(String8("WVKeyIDKey")).string();
|
||||
|
||||
uint32_t systemId, assetId, keyId;
|
||||
|
||||
if (!mDrmPluginImpl->AcquireDrmInfo(assetPath, credentials, assetDbPath,
|
||||
systemIdStr, assetIdStr, keyIdStr,
|
||||
&systemId, &assetId, &keyId))
|
||||
return NULL;
|
||||
|
||||
|
||||
String8 dataString("dummy_acquistion_string");
|
||||
int length = dataString.length();
|
||||
char* data = NULL;
|
||||
data = new char[length];
|
||||
memcpy(data, dataString.string(), length);
|
||||
drmInfo = new DrmInfo(drmInfoRequest->getInfoType(),
|
||||
DrmBuffer(data, length), drmInfoRequest->getMimeType());
|
||||
|
||||
// Sets additional drmInfo attributes
|
||||
drmInfo->put(String8("WVAssetURIKey"), String8(assetPath.c_str()));
|
||||
drmInfo->put(String8("WVDRMServerKey"), String8(credentials.drmServerURL.c_str()));
|
||||
drmInfo->put(String8("WVAssetDbPathKey"), String8(assetDbPath.c_str()));
|
||||
drmInfo->put(String8("WVPortalKey"), String8(credentials.portal.c_str()));
|
||||
drmInfo->put(String8("WVCAUserDataKey"), String8(credentials.userData.c_str()));
|
||||
drmInfo->put(String8("WVDeviceIDKey"), String8(credentials.deviceID.c_str()));
|
||||
drmInfo->put(String8("WVStreamIDKey"), String8(credentials.streamID.c_str()));
|
||||
|
||||
char buffer[16];
|
||||
sprintf(buffer, "%lu", (unsigned long)systemId);
|
||||
drmInfo->put(String8("WVSystemIDKey"), String8(buffer));
|
||||
sprintf(buffer, "%lu", (unsigned long)assetId);
|
||||
drmInfo->put(String8("WVAssetIDKey"), String8(buffer));
|
||||
sprintf(buffer, "%lu", (unsigned long)keyId);
|
||||
drmInfo->put(String8("WVKeyIDKey"), String8(buffer));
|
||||
break;
|
||||
}
|
||||
case DrmInfoRequest::TYPE_REGISTRATION_INFO:
|
||||
case DrmInfoRequest::TYPE_UNREGISTRATION_INFO:
|
||||
case DrmInfoRequest::TYPE_RIGHTS_ACQUISITION_PROGRESS_INFO: {
|
||||
LOGE("onAcquireDrmInfo: Unsupported DrmInfoRequest type %d",
|
||||
drmInfoRequest->getInfoType());
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LOGE("onAcquireDrmInfo: Unknown info type %d", drmInfoRequest->getInfoType());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return drmInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes given drm information based on its type
|
||||
*
|
||||
* @param[in] uniqueId Unique identifier for a session
|
||||
* @param[in] drmInfo Information needs to be processed
|
||||
* @return DrmInfoStatus
|
||||
* instance as a result of processing given input
|
||||
*/
|
||||
DrmInfoStatus* WVMDrmPlugin::onProcessDrmInfo(int uniqueId, const DrmInfo* drmInfo) {
|
||||
//LOGD("WVMDrmPlugin::onProcessDrmInfo: %d", uniqueId);
|
||||
|
||||
int status = DrmInfoStatus::STATUS_ERROR;
|
||||
|
||||
if (NULL != drmInfo) {
|
||||
if (drmInfo->getInfoType() == DrmInfoRequest::TYPE_RIGHTS_ACQUISITION_INFO) {
|
||||
std::string assetPath = drmInfo->get(String8("WVAssetURIKey")).string();
|
||||
|
||||
if (mDrmPluginImpl->ProcessDrmInfo(assetPath))
|
||||
status = DrmInfoStatus::STATUS_OK;
|
||||
} else {
|
||||
LOGE("onProcessDrmInfo : drmInfo type %d not supported", drmInfo->getInfoType());
|
||||
}
|
||||
} else {
|
||||
LOGE("onProcessDrmInfo : drmInfo cannot be NULL");
|
||||
}
|
||||
|
||||
String8 licenseString("dummy_license_string");
|
||||
const int bufferSize = licenseString.size();
|
||||
char* data = NULL;
|
||||
data = new char[bufferSize];
|
||||
memcpy(data, licenseString.string(), bufferSize);
|
||||
const DrmBuffer* buffer = new DrmBuffer(data, bufferSize);
|
||||
DrmInfoStatus* drmInfoStatus =
|
||||
new DrmInfoStatus(status, drmInfo->getInfoType(), buffer, drmInfo->getMimeType());
|
||||
|
||||
return drmInfoStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get constraint information associated with input content
|
||||
*
|
||||
* @param[in] uniqueId Unique identifier for a session
|
||||
* @param[in] path Path of the protected content
|
||||
* @param[in] action Actions defined such as,
|
||||
* Action::DEFAULT, Action::PLAY, etc
|
||||
* @return DrmConstraints
|
||||
* key-value pairs of constraint are embedded in it
|
||||
* @note
|
||||
* In case of error, return NULL
|
||||
*/
|
||||
DrmConstraints* WVMDrmPlugin::onGetConstraints(int uniqueId, const String8* path, int action)
|
||||
{
|
||||
//LOGD("WVMDrmPlugin::onGetConstraints : %d", uniqueId);
|
||||
|
||||
if ( (Action::DEFAULT != action) && (Action::PLAY != action) ) {
|
||||
LOGE("onGetConstraints : action %d not supported", action);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t licenseDuration = 0;
|
||||
uint32_t timeSincePlayback = 0;
|
||||
uint32_t timeRemaining = 0;
|
||||
|
||||
std::string assetPath(path->string());
|
||||
if (!mDrmPluginImpl->GetConstraints(assetPath, &timeSincePlayback, &timeRemaining, &licenseDuration))
|
||||
return NULL;
|
||||
|
||||
DrmConstraints* drmConstraints = new DrmConstraints();
|
||||
char charValue[16]; // max uint32 = 0xffffffff + terminating char
|
||||
|
||||
memset(charValue, 0, 16);
|
||||
sprintf(charValue, "%lu", (unsigned long)timeSincePlayback);
|
||||
drmConstraints->put(&(DrmConstraints::LICENSE_START_TIME), charValue);
|
||||
|
||||
memset(charValue, 0, 16);
|
||||
sprintf(charValue, "%lu", (unsigned long)timeRemaining);
|
||||
drmConstraints->put(&(DrmConstraints::LICENSE_EXPIRY_TIME), charValue);
|
||||
|
||||
memset(charValue, 0, 16);
|
||||
sprintf(charValue, "%lu", (unsigned long)licenseDuration);
|
||||
drmConstraints->put(&(DrmConstraints::LICENSE_AVAILABLE_TIME), charValue);
|
||||
|
||||
return drmConstraints;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the information about the Drm Engine capabilities which includes
|
||||
* supported MimeTypes and file suffixes.
|
||||
*
|
||||
* @param[in] uniqueId Unique identifier for a session
|
||||
* @return DrmSupportInfo
|
||||
* instance which holds the capabilities of a plug-in
|
||||
*/
|
||||
DrmSupportInfo* WVMDrmPlugin::onGetSupportInfo(int uniqueId) {
|
||||
//LOGD("WVMDrmPlugin::onGetSupportInfo : %d", uniqueId);
|
||||
DrmSupportInfo* drmSupportInfo = new DrmSupportInfo();
|
||||
// Add mimetype's
|
||||
drmSupportInfo->addMimeType(String8("video/wvm"));
|
||||
// Add File Suffixes
|
||||
drmSupportInfo->addFileSuffix(String8(".wvm"));
|
||||
// Add plug-in description
|
||||
drmSupportInfo->setDescription(String8("Widevine DRM plug-in"));
|
||||
return drmSupportInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get meta data from protected content
|
||||
*
|
||||
* @param[in] uniqueId Unique identifier for a session
|
||||
* @param[in] path Path of the protected content
|
||||
*
|
||||
* @return DrmMetadata
|
||||
* key-value pairs of meta data; NULL if failed
|
||||
*/
|
||||
DrmMetadata* WVMDrmPlugin::onGetMetadata(int uniqueId, const String8* path) {
|
||||
//LOGD("WVDrmPlugin::onGetMetadata returns NULL\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save DRM rights to specified rights path
|
||||
* and make association with content path
|
||||
*
|
||||
* @param[in] uniqueId Unique identifier for a session
|
||||
* @param[in] drmRights DrmRights to be saved
|
||||
* @param[in] rightsPath File path where rights to be saved
|
||||
* @param[in] contentPath File path where content was saved
|
||||
* @return status_t
|
||||
* Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
|
||||
*/
|
||||
status_t WVMDrmPlugin::onSaveRights(int uniqueId, const DrmRights& drmRights,
|
||||
const String8& rightsPath, const String8& contentPath) {
|
||||
//LOGD("WVMDrmPlugin::onSaveRights : %d", uniqueId);
|
||||
return DRM_NO_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether the given content can be handled by this plugin or not
|
||||
*
|
||||
* @param[in] uniqueId Unique identifier for a session
|
||||
* @param[in] path Path the protected object
|
||||
* @return bool
|
||||
* Returns true if this plugin can handle , false in case of not able to handle
|
||||
*/
|
||||
bool WVMDrmPlugin::onCanHandle(int uniqueId, const String8& path) {
|
||||
//LOGD("WVMDrmPlugin::canHandle('%s') ", path.string());
|
||||
String8 extension = path.getPathExtension();
|
||||
extension.toLower();
|
||||
return (String8(".wvm") == extension);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the mime type embedded inside the original content
|
||||
*
|
||||
* @param[in] uniqueId Unique identifier for a session
|
||||
* @param[in] path Path of the protected content
|
||||
* @return String8
|
||||
* Returns mime-type of the original content, such as "video/mpeg"
|
||||
*/
|
||||
String8 WVMDrmPlugin::onGetOriginalMimeType(int uniqueId, const String8& path) {
|
||||
//LOGD("WVMDrmPlugin::onGetOriginalMimeType() : %d", uniqueId);
|
||||
return String8("video/wvm");
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the type of the protected object (content, rights, etc..)
|
||||
* using specified path or mimetype. At least one parameter should be non null
|
||||
* to retrieve DRM object type
|
||||
*
|
||||
* @param[in] uniqueId Unique identifier for a session
|
||||
* @param[in] path Path of the content or null.
|
||||
* @param[in] mimeType Mime type of the content or null.
|
||||
* @return type of the DRM content,
|
||||
* such as DrmObjectType::CONTENT, DrmObjectType::RIGHTS_OBJECT
|
||||
*/
|
||||
int WVMDrmPlugin::onGetDrmObjectType(
|
||||
int uniqueId, const String8& path, const String8& mimeType) {
|
||||
//LOGD("WVMDrmPlugin::onGetDrmObjectType() : %d", uniqueId);
|
||||
return DrmObjectType::UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the given content has valid rights or not
|
||||
*
|
||||
* @param[in] uniqueId Unique identifier for a session
|
||||
* @param[in] path Path of the protected content
|
||||
* @param[in] action Action to perform (Action::DEFAULT, Action::PLAY, etc)
|
||||
* @return the status of the rights for the protected content,
|
||||
* such as RightsStatus::RIGHTS_VALID, RightsStatus::RIGHTS_EXPIRED, etc.
|
||||
*/
|
||||
int WVMDrmPlugin::onCheckRightsStatus(int uniqueId, const String8& path, int action) {
|
||||
//LOGD("WVMDrmPlugin::onCheckRightsStatus() : %d", uniqueId);
|
||||
|
||||
if ( (Action::DEFAULT != action) && (Action::PLAY != action) ) {
|
||||
LOGE("onCheckRightsStatus : action %d not supported", action);
|
||||
return RightsStatus::RIGHTS_INVALID;
|
||||
}
|
||||
|
||||
std::string assetPath(path.string());
|
||||
int rightsStatus = mDrmPluginImpl->CheckRightsStatus(assetPath);
|
||||
|
||||
switch(rightsStatus) {
|
||||
case WVDRMPluginAPI::RIGHTS_INVALID:
|
||||
return RightsStatus::RIGHTS_INVALID;
|
||||
break;
|
||||
case WVDRMPluginAPI::RIGHTS_EXPIRED:
|
||||
return RightsStatus::RIGHTS_EXPIRED;
|
||||
break;
|
||||
case WVDRMPluginAPI::RIGHTS_VALID:
|
||||
return RightsStatus::RIGHTS_VALID;
|
||||
break;
|
||||
case WVDRMPluginAPI::RIGHTS_NOT_ACQUIRED:
|
||||
return RightsStatus::RIGHTS_NOT_ACQUIRED;
|
||||
break;
|
||||
}
|
||||
return RightsStatus::RIGHTS_INVALID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Consumes the rights for a content.
|
||||
* If the reserve parameter is true the rights is reserved until the same
|
||||
* application calls this api again with the reserve parameter set to false.
|
||||
*
|
||||
* @param[in] uniqueId Unique identifier for a session
|
||||
* @param[in] decryptHandle Handle for the decryption session
|
||||
* @param[in] action Action to perform. (Action::DEFAULT, Action::PLAY, etc)
|
||||
* @param[in] reserve True if the rights should be reserved.
|
||||
* @return status_t
|
||||
* Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
|
||||
*/
|
||||
status_t WVMDrmPlugin::onConsumeRights(int uniqueId, DecryptHandle* decryptHandle,
|
||||
int action, bool reserve) {
|
||||
//LOGD("WVMDrmPlugin::onConsumeRights() : %d", uniqueId);
|
||||
return DRM_NO_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Informs the DRM Engine about the playback actions performed on the DRM files.
|
||||
*
|
||||
* @param[in] uniqueId Unique identifier for a session
|
||||
* @param[in] decryptHandle Handle for the decryption session
|
||||
* @param[in] playbackStatus Playback action (Playback::START, Playback::STOP, Playback::PAUSE)
|
||||
* @param[in] position Position in the file (in milliseconds) where the start occurs.
|
||||
* Only valid together with Playback::START.
|
||||
* @return status_t
|
||||
* Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
|
||||
*/
|
||||
status_t WVMDrmPlugin::onSetPlaybackStatus(int uniqueId, DecryptHandle* decryptHandle,
|
||||
int playbackStatus, off64_t position) {
|
||||
//LOGD("WVMDrmPlugin::onSetPlaybackStatus");
|
||||
|
||||
int op;
|
||||
|
||||
switch(playbackStatus) {
|
||||
case Playback::START:
|
||||
op = WVDRMPluginAPI::PLAYBACK_START;
|
||||
break;
|
||||
case Playback::STOP:
|
||||
op = WVDRMPluginAPI::PLAYBACK_STOP;
|
||||
break;
|
||||
case Playback::PAUSE:
|
||||
op = WVDRMPluginAPI::PLAYBACK_PAUSE;
|
||||
break;
|
||||
default:
|
||||
op = WVDRMPluginAPI::PLAYBACK_INVALID;
|
||||
break;
|
||||
}
|
||||
|
||||
if (mDrmPluginImpl->SetPlaybackStatus(op, position))
|
||||
return DRM_NO_ERROR;
|
||||
|
||||
return DRM_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates whether an action on the DRM content is allowed or not.
|
||||
*
|
||||
* @param[in] uniqueId Unique identifier for a session
|
||||
* @param[in] path Path of the protected content
|
||||
* @param[in] action Action to validate (Action::PLAY, Action::TRANSFER, etc)
|
||||
* @param[in] description Detailed description of the action
|
||||
* @return true if the action is allowed.
|
||||
*/
|
||||
bool WVMDrmPlugin::onValidateAction(int uniqueId, const String8& path,
|
||||
int action, const ActionDescription& description) {
|
||||
//LOGD("WVMDrmPlugin::onValidateAction() : %d", uniqueId);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the rights associated with the given protected content
|
||||
*
|
||||
* @param[in] uniqueId Unique identifier for a session
|
||||
* @param[in] path Path of the protected content
|
||||
* @return status_t
|
||||
* Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
|
||||
*/
|
||||
status_t WVMDrmPlugin::onRemoveRights(int uniqueId, const String8& path) {
|
||||
//LOGD("WVMDrmPlugin::onRemoveRights() : %d", uniqueId);
|
||||
|
||||
std::string assetPath(path.string());
|
||||
if (mDrmPluginImpl->RemoveRights(assetPath))
|
||||
return DRM_NO_ERROR;
|
||||
|
||||
return DRM_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all the rights information of each plug-in associated with
|
||||
* DRM framework. Will be used in master reset
|
||||
*
|
||||
* @param[in] uniqueId Unique identifier for a session
|
||||
* @return status_t
|
||||
* Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
|
||||
*/
|
||||
status_t WVMDrmPlugin::onRemoveAllRights(int uniqueId) {
|
||||
//LOGD("WVMDrmPlugin::onRemoveAllRights() : %d", uniqueId);
|
||||
|
||||
if (mDrmPluginImpl->RemoveAllRights())
|
||||
return DRM_NO_ERROR;
|
||||
|
||||
return DRM_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the decrypt session to decrypt the given protected content
|
||||
*
|
||||
* @param[in] uniqueId Unique identifier for a session
|
||||
* @param[in] decryptHandle Handle for the current decryption session
|
||||
* @param[in] fd File descriptor of the protected content to be decrypted
|
||||
* @param[in] offset Start position of the content
|
||||
* @param[in] length The length of the protected content
|
||||
* @return
|
||||
* DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success
|
||||
*/
|
||||
status_t WVMDrmPlugin::onOpenDecryptSession(
|
||||
int uniqueId, DecryptHandle *decryptHandle, int fd, off64_t offset, off64_t length)
|
||||
{
|
||||
status_t result = DRM_ERROR_CANNOT_HANDLE;
|
||||
|
||||
//LOGD("onOpenDecryptSession: fd=%d, offset=%lld, length=%lld", fd, offset, length);
|
||||
|
||||
char buffer[64 * 1024];
|
||||
int dupfd = dup(fd);
|
||||
if (dupfd == -1)
|
||||
return result;
|
||||
|
||||
FILE *f = fdopen(dupfd, "rb");
|
||||
if (f) {
|
||||
fseek(f, 0, SEEK_SET);
|
||||
if (fread(buffer, 1, sizeof(buffer), f) != sizeof(buffer)) {
|
||||
fclose(f);
|
||||
return DRM_ERROR_CANNOT_HANDLE;
|
||||
}
|
||||
fclose(f);
|
||||
} else {
|
||||
close(dupfd);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (WV_IsWidevineMedia(buffer, sizeof(buffer))) {
|
||||
//LOGD("WVMDrmPlugin::onOpenDecryptSession - WV_IsWidevineMedia: true");
|
||||
decryptHandle->mimeType = String8("video/wvm");
|
||||
decryptHandle->decryptApiType = DecryptApiType::WV_BASED;
|
||||
decryptHandle->status = DRM_NO_ERROR;
|
||||
decryptHandle->decryptInfo = NULL;
|
||||
result = DRM_NO_ERROR;
|
||||
} else {
|
||||
//LOGD("WVMDrmPlugin::onOpenDecryptSession - not Widevine media");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the decrypt session to decrypt the given protected content
|
||||
*
|
||||
* @param[in] uniqueId Unique identifier for a session
|
||||
* @param[in] decryptHandle Handle for the current decryption session
|
||||
* @param[in] uri Path of the protected content to be decrypted
|
||||
* @return
|
||||
* DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success
|
||||
*/
|
||||
status_t WVMDrmPlugin::onOpenDecryptSession(
|
||||
int uniqueId, DecryptHandle* decryptHandle, const char* uri)
|
||||
{
|
||||
status_t result = DRM_ERROR_CANNOT_HANDLE;
|
||||
|
||||
if (!uri)
|
||||
return result;
|
||||
|
||||
size_t len = strlen(uri);
|
||||
|
||||
if ((len >= 4 && !strncmp(&uri[len - 4], ".wvm", 4)) ||
|
||||
(strstr(uri, ".wvm?") != NULL) ||
|
||||
(len >= 5 && !strncmp(&uri[len - 5], ".m3u8", 5)) ||
|
||||
(strstr(uri, ".m3u8?") != NULL))
|
||||
{
|
||||
//LOGD("WVMDrmPlugin::onOpenDecryptSession(uri) : %d - match", uniqueId);
|
||||
decryptHandle->mimeType = String8("video/wvm");
|
||||
decryptHandle->decryptApiType = DecryptApiType::WV_BASED;
|
||||
decryptHandle->status = DRM_NO_ERROR;
|
||||
decryptHandle->decryptInfo = NULL;
|
||||
|
||||
mDrmPluginImpl->OpenSession();
|
||||
result = DRM_NO_ERROR;
|
||||
} else {
|
||||
//LOGD("WVMDrmPlugin::onOpenDecryptSession(uri) - not Widevine media");
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Close the decrypt session for the given handle
|
||||
*
|
||||
* @param[in] uniqueId Unique identifier for a session
|
||||
* @param[in] decryptHandle Handle for the decryption session
|
||||
* @return status_t
|
||||
* Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
|
||||
*/
|
||||
status_t WVMDrmPlugin::onCloseDecryptSession(int uniqueId, DecryptHandle* decryptHandle) {
|
||||
//LOGD("WVMDrmPlugin::onCloseDecryptSession() : %d", uniqueId);
|
||||
if (NULL != decryptHandle) {
|
||||
if (NULL != decryptHandle->decryptInfo) {
|
||||
delete decryptHandle->decryptInfo; decryptHandle->decryptInfo = NULL;
|
||||
}
|
||||
delete decryptHandle; decryptHandle = NULL;
|
||||
}
|
||||
mDrmPluginImpl->CloseSession();
|
||||
return DRM_NO_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize decryption for the given unit of the protected content
|
||||
*
|
||||
* @param[in] uniqueId Unique identifier for a session
|
||||
* @param[in] decryptId Handle for the decryption session
|
||||
* @param[in] decryptUnitId ID Specifies decryption unit, such as track ID
|
||||
* @param[in] headerInfo Information for initializing decryption of this decrypUnit
|
||||
* @return status_t
|
||||
* Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
|
||||
*/
|
||||
status_t WVMDrmPlugin::onInitializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
|
||||
int decryptUnitId, const DrmBuffer* headerInfo) {
|
||||
//LOGD("WVMDrmPlugin::onInitializeDecryptUnit(): %d", uniqueId);
|
||||
if (!mDrmPluginImpl->Prepare(headerInfo->data, headerInfo->length))
|
||||
return DRM_ERROR_CANNOT_HANDLE;
|
||||
|
||||
return DRM_NO_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt the protected content buffers for the given unit
|
||||
* This method will be called any number of times, based on number of
|
||||
* encrypted streams received from application.
|
||||
*
|
||||
* @param[in] uniqueId Unique identifier for a session
|
||||
* @param[in] decryptId Handle for the decryption session
|
||||
* @param[in] decryptUnitId ID Specifies decryption unit, such as track ID
|
||||
* @param[in] encBuffer Encrypted data block
|
||||
* @param[out] decBuffer Decrypted data block
|
||||
* @param[in] IV Optional buffer
|
||||
* @return status_t
|
||||
* Returns the error code for this API
|
||||
* DRM_NO_ERROR for success, and one of DRM_ERROR_UNKNOWN, DRM_ERROR_LICENSE_EXPIRED
|
||||
* DRM_ERROR_SESSION_NOT_OPENED, DRM_ERROR_DECRYPT_UNIT_NOT_INITIALIZED,
|
||||
* DRM_ERROR_DECRYPT for failure.
|
||||
*/
|
||||
status_t WVMDrmPlugin::onDecrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
|
||||
const DrmBuffer* encBuffer, DrmBuffer** decBuffer,
|
||||
DrmBuffer *ivBuffer)
|
||||
{
|
||||
//LOGD("WVMDrmPlugin::onDecrypt\n");
|
||||
#define AES_BLOCK_SIZE 16
|
||||
char iv[AES_BLOCK_SIZE];
|
||||
memcpy(iv, ivBuffer->data, sizeof(iv));
|
||||
|
||||
if (*decBuffer == NULL)
|
||||
return DRM_ERROR_DECRYPT;
|
||||
|
||||
(*decBuffer)->length = encBuffer->length;
|
||||
|
||||
if (!mDrmPluginImpl->Operate(encBuffer->data, (*decBuffer)->data, encBuffer->length, iv)) {
|
||||
(*decBuffer)->length = 0;
|
||||
usleep(1000000); // prevent spinning
|
||||
return DRM_ERROR_LICENSE_EXPIRED;
|
||||
}
|
||||
|
||||
return DRM_NO_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finalize decryption for the given unit of the protected content
|
||||
*
|
||||
* @param[in] uniqueId Unique identifier for a session
|
||||
* @param[in] decryptHandle Handle for the decryption session
|
||||
* @param[in] decryptUnitId ID Specifies decryption unit, such as track ID
|
||||
* @return status_t
|
||||
* Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
|
||||
*/
|
||||
status_t WVMDrmPlugin::onFinalizeDecryptUnit(
|
||||
int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) {
|
||||
//LOGD("WVMDrmPlugin::onFinalizeDecryptUnit() : %d", uniqueId);
|
||||
return DRM_NO_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* The following methods are not required for the Widevine DRM plugin
|
||||
*/
|
||||
ssize_t WVMDrmPlugin::onPread(int uniqueId, DecryptHandle* decryptHandle,
|
||||
void* buffer, ssize_t numBytes, off64_t offset) {
|
||||
return DRM_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
status_t WVMDrmPlugin::onOpenConvertSession(int uniqueId, int convertId) {
|
||||
return DRM_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
DrmConvertedStatus* WVMDrmPlugin::onConvertData(
|
||||
int uniqueId, int convertId, const DrmBuffer* inputData) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DrmConvertedStatus* WVMDrmPlugin::onCloseConvertSession(int uniqueId, int convertId) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
25
proprietary/drmwvmplugin/src/WVMLogging.cpp
Normal file
25
proprietary/drmwvmplugin/src/WVMLogging.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#define LOG_TAG "WVMLogging"
|
||||
#include <utils/Log.h>
|
||||
#include "WVMLogging.h"
|
||||
|
||||
// Connect Widevine debug logging into Android logging
|
||||
|
||||
void android_printbuf(const char *buf)
|
||||
{
|
||||
LOGD("%s", buf);
|
||||
}
|
||||
32
proprietary/drmwvmplugin/test/Android.mk
Normal file
32
proprietary/drmwvmplugin/test/Android.mk
Normal file
@@ -0,0 +1,32 @@
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES:= \
|
||||
TestPlugin.cpp \
|
||||
../src/WVMLogging.cpp
|
||||
|
||||
LOCAL_C_INCLUDES+= \
|
||||
bionic \
|
||||
vendor/widevine/proprietary/include \
|
||||
external/stlport/stlport \
|
||||
frameworks/base/drm/libdrmframework/include \
|
||||
frameworks/base/drm/libdrmframework/plugins/common/include \
|
||||
frameworks/base/drm/libdrmframework/plugins/widevine/include
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libstlport \
|
||||
libwvdrm \
|
||||
liblog \
|
||||
libutils \
|
||||
libz \
|
||||
libdl
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := \
|
||||
libdrmframeworkcommon
|
||||
|
||||
LOCAL_MODULE:=test-wvdrmplugin
|
||||
|
||||
LOCAL_MODULE_TAGS := tests
|
||||
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
237
proprietary/drmwvmplugin/test/TestPlugin.cpp
Normal file
237
proprietary/drmwvmplugin/test/TestPlugin.cpp
Normal file
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "WVMDrmPlugin.h"
|
||||
#include "drm/DrmInfoRequest.h"
|
||||
#include "drm/DrmInfoStatus.h"
|
||||
#include "drm/DrmConstraints.h"
|
||||
#include "drm/DrmInfo.h"
|
||||
|
||||
using namespace android;
|
||||
using namespace std;
|
||||
|
||||
class WVMDrmPluginTest
|
||||
{
|
||||
public:
|
||||
WVMDrmPluginTest() {}
|
||||
~WVMDrmPluginTest() {}
|
||||
|
||||
void TestAsset(IDrmEngine *plugin, String8 &url);
|
||||
|
||||
void TestRemoveAllRights(IDrmEngine *plugin);
|
||||
void TestAcquireRights(IDrmEngine *plugin, String8 &url);
|
||||
void TestCheckRightsNotAcquired(IDrmEngine *plugin, String8 &url);
|
||||
void TestCheckValidRights(IDrmEngine *plugin, String8 &url);
|
||||
void TestGetConstraints(IDrmEngine *plugin, String8 &url);
|
||||
void TestRemoveRights(IDrmEngine *plugin, String8 &url);
|
||||
|
||||
// Tests
|
||||
void Run();
|
||||
};
|
||||
|
||||
void WVMDrmPluginTest::Run()
|
||||
{
|
||||
cout << "WVDrmPluginTest::Run" << endl;
|
||||
const char *path = "/system/lib/drm/libdrmwvmplugin.so";
|
||||
void *handle = dlopen(path, RTLD_NOW);
|
||||
if (handle == NULL) {
|
||||
fprintf(stderr, "Can't open plugin: %s\n", path);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
typedef IDrmEngine *(*create_t)();
|
||||
create_t creator = (create_t)dlsym(handle, "create");
|
||||
if (!creator) {
|
||||
fprintf(stderr, "Can't find create method\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
typedef void (*destroy_t)(IDrmEngine *);
|
||||
destroy_t destroyer = (destroy_t)dlsym(handle, "destroy");
|
||||
if (!destroyer) {
|
||||
fprintf(stderr, "Can't find destroy method\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// Basic test - see if we can instantiate the object and call a method
|
||||
IDrmEngine *plugin = (*creator)();
|
||||
if (plugin->initialize(0) != DRM_NO_ERROR) {
|
||||
fprintf(stderr, "onInitialize failed!\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// Remote asset
|
||||
String8 url;
|
||||
url = String8("http://seawwws001.cdn.shibboleth.tv/videos/qa/adventures_d_ch_444169.wvm");
|
||||
TestAsset(plugin, url);
|
||||
|
||||
// Local asset
|
||||
url = String8("file:///sdcard/Widevine/trailers_d_ch_444169.wvm");
|
||||
TestAsset(plugin, url);
|
||||
|
||||
// Remote asset with query parameters
|
||||
url = String8("http://seawwws001.cdn.shibboleth.tv/videos/qa/adventures_d_ch_444169.wvm?a=b");
|
||||
TestAsset(plugin, url);
|
||||
|
||||
// Shut down and clean up
|
||||
if (plugin->terminate(0) != DRM_NO_ERROR) {
|
||||
fprintf(stderr, "onTerminate failed!\n");
|
||||
exit(-1);
|
||||
}
|
||||
destroyer(plugin);
|
||||
dlclose(handle);
|
||||
printf("Test successful!\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void WVMDrmPluginTest::TestAcquireRights(IDrmEngine *plugin, String8 &url)
|
||||
{
|
||||
cout << "WVDrmPluginTest::TestAcquireRights url=" << url << endl;
|
||||
|
||||
String8 mimeType("video/wvm");
|
||||
DrmInfoRequest rightsAcquisitionInfo(DrmInfoRequest::TYPE_RIGHTS_ACQUISITION_INFO, mimeType);
|
||||
rightsAcquisitionInfo.put(String8("WVDRMServerKey"), String8("http://wstfcps005.shibboleth.tv/widevine/cypherpc/cgi-bin/GetEMMs.cgi"));
|
||||
rightsAcquisitionInfo.put(String8("WVAssetURIKey"), url);
|
||||
rightsAcquisitionInfo.put(String8("WVDeviceIDKey"), String8("device1234"));
|
||||
rightsAcquisitionInfo.put(String8("WVPortalKey"), String8("YouTube"));
|
||||
|
||||
DrmInfo *info = plugin->acquireDrmInfo(0, &rightsAcquisitionInfo);
|
||||
if (info == NULL) {
|
||||
fprintf(stderr, "acquireDrmInfo failed!\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
DrmInfoStatus *status = plugin->processDrmInfo(0, info);
|
||||
if (status == NULL || status->statusCode != DrmInfoStatus::STATUS_OK) {
|
||||
fprintf(stderr, "processDrmInfo failed!\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
delete status;
|
||||
delete info;
|
||||
}
|
||||
|
||||
void WVMDrmPluginTest::TestCheckRightsNotAcquired(IDrmEngine *plugin, String8 &url)
|
||||
{
|
||||
cout << "WVDrmPluginTest::TestCheckRightsNotAcquired url=" << url << endl;
|
||||
|
||||
if (plugin->checkRightsStatus(0, url, Action::DEFAULT) != RightsStatus::RIGHTS_NOT_ACQUIRED) {
|
||||
fprintf(stderr, "checkRightsNotAcquired default action failed!\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (plugin->checkRightsStatus(0, url, Action::PLAY) != RightsStatus::RIGHTS_NOT_ACQUIRED) {
|
||||
fprintf(stderr, "checkRightsNotAcquired failed!\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
void WVMDrmPluginTest::TestCheckValidRights(IDrmEngine *plugin, String8 &url)
|
||||
{
|
||||
cout << "WVDrmPluginTest::TestCheckValidRights url=" << url << endl;
|
||||
|
||||
if (plugin->checkRightsStatus(0, url, Action::DEFAULT) != RightsStatus::RIGHTS_VALID) {
|
||||
fprintf(stderr, "checkValidRights default action failed!\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (plugin->checkRightsStatus(0, url, Action::PLAY) != RightsStatus::RIGHTS_VALID) {
|
||||
fprintf(stderr, "checkValidRights play action failed!\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
void WVMDrmPluginTest::TestGetConstraints(IDrmEngine *plugin, String8 &url)
|
||||
{
|
||||
cout << "WVDrmPluginTest::TestGetConstraints url=" << url << endl;
|
||||
|
||||
DrmConstraints *constraints;
|
||||
constraints = plugin->getConstraints(0, &url, Action::PLAY);
|
||||
if (constraints == NULL) {
|
||||
fprintf(stderr, "getConstraints returned NULL constraints!\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (constraints->getCount() != 3) {
|
||||
fprintf(stderr, "getConstraints returned unexpected count!\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (constraints->get(DrmConstraints::LICENSE_START_TIME) == "") {
|
||||
fprintf(stderr, "getConstraints returned unexpected count!\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (constraints->get(DrmConstraints::LICENSE_AVAILABLE_TIME) == "") {
|
||||
fprintf(stderr, "getConstraints returned unexpected count!\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (constraints->get(DrmConstraints::LICENSE_EXPIRY_TIME) == "") {
|
||||
fprintf(stderr, "getConstraints returned unexpected count!\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
delete constraints;
|
||||
}
|
||||
|
||||
void WVMDrmPluginTest::TestRemoveRights(IDrmEngine *plugin, String8 &url)
|
||||
{
|
||||
cout << "WVDrmPluginTest::TestRemoveRights url=" << url << endl;
|
||||
|
||||
status_t status = plugin->removeRights(0, url);
|
||||
if (status != DRM_NO_ERROR) {
|
||||
fprintf(stderr, "removeRights returned error: %d!\n", (int)status);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
void WVMDrmPluginTest::TestRemoveAllRights(IDrmEngine *plugin)
|
||||
{
|
||||
cout << "WVDrmPluginTest::TestRemoveAllRights" << endl;
|
||||
|
||||
status_t status = plugin->removeAllRights(0);
|
||||
if (status != DRM_NO_ERROR) {
|
||||
fprintf(stderr, "removeAllRights returned error: %d!\n", (int)status);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
void WVMDrmPluginTest::TestAsset(IDrmEngine *plugin, String8 &url)
|
||||
{
|
||||
cout << "WVDrmPluginTest::TestAsset url=" << url << endl;
|
||||
|
||||
TestAcquireRights(plugin, url);
|
||||
TestCheckValidRights(plugin, url);
|
||||
TestGetConstraints(plugin, url);
|
||||
TestRemoveRights(plugin, url);
|
||||
TestCheckRightsNotAcquired(plugin, url);
|
||||
TestAcquireRights(plugin, url);
|
||||
TestRemoveAllRights(plugin);
|
||||
TestCheckRightsNotAcquired(plugin, url);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
// turn off some noisy printing in WVStreamControl
|
||||
setenv("WV_SILENT", "true", 1);
|
||||
WVMDrmPluginTest test;
|
||||
test.Run();
|
||||
}
|
||||
3
proprietary/drmwvmplugin/test/kill.sh
Executable file
3
proprietary/drmwvmplugin/test/kill.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
PID=`adb shell ps | grep test-wvdrmplugin | awk '{print $2}'`
|
||||
adb shell kill -9 $PID
|
||||
1
proprietary/streamcontrol/Android.mk
Normal file
1
proprietary/streamcontrol/Android.mk
Normal file
@@ -0,0 +1 @@
|
||||
include $(call all-subdir-makefiles)
|
||||
@@ -8,7 +8,7 @@ LOCAL_C_INCLUDES+= \
|
||||
bionic \
|
||||
vendor/widevine/proprietary/include \
|
||||
external/stlport/stlport \
|
||||
frameworks/base/media/libwvm/include
|
||||
vendor/widevine/proprietary/streamcontrol/include
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libstlport \
|
||||
38
proprietary/wvm/Android.mk
Normal file
38
proprietary/wvm/Android.mk
Normal file
@@ -0,0 +1,38 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
ifeq ($(TARGET_ARCH),arm)
|
||||
|
||||
LOCAL_SRC_FILES:= \
|
||||
WVMLogging.cpp \
|
||||
WVMExtractorImpl.cpp \
|
||||
WVMFileSource.cpp \
|
||||
WVMMediaSource.cpp
|
||||
|
||||
LOCAL_C_INCLUDES:= \
|
||||
bionic \
|
||||
bionic/libstdc++ \
|
||||
external/stlport/stlport \
|
||||
vendor/widevine/proprietary/streamcontrol/include \
|
||||
vendor/widevine/proprietary/wvm/include
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libstlport \
|
||||
libstagefright \
|
||||
libWVStreamControlAPI \
|
||||
libdrmframework \
|
||||
libcutils \
|
||||
liblog \
|
||||
libutils \
|
||||
libz
|
||||
|
||||
LOCAL_MODULE := libwvm
|
||||
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
|
||||
LOCAL_PRELINK_MODULE := false
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
endif
|
||||
419
proprietary/wvm/WVMExtractorImpl.cpp
Normal file
419
proprietary/wvm/WVMExtractorImpl.cpp
Normal file
@@ -0,0 +1,419 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "WVMExtractorImpl"
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include "WVMExtractorImpl.h"
|
||||
#include "WVMMediaSource.h"
|
||||
#include "WVMFileSource.h"
|
||||
#include "WVMLogging.h"
|
||||
#include "WVStreamControlAPI.h"
|
||||
#include "media/stagefright/MediaErrors.h"
|
||||
#include "media/stagefright/MediaDefs.h"
|
||||
#include "drm/DrmManagerClient.h"
|
||||
#include "AndroidHooks.h"
|
||||
|
||||
#define AES_BLOCK_SIZE 16
|
||||
|
||||
|
||||
using namespace android;
|
||||
|
||||
static DecryptHandle *sDecryptHandle;
|
||||
static DrmManagerClient *sDrmManagerClient;
|
||||
|
||||
|
||||
// Android integration callout hooks
|
||||
static void HandleEcmCallout(char *ecm, unsigned long size)
|
||||
{
|
||||
DrmBuffer buf(ecm, size);
|
||||
if (sDrmManagerClient != NULL) {
|
||||
sDrmManagerClient->initializeDecryptUnit(sDecryptHandle, 0, &buf);
|
||||
}
|
||||
}
|
||||
|
||||
static int HandleDecryptCallout(char *in, char *out, int length, char *iv)
|
||||
{
|
||||
int status = -1;
|
||||
|
||||
if (sDrmManagerClient != NULL) {
|
||||
DrmBuffer encryptedDrmBuffer(in, length);
|
||||
DrmBuffer ivBuffer(iv, length);
|
||||
|
||||
DrmBuffer decryptedDrmBuffer(out, length);
|
||||
DrmBuffer *decryptedDrmBufferPtr = &decryptedDrmBuffer;
|
||||
|
||||
char ivout[AES_BLOCK_SIZE];
|
||||
if (in && length)
|
||||
memcpy(ivout, in + length - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
|
||||
|
||||
status = sDrmManagerClient->decrypt(sDecryptHandle, 0,
|
||||
&encryptedDrmBuffer, &decryptedDrmBufferPtr,
|
||||
&ivBuffer);
|
||||
|
||||
if (iv)
|
||||
memcpy(iv, ivout, AES_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
namespace android {
|
||||
|
||||
// DLL entry - construct an extractor and return it
|
||||
MediaExtractor *GetInstance(sp<DataSource> dataSource) {
|
||||
return new WVMExtractorImpl(dataSource);
|
||||
}
|
||||
|
||||
WVMExtractorImpl::WVMExtractorImpl(sp<DataSource> dataSource)
|
||||
: mFileMetaData(new MetaData()),
|
||||
mDataSource(dataSource),
|
||||
mHaveMetaData(false),
|
||||
mSession(NULL),
|
||||
mSetupStatus(OK)
|
||||
{
|
||||
dataSource->getDrmInfo(&sDecryptHandle, &sDrmManagerClient);
|
||||
|
||||
// Set up callouts
|
||||
AndroidSetLogCallout(android_printbuf);
|
||||
AndroidSetEcmCallout(HandleEcmCallout);
|
||||
AndroidSetDecryptCallout(HandleDecryptCallout);
|
||||
|
||||
if (sDecryptHandle != NULL) {
|
||||
if (sDecryptHandle->status != RightsStatus::RIGHTS_VALID) {
|
||||
mSetupStatus = ERROR_NO_LICENSE;
|
||||
}
|
||||
} else
|
||||
mSetupStatus = ERROR_NO_LICENSE;
|
||||
|
||||
WVCredentials credentials;
|
||||
|
||||
WVStatus result = WV_Initialize(NULL);
|
||||
if (result != WV_Status_OK) {
|
||||
LOGE("WV_Initialize returned status %d\n", result);
|
||||
mSetupStatus = ERROR_IO;
|
||||
} else {
|
||||
// Enable for debugging HTTP messages
|
||||
// WV_SetLogging(WV_Logging_HTTP);
|
||||
|
||||
if (dataSource->getUri().size() == 0) {
|
||||
// No URI supplied, pull data from the data source
|
||||
mFileSource = new WVMFileSource(dataSource);
|
||||
result = WV_Setup(mSession, mFileSource.get(),
|
||||
"RAW/RAW/RAW;destination=getdata", credentials,
|
||||
WV_OutputFormat_ES, kStreamCacheSize);
|
||||
} else {
|
||||
// Use the URI
|
||||
result = WV_Setup(mSession, dataSource->getUri().string(),
|
||||
"RAW/RAW/RAW;destination=getdata", credentials,
|
||||
WV_OutputFormat_ES, kStreamCacheSize);
|
||||
}
|
||||
if (result != WV_Status_OK) {
|
||||
LOGE("WV_Setup returned status %d in WVMMediaSource::start\n", result);
|
||||
mSetupStatus = ERROR_IO;
|
||||
}
|
||||
}
|
||||
|
||||
WV_SetWarningToErrorMS(5000);
|
||||
}
|
||||
|
||||
WVMExtractorImpl::~WVMExtractorImpl() {
|
||||
}
|
||||
|
||||
//
|
||||
// Configure metadata for video and audio sources
|
||||
//
|
||||
status_t WVMExtractorImpl::readMetaData()
|
||||
{
|
||||
if (mHaveMetaData)
|
||||
return OK;
|
||||
|
||||
if (mSetupStatus != OK)
|
||||
return mSetupStatus;
|
||||
|
||||
// Get Video Configuration
|
||||
WVVideoType videoType;
|
||||
unsigned short videoStreamID;
|
||||
unsigned short videoProfile;
|
||||
unsigned short level;
|
||||
unsigned short width, height;
|
||||
float aspect, frameRate;
|
||||
unsigned long bitRate;
|
||||
|
||||
WVStatus result = WV_Info_GetVideoConfiguration(mSession, &videoType, &videoStreamID,
|
||||
&videoProfile, &level, &width, &height,
|
||||
&aspect, &frameRate, &bitRate);
|
||||
if (result != WV_Status_OK)
|
||||
return ERROR_MALFORMED;
|
||||
|
||||
// Get Audio Configuration
|
||||
WVAudioType audioType;
|
||||
unsigned short audioStreamID;
|
||||
unsigned short audioProfile;
|
||||
unsigned short numChannels;
|
||||
unsigned long sampleRate;
|
||||
|
||||
result = WV_Info_GetAudioConfiguration(mSession, &audioType, &audioStreamID, &audioProfile,
|
||||
&numChannels, &sampleRate, &bitRate);
|
||||
if (result != WV_Status_OK)
|
||||
return ERROR_MALFORMED;
|
||||
|
||||
std::string durationString = WV_Info_GetDuration(mSession, "sec");
|
||||
if (durationString == "") {
|
||||
return ERROR_MALFORMED;
|
||||
}
|
||||
|
||||
int64_t duration = (int64_t)(strtod(durationString.c_str(), NULL) * 1000000);
|
||||
|
||||
sp<MetaData> audioMetaData = new MetaData();
|
||||
sp<MetaData> videoMetaData = new MetaData();
|
||||
|
||||
audioMetaData->setInt64(kKeyDuration, duration);
|
||||
videoMetaData->setInt64(kKeyDuration, duration);
|
||||
|
||||
switch(videoType) {
|
||||
case WV_VideoType_H264:
|
||||
videoMetaData->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
|
||||
break;
|
||||
default:
|
||||
LOGE("Invalid WV video type %d, expected H264C\n", audioType);
|
||||
break;
|
||||
}
|
||||
|
||||
switch(audioType) {
|
||||
case WV_AudioType_AAC:
|
||||
audioMetaData->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
|
||||
break;
|
||||
default:
|
||||
LOGE("Invalid WV audio type %d, expected AAC\n", audioType);
|
||||
break;
|
||||
}
|
||||
|
||||
audioMetaData->setInt32(kKeyTrackID, audioStreamID);
|
||||
videoMetaData->setInt32(kKeyTrackID, videoStreamID);
|
||||
|
||||
audioMetaData->setInt32(kKeyChannelCount, numChannels);
|
||||
audioMetaData->setInt32(kKeySampleRate, sampleRate);
|
||||
|
||||
videoMetaData->setInt32(kKeyWidth, width);
|
||||
videoMetaData->setInt32(kKeyHeight, height);
|
||||
|
||||
status_t status;
|
||||
|
||||
status = readAVCCMetaData(videoMetaData);
|
||||
if (status != OK)
|
||||
return status;
|
||||
|
||||
status = readESDSMetaData(audioMetaData);
|
||||
if (status != OK)
|
||||
return status;
|
||||
|
||||
mAudioSource = new WVMMediaSource(mSession, WV_EsSelector_Audio, audioMetaData);
|
||||
mVideoSource = new WVMMediaSource(mSession, WV_EsSelector_Video, videoMetaData);
|
||||
|
||||
// Since the WVExtractor goes away soon after this, we delegate ownership of some resources
|
||||
// to the constructed media source
|
||||
if (mFileSource.get())
|
||||
mVideoSource->delegateFileSource(mFileSource);
|
||||
|
||||
mVideoSource->delegateDataSource(mDataSource);
|
||||
|
||||
mFileMetaData->setCString(kKeyMIMEType, "video/mp4");
|
||||
|
||||
mHaveMetaData = true;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
status_t WVMExtractorImpl::readAVCCMetaData(sp<MetaData> videoMetaData)
|
||||
{
|
||||
WVStatus result;
|
||||
|
||||
const unsigned char *config;
|
||||
unsigned long size;
|
||||
int limit = 50;
|
||||
do {
|
||||
size_t bytesRead;
|
||||
bool auStart;
|
||||
unsigned long long dts, pts;
|
||||
unsigned char buf[1];
|
||||
size_t bufSize = 0;
|
||||
|
||||
//
|
||||
// In order to get the codec config data, we need to have the WVMK
|
||||
// pull some video data. But we can't use it yet, so just request 0 bytes.
|
||||
//
|
||||
(void)WV_GetEsData(mSession, WV_EsSelector_Video, buf, bufSize,
|
||||
bytesRead, auStart, dts, pts);
|
||||
|
||||
result = WV_Info_GetCodecConfig(mSession, WV_CodecConfigType_AVCC, config, size);
|
||||
if (result != WV_Status_OK)
|
||||
usleep(100);
|
||||
} while (result == WV_Status_Warning_Not_Available && limit-- > 0);
|
||||
|
||||
if (result != WV_Status_OK) {
|
||||
LOGE("WV_Info_GetCodecConfig AVCC returned error %d\n", result);
|
||||
return ERROR_IO;
|
||||
}
|
||||
|
||||
#if 0
|
||||
char *filename = "/data/wvm/avcc";
|
||||
FILE *f = fopen(filename, "w");
|
||||
if (!f)
|
||||
LOGD("Failed to open %s", filename);
|
||||
else {
|
||||
fwrite(config, size, 1, f);
|
||||
fclose(f);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
unsigned char mp4_force[] =
|
||||
{ 0x01, 0x42, 0x00, 0x1e, 0xff, 0xe1, 0x00, 0x1b, 0x67, 0x42, 0x80, 0x1e, 0x96, 0x52, 0x01, 0x40,
|
||||
0x5f, 0xf3, 0x60, 0x2a, 0x10, 0x00, 0x00, 0x03, 0x00, 0x10, 0x00, 0x00, 0x03, 0x03, 0x09, 0xda,
|
||||
0x14, 0x2a, 0x48, 0x01, 0x00, 0x04, 0x68, 0xcb, 0x8d, 0x48 } ;
|
||||
unsigned char wvm_force[] =
|
||||
{ 0x01, 0x42, 0x80, 0x1e, 0xff, 0xe1, 0x00, 0x1c, 0x67, 0x42, 0x80, 0x1e, 0x96, 0x52, 0x01, 0x40,
|
||||
0x5f, 0xf3, 0x60, 0x2a, 0x10, 0x00, 0x00, 0x03, 0x00, 0x10, 0x00, 0x00, 0x03, 0x03, 0x09, 0xda,
|
||||
0x14, 0x2a, 0x48, 0x00, 0x01, 0x00, 0x05, 0x68, 0xcb, 0x8d, 0x48, 0x00 } ;
|
||||
unsigned char wvm_force_no_zero[] =
|
||||
{ 0x01, 0x42, 0x80, 0x1e, 0xff, 0xe1, 0x00, 0x1b, 0x67, 0x42, 0x80, 0x1e, 0x96, 0x52, 0x01, 0x40,
|
||||
0x5f, 0xf3, 0x60, 0x2a, 0x10, 0x00, 0x00, 0x03, 0x00, 0x10, 0x00, 0x00, 0x03, 0x03, 0x09, 0xda,
|
||||
0x14, 0x2a, 0x48, 0x01, 0x00, 0x04, 0x68, 0xcb, 0x8d, 0x48 } ;
|
||||
unsigned char wvm_force_modprof[] =
|
||||
{ 0x01, 0x42, 0x00, 0x1e, 0xff, 0xe1, 0x00, 0x1c, 0x67, 0x42, 0x80, 0x1e, 0x96, 0x52, 0x01, 0x40,
|
||||
0x5f, 0xf3, 0x60, 0x2a, 0x10, 0x00, 0x00, 0x03, 0x00, 0x10, 0x00, 0x00, 0x03, 0x03, 0x09, 0xda,
|
||||
0x14, 0x2a, 0x48, 0x00, 0x01, 0x00, 0x05, 0x68, 0xcb, 0x8d, 0x48, 0x00 } ;
|
||||
|
||||
videoMetaData->setData(kKeyAVCC, kTypeAVCC, wvm_force_no_zero, sizeof(wvm_force_no_zero));
|
||||
#else
|
||||
videoMetaData->setData(kKeyAVCC, kTypeAVCC, config, size);
|
||||
#endif
|
||||
return OK;
|
||||
}
|
||||
|
||||
status_t WVMExtractorImpl::readESDSMetaData(sp<MetaData> audioMetaData)
|
||||
{
|
||||
WVStatus result;
|
||||
|
||||
const unsigned char *config;
|
||||
unsigned long size;
|
||||
int limit = 50;
|
||||
do {
|
||||
size_t bytesRead;
|
||||
bool auStart;
|
||||
unsigned long long dts, pts;
|
||||
unsigned char buf[1];
|
||||
size_t bufSize = 0;
|
||||
|
||||
//
|
||||
// In order to get the codec config data, we need to have the WVMK
|
||||
// pull some audio data. But we can't use it yet, so just request 0 bytes.
|
||||
//
|
||||
(void)WV_GetEsData(mSession, WV_EsSelector_Audio, buf, bufSize,
|
||||
bytesRead, auStart, dts, pts);
|
||||
|
||||
result = WV_Info_GetCodecConfig(mSession, WV_CodecConfigType_ESDS, config, size);
|
||||
if (result != WV_Status_OK)
|
||||
usleep(100);
|
||||
} while (result == WV_Status_Warning_Not_Available && limit-- > 0);
|
||||
|
||||
if (result != WV_Status_OK) {
|
||||
LOGE("WV_Info_GetCodecConfig ESDS returned error %d\n", result);
|
||||
return ERROR_IO;
|
||||
}
|
||||
|
||||
#if 0
|
||||
char *filename = "/data/wvm/esds";
|
||||
FILE *f = fopen(filename, "w");
|
||||
if (!f)
|
||||
LOGD("Failed to open %s", filename);
|
||||
else {
|
||||
fwrite(config, size, 1, f);
|
||||
fclose(f);
|
||||
}
|
||||
#endif
|
||||
audioMetaData->setData(kKeyESDS, kTypeESDS, config, size);
|
||||
return OK;
|
||||
}
|
||||
|
||||
size_t WVMExtractorImpl::countTracks() {
|
||||
status_t err;
|
||||
if ((err = readMetaData()) != OK) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 2; // 1 audio + 1 video
|
||||
}
|
||||
|
||||
sp<MediaSource> WVMExtractorImpl::getTrack(size_t index)
|
||||
{
|
||||
status_t err;
|
||||
if ((err = readMetaData()) != OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sp<MediaSource> result;
|
||||
|
||||
switch(index) {
|
||||
case 0:
|
||||
result = mVideoSource;
|
||||
break;
|
||||
case 1:
|
||||
result = mAudioSource;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
sp<MetaData> WVMExtractorImpl::getTrackMetaData(size_t index, uint32_t flags)
|
||||
{
|
||||
status_t err;
|
||||
if ((err = readMetaData()) != OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sp<MetaData> result;
|
||||
switch(index) {
|
||||
case 0:
|
||||
if (mVideoSource != NULL)
|
||||
result = mVideoSource->getFormat();
|
||||
break;
|
||||
case 1:
|
||||
if (mAudioSource != NULL)
|
||||
result = mAudioSource->getFormat();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
sp<MetaData> WVMExtractorImpl::getMetaData() {
|
||||
status_t err;
|
||||
if ((err = readMetaData()) != OK) {
|
||||
return new MetaData;
|
||||
}
|
||||
|
||||
return mFileMetaData;
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
|
||||
74
proprietary/wvm/WVMFileSource.cpp
Normal file
74
proprietary/wvm/WVMFileSource.cpp
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "WVMFileSource"
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include "WVMFileSource.h"
|
||||
#include "media/stagefright/MediaErrors.h"
|
||||
#include "media/stagefright/MediaDefs.h"
|
||||
#include "media/stagefright/MediaDebug.h"
|
||||
|
||||
namespace android {
|
||||
|
||||
|
||||
WVMFileSource::WVMFileSource(sp<DataSource> &dataSource)
|
||||
: mDataSource(dataSource),
|
||||
mOffset(0)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned long long WVMFileSource::GetSize()
|
||||
{
|
||||
off64_t size;
|
||||
mDataSource->getSize(&size);
|
||||
return size;
|
||||
}
|
||||
|
||||
unsigned long long WVMFileSource::GetOffset()
|
||||
{
|
||||
return mOffset;
|
||||
}
|
||||
|
||||
void WVMFileSource::Seek(unsigned long long offset)
|
||||
{
|
||||
mOffset = offset;
|
||||
}
|
||||
|
||||
size_t WVMFileSource::Read(size_t amount, unsigned char *buffer)
|
||||
{
|
||||
size_t result = mDataSource->readAt(mOffset, buffer, amount);
|
||||
|
||||
#if 0
|
||||
// debug code - log packets to files
|
||||
char filename[32];
|
||||
static int counter = 0;
|
||||
sprintf(filename, "/data/wv/buf%d", counter++);
|
||||
FILE *f = fopen(filename, "w");
|
||||
if (!f)
|
||||
LOGE("WVMFileSource: can't open %s", filename);
|
||||
else {
|
||||
fwrite(buffer, amount, 1, f);
|
||||
fclose(f);
|
||||
}
|
||||
LOGD("WVMFileSource::Read(%d bytes to buf=%p)", amount, buffer);
|
||||
#endif
|
||||
|
||||
mOffset += result;
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
26
proprietary/wvm/WVMLogging.cpp
Normal file
26
proprietary/wvm/WVMLogging.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "WVMLogging"
|
||||
#include <utils/Log.h>
|
||||
#include "WVMLogging.h"
|
||||
|
||||
// Connect Widevine debug logging into Android logging
|
||||
|
||||
void android_printbuf(const char *buf)
|
||||
{
|
||||
LOGD("%s", buf);
|
||||
}
|
||||
278
proprietary/wvm/WVMMediaSource.cpp
Normal file
278
proprietary/wvm/WVMMediaSource.cpp
Normal file
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "WVMMediaSource"
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include "WVMMediaSource.h"
|
||||
#include "WVMFileSource.h"
|
||||
#include "media/stagefright/MediaErrors.h"
|
||||
#include "media/stagefright/MediaDefs.h"
|
||||
#include "media/stagefright/MediaDebug.h"
|
||||
|
||||
namespace android {
|
||||
|
||||
extern DrmManagerClient *gDrmManagerClient;
|
||||
|
||||
WVMMediaSource::WVMMediaSource(WVSession *session, WVEsSelector esSelector,
|
||||
const sp<MetaData> &metaData)
|
||||
: mSession(session),
|
||||
mESSelector(esSelector),
|
||||
mTrackMetaData(metaData),
|
||||
mStarted(false),
|
||||
mGroup(NULL),
|
||||
mDts(0),
|
||||
mPts(0)
|
||||
{
|
||||
}
|
||||
|
||||
// Since the WVMExtractor lifetime is short, we delegate ownership of some resources
|
||||
// to the media source, which cleans them up after when the media source is destroyed
|
||||
|
||||
void WVMMediaSource::delegateFileSource(sp<WVMFileSource> fileSource)
|
||||
{
|
||||
mFileSource = fileSource;
|
||||
}
|
||||
|
||||
void WVMMediaSource::delegateDataSource(sp<DataSource> dataSource)
|
||||
{
|
||||
mDataSource = dataSource;
|
||||
}
|
||||
|
||||
void WVMMediaSource::allocBufferGroup()
|
||||
{
|
||||
if (mGroup)
|
||||
delete mGroup;
|
||||
|
||||
mGroup = new MediaBufferGroup;
|
||||
|
||||
size_t size;
|
||||
if (mESSelector == WV_EsSelector_Video)
|
||||
size = 256 * 1024;
|
||||
else
|
||||
size = 64 * 1024;
|
||||
|
||||
mGroup->add_buffer(new MediaBuffer(size));
|
||||
}
|
||||
|
||||
|
||||
|
||||
status_t WVMMediaSource::start(MetaData *)
|
||||
{
|
||||
//LOGD("WVMMediaSource::start()");
|
||||
Mutex::Autolock autoLock(mLock);
|
||||
|
||||
CHECK(!mStarted);
|
||||
|
||||
allocBufferGroup();
|
||||
|
||||
mStarted = true;
|
||||
|
||||
// Let video stream control play/pause
|
||||
if (mESSelector == WV_EsSelector_Video) {
|
||||
float speed;
|
||||
WVStatus result = WV_Play(mSession, 1.0, &speed, "now-");
|
||||
if (result != WV_Status_OK) {
|
||||
LOGE("WV_Play returned status %d in WVMMediaSource::start\n", result);
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
status_t WVMMediaSource::stop()
|
||||
{
|
||||
//LOGD("WVMMediaSource::stop()");
|
||||
Mutex::Autolock autoLock(mLock);
|
||||
|
||||
CHECK(mStarted);
|
||||
|
||||
// Let video stream control play/pause
|
||||
if (mESSelector == WV_EsSelector_Video) {
|
||||
WVStatus result = WV_Pause(mSession, "now");
|
||||
if (result != WV_Status_OK) {
|
||||
LOGE("WV_Pause returned status %d in WVMMediaSource::stop\n", result);
|
||||
}
|
||||
}
|
||||
|
||||
delete mGroup;
|
||||
mGroup = NULL;
|
||||
|
||||
mStarted = false;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
sp<MetaData> WVMMediaSource::getFormat()
|
||||
{
|
||||
Mutex::Autolock autoLock(mLock);
|
||||
return mTrackMetaData;
|
||||
}
|
||||
|
||||
std::string usecToNPT(int64_t time)
|
||||
{
|
||||
unsigned hours = (unsigned)(time / (60LL * 60 * 1000000));
|
||||
time -= (int64_t)hours * 60 * 60 * 1000000;
|
||||
unsigned mins = (unsigned)(time / (60 * 1000000));
|
||||
time -= (int64_t)mins * 60 * 1000000;
|
||||
float secs = (float)time / 1000000;
|
||||
char buf[32];
|
||||
sprintf(buf, "%d:%d:%f", hours, mins, secs);
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
status_t WVMMediaSource::read(MediaBuffer **buffer, const ReadOptions *options)
|
||||
{
|
||||
Mutex::Autolock autoLock(mLock);
|
||||
|
||||
CHECK(mStarted);
|
||||
|
||||
*buffer = NULL;
|
||||
|
||||
int64_t seekTimeUs;
|
||||
ReadOptions::SeekMode mode;
|
||||
if (options && options->getSeekTo(&seekTimeUs, &mode)) {
|
||||
// Let video stream control seek
|
||||
if (mESSelector == WV_EsSelector_Video) {
|
||||
float scaleUsed;
|
||||
std::string when = usecToNPT(seekTimeUs) + std::string("-");
|
||||
WVStatus result = WV_Play(mSession, 1.0, &scaleUsed, when );
|
||||
if (result != WV_Status_OK) {
|
||||
LOGE("WV_Play returned status %d in WVMMediaSource::read\n", result);
|
||||
return ERROR_IO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MediaBuffer *mediaBuf;
|
||||
|
||||
status_t err = mGroup->acquire_buffer(&mediaBuf);
|
||||
|
||||
if (err != OK) {
|
||||
CHECK_EQ(mediaBuf, NULL);
|
||||
return err;
|
||||
}
|
||||
|
||||
size_t bytesRead;
|
||||
bool auStart;
|
||||
size_t offset = 0;
|
||||
|
||||
// Pull full access units. Since we aren't sure how big they might be,
|
||||
// start with initial buffer size, then allocate a larger buffer if we
|
||||
// get more a number of bytes equal to the full buffer size and go back
|
||||
// for the rest. Only loop in this case, usually it's one pass through.
|
||||
|
||||
while (true) {
|
||||
size_t size = mediaBuf->size() - offset;
|
||||
|
||||
WVStatus result = WV_GetEsData(mSession, mESSelector, (uint8_t *)mediaBuf->data() + offset,
|
||||
size, bytesRead, auStart, mDts, mPts);
|
||||
if (result == WV_Status_End_Of_Media) {
|
||||
mediaBuf->release();
|
||||
return ERROR_END_OF_STREAM;
|
||||
} else if (result != WV_Status_OK) {
|
||||
if (result != WV_Status_Warning_Need_Key &&
|
||||
result != WV_Status_Warning_Download_Stalled)
|
||||
{
|
||||
LOGE("WV_GetEsData returned ERROR %d in WVMMediaSource::read\n", result);
|
||||
mediaBuf->release();
|
||||
return ERROR_IO;
|
||||
} else
|
||||
LOGW("WV_GetEsData returned WARNING %d in WVMMediaSource::read\n", result);
|
||||
}
|
||||
|
||||
|
||||
if (bytesRead == 0) {
|
||||
// Didn't get anything, sleep a bit so we don't hog the CPU then
|
||||
// try again.
|
||||
usleep(10000);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (offset + bytesRead < mediaBuf->size())
|
||||
break;
|
||||
|
||||
//LOGD("Resizing...");
|
||||
|
||||
// This buffer is too small, allocate a larger buffer twice the size
|
||||
// and copy the data from the current buffer into the first part of
|
||||
// the new buffer, then set offset to where the next read should go.
|
||||
|
||||
MediaBuffer *newBuffer = new MediaBuffer(mediaBuf->size() * 2);
|
||||
newBuffer->add_ref();
|
||||
|
||||
memcpy(newBuffer->data(), mediaBuf->data(), mediaBuf->size());
|
||||
offset = mediaBuf->size();
|
||||
|
||||
mGroup->add_buffer(newBuffer);
|
||||
|
||||
mediaBuf->release();
|
||||
mediaBuf = newBuffer;
|
||||
}
|
||||
|
||||
#define PCR_HZ 90000
|
||||
int64_t keyTime = (int64_t)mDts * 1000000 / PCR_HZ;
|
||||
|
||||
mediaBuf->meta_data()->clear();
|
||||
mediaBuf->meta_data()->setInt64(kKeyTime, keyTime);
|
||||
|
||||
mediaBuf->set_range(0, bytesRead + offset);
|
||||
|
||||
#if 0
|
||||
// debug code - log packets to files
|
||||
char filename[32];
|
||||
static int acounter = 0, vcounter = 0;
|
||||
if (mESSelector == WV_EsSelector_Video)
|
||||
sprintf(filename, "/data/wvm/v%d", vcounter++);
|
||||
else
|
||||
sprintf(filename, "/data/wvm/a%d", acounter++);
|
||||
|
||||
FILE *f = fopen(filename, "w");
|
||||
if (!f)
|
||||
LOGE("WVMFileSource: can't open %s", filename);
|
||||
else {
|
||||
fwrite(mediaBuf->data(), bytesRead + offset, 1, f);
|
||||
fclose(f);
|
||||
}
|
||||
LOGD("WVMMediaSource::read writing (%d bytes to %s)", bytesRead + offset, filename);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
LOGD("[%p] %s set range_length=%d, get range_length=%d kKeyTime=%lld\n", mediaBuf,
|
||||
(mESSelector == WV_EsSelector_Video ? "video" : "audio"),
|
||||
bytesRead + offset, mediaBuf->range_length(), keyTime);
|
||||
#endif
|
||||
|
||||
*buffer = mediaBuf;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
WVMMediaSource::~WVMMediaSource()
|
||||
{
|
||||
//LOGD("WVMMediaSource::~WVMMediaSource()");
|
||||
|
||||
if (mStarted) {
|
||||
stop();
|
||||
}
|
||||
|
||||
if (mESSelector == WV_EsSelector_Video) {
|
||||
if (mSession != NULL)
|
||||
WV_Teardown(mSession);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
77
proprietary/wvm/include/WVMExtractorImpl.h
Normal file
77
proprietary/wvm/include/WVMExtractorImpl.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef WVMEXTRACTOR_H_
|
||||
|
||||
#define WVMEXTRACTOR_H_
|
||||
|
||||
#include "AndroidConfig.h"
|
||||
#include "WVStreamControlAPI.h"
|
||||
#include <media/stagefright/MediaExtractor.h>
|
||||
#include <media/stagefright/DataSource.h>
|
||||
#include <utils/RefBase.h>
|
||||
|
||||
|
||||
// DLL entry - given a data source, instantiate a WVMExtractor object
|
||||
|
||||
namespace android {
|
||||
|
||||
MediaExtractor *GetInstance(sp<DataSource> dataSource);
|
||||
|
||||
|
||||
class WVMMediaSource;
|
||||
class WVMFileSource;
|
||||
|
||||
class WVMExtractorImpl : public MediaExtractor {
|
||||
public:
|
||||
WVMExtractorImpl(sp<DataSource> dataSource);
|
||||
|
||||
virtual size_t countTracks();
|
||||
virtual sp<MediaSource> getTrack(size_t index);
|
||||
virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
|
||||
|
||||
virtual sp<MetaData> getMetaData();
|
||||
|
||||
protected:
|
||||
virtual ~WVMExtractorImpl();
|
||||
|
||||
private:
|
||||
status_t readAVCCMetaData(sp<MetaData> videoMetaData);
|
||||
status_t readESDSMetaData(sp<MetaData> audioMetaData);
|
||||
|
||||
sp<WVMMediaSource> mAudioSource;
|
||||
sp<WVMMediaSource> mVideoSource;
|
||||
sp<MetaData> mFileMetaData;
|
||||
sp<WVMFileSource> mFileSource;
|
||||
sp<DataSource> mDataSource;
|
||||
|
||||
bool mHaveMetaData;
|
||||
|
||||
WVSession *mSession;
|
||||
|
||||
status_t mSetupStatus;
|
||||
|
||||
status_t readMetaData();
|
||||
|
||||
const static size_t kStreamCacheSize = 10 * 1024 * 1024;
|
||||
|
||||
WVMExtractorImpl(const WVMExtractorImpl &);
|
||||
WVMExtractorImpl &operator=(const WVMExtractorImpl &);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
|
||||
#endif // WVMEXTRACTOR_H_
|
||||
51
proprietary/wvm/include/WVMFileSource.h
Normal file
51
proprietary/wvm/include/WVMFileSource.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef WVFILE_SOURCE_H_
|
||||
#define WVFILE_SOURCE_H_
|
||||
|
||||
#include "AndroidConfig.h"
|
||||
#include "WVStreamControlAPI.h"
|
||||
#include <media/stagefright/DataSource.h>
|
||||
#include <utils/RefBase.h>
|
||||
|
||||
//
|
||||
// Supports reading data from local file descriptor instead of URI-based streaming
|
||||
// as we normally do.
|
||||
//
|
||||
|
||||
namespace android {
|
||||
|
||||
class WVMFileSource : public WVFileSource, public RefBase {
|
||||
public:
|
||||
WVMFileSource(sp<DataSource> &dataSource);
|
||||
virtual ~WVMFileSource() {}
|
||||
|
||||
virtual unsigned long long GetSize();
|
||||
virtual unsigned long long GetOffset();
|
||||
|
||||
virtual void Seek(unsigned long long offset);
|
||||
virtual size_t Read(size_t amount, unsigned char *buffer);
|
||||
|
||||
private:
|
||||
sp<DataSource> mDataSource;
|
||||
unsigned long long mOffset;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
22
proprietary/wvm/include/WVMLogging.h
Normal file
22
proprietary/wvm/include/WVMLogging.h
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __WVMLOGGING_H__
|
||||
#define __WVMLOGGING_H__
|
||||
|
||||
void android_printbuf(const char *buf);
|
||||
|
||||
#endif
|
||||
77
proprietary/wvm/include/WVMMediaSource.h
Normal file
77
proprietary/wvm/include/WVMMediaSource.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef WVMMEDIA_SOURCE_H_
|
||||
#define WVMMEDIA_SOURCE_H_
|
||||
|
||||
#include "AndroidConfig.h"
|
||||
#include "WVStreamControlAPI.h"
|
||||
#include <media/stagefright/DataSource.h>
|
||||
#include <media/stagefright/MediaSource.h>
|
||||
#include <media/stagefright/MetaData.h>
|
||||
#include <media/stagefright/MediaBufferGroup.h>
|
||||
#include <utils/RefBase.h>
|
||||
|
||||
|
||||
namespace android {
|
||||
|
||||
class WVMFileSource;
|
||||
|
||||
class WVMMediaSource : public MediaSource {
|
||||
public:
|
||||
WVMMediaSource(WVSession *session, WVEsSelector esSelector,
|
||||
const sp<MetaData> &metaData);
|
||||
|
||||
void delegateFileSource(sp<WVMFileSource> fileSource);
|
||||
void delegateDataSource(sp<DataSource> dataSource);
|
||||
|
||||
virtual status_t start(MetaData *params = NULL);
|
||||
virtual status_t stop();
|
||||
|
||||
virtual sp<MetaData> getFormat();
|
||||
|
||||
virtual status_t read(MediaBuffer **buffer, const ReadOptions *options = NULL);
|
||||
|
||||
protected:
|
||||
virtual ~WVMMediaSource();
|
||||
|
||||
private:
|
||||
Mutex mLock;
|
||||
|
||||
WVSession *mSession;
|
||||
WVEsSelector mESSelector; // indicates audio vs. video
|
||||
|
||||
sp<MetaData> mTrackMetaData;
|
||||
|
||||
bool mStarted;
|
||||
|
||||
MediaBufferGroup *mGroup;
|
||||
|
||||
unsigned long long mDts;
|
||||
unsigned long long mPts;
|
||||
|
||||
sp<WVMFileSource> mFileSource;
|
||||
sp<DataSource> mDataSource;
|
||||
|
||||
void allocBufferGroup();
|
||||
|
||||
WVMMediaSource(const WVMMediaSource &);
|
||||
WVMMediaSource &operator=(const WVMMediaSource &);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
|
||||
#endif // WVMMEDIA_SOURCE_H_
|
||||
27
proprietary/wvm/test/Android.mk
Normal file
27
proprietary/wvm/test/Android.mk
Normal file
@@ -0,0 +1,27 @@
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES:= \
|
||||
Testlibwvm.cpp
|
||||
|
||||
LOCAL_C_INCLUDES+= \
|
||||
bionic \
|
||||
vendor/widevine/proprietary/include \
|
||||
external/stlport/stlport \
|
||||
frameworks/base/media/libstagefright
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libstlport \
|
||||
libdrmframework \
|
||||
libstagefright \
|
||||
liblog \
|
||||
libutils \
|
||||
libz \
|
||||
libdl
|
||||
|
||||
LOCAL_MODULE:=test-libwvm
|
||||
|
||||
LOCAL_MODULE_TAGS := tests
|
||||
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
81
proprietary/wvm/test/Testlibwvm.cpp
Normal file
81
proprietary/wvm/test/Testlibwvm.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <iostream>
|
||||
|
||||
#include "include/WVMExtractor.h"
|
||||
#include <media/stagefright/Utils.h>
|
||||
#include <media/stagefright/DataSource.h>
|
||||
#include <media/stagefright/MediaSource.h>
|
||||
#include <media/stagefright/FileSource.h>
|
||||
#include <media/stagefright/MediaDefs.h>
|
||||
#include <media/stagefright/MetaData.h>
|
||||
#include <media/stagefright/MediaErrors.h>
|
||||
#include <media/stagefright/MediaBuffer.h>
|
||||
#include <media/stagefright/MediaDebug.h>
|
||||
|
||||
using namespace android;
|
||||
using namespace std;
|
||||
|
||||
class TestLibWVM
|
||||
{
|
||||
public:
|
||||
TestLibWVM() {}
|
||||
~TestLibWVM() {}
|
||||
|
||||
// Tests
|
||||
void Load();
|
||||
};
|
||||
|
||||
DrmManagerClient* gDrmManagerClient;
|
||||
|
||||
// This test just confirms that there are no unresolved symbols in libwvm and we
|
||||
// can locate the entry point.
|
||||
|
||||
void TestLibWVM::Load()
|
||||
{
|
||||
cout << "TestLibWVM::Load" << endl;
|
||||
|
||||
const char *path = "/system/lib/libwvm.so";
|
||||
void *handle = dlopen(path, RTLD_NOW);
|
||||
if (handle == NULL) {
|
||||
fprintf(stderr, "Can't open plugin: %s\n", path);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
typedef MediaExtractor *(*GetInstanceFunc)(sp<DataSource>);
|
||||
GetInstanceFunc getInstanceFunc =
|
||||
(GetInstanceFunc) dlsym(handle,
|
||||
"_ZN7android11GetInstanceENS_2spINS_10DataSourceEEE");
|
||||
|
||||
// Basic test - just see if we can instantiate the object and call a method
|
||||
if (getInstanceFunc) {
|
||||
LOGD("Found GetInstanceFunc");
|
||||
} else {
|
||||
LOGE("Failed to locate GetInstance in libwvm.so");
|
||||
}
|
||||
|
||||
// dlclose(handle);
|
||||
printf("Test successful!\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
TestLibWVM test;
|
||||
test.Load();
|
||||
}
|
||||
Reference in New Issue
Block a user