Move all Widevine code which have dependency on vendor modules from framework/base to vendor/widevine

Change-Id: I2b43e90c279391436f1bbb18ebd64961bec4f9ee
This commit is contained in:
Gloria Wang
2011-02-18 22:51:13 -08:00
parent 1c53769dc1
commit 0f9922ff77
32 changed files with 2376 additions and 1 deletions

View 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

View 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

View 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

View 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);
}

View 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

View 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_

View 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

View 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

View 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_

View 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)

View 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();
}