am ba5fa0ef: Fixes for b/4149416:expired license refresh, b/4126624:heartbeats, b/4171055: inconsistent license modes Also includes b/3500025: A/V resync issues
* commit 'ba5fa0ef570f6ca3524f8158a23371528930f0fc': Fixes for b/4149416:expired license refresh, b/4126624:heartbeats, b/4171055: inconsistent license modes Also includes b/3500025: A/V resync issues
This commit is contained in:
@@ -47,16 +47,18 @@ class WVDRMPluginAPI {
|
||||
std::string &dsPath, const std::string &assetIdStr,
|
||||
const std::string &systemIdStr,
|
||||
const std::string &keyIdStr,
|
||||
uint32_t *assetId, uint32_t *systemId,
|
||||
uint32_t *assetId, uint32_t *systemId,
|
||||
uint32_t *keyId) = 0;
|
||||
|
||||
virtual bool ProcessDrmInfo(std::string &assetPath, int playbackMode) = 0;
|
||||
virtual int CheckRightsStatus(std::string &path) = 0;
|
||||
|
||||
virtual bool GetConstraints(std::string &path, uint32_t *timeSincePlayback,
|
||||
uint32_t *timeRemaining,
|
||||
uint32_t *licenseDuration, std::string &lastError,
|
||||
bool &allowOffline, bool &allowStreaming,
|
||||
bool &denyHD) = 0;
|
||||
|
||||
virtual bool SetPlaybackStatus(int playbackStatus, off64_t position) = 0;
|
||||
virtual bool RemoveRights(std::string &path) = 0;
|
||||
virtual bool RemoveAllRights() = 0;
|
||||
@@ -67,10 +69,20 @@ class WVDRMPluginAPI {
|
||||
EventType_AcquireDrmInfoFailed,
|
||||
EventType_ProcessDrmInfoFailed,
|
||||
EventType_RightsInstalled,
|
||||
EventType_RightsRemoved
|
||||
EventType_RightsRemoved,
|
||||
|
||||
EventType_HeartbeatServer,
|
||||
EventType_HeartbeatPeriod
|
||||
};
|
||||
|
||||
typedef void (*EventHandler)(EventType type, const std::string &path);
|
||||
enum EventDestination {
|
||||
EventDestination_JavaAPI,
|
||||
EventDestination_MediaPlayer
|
||||
};
|
||||
|
||||
// Returns true if event sent, false if no handler
|
||||
typedef bool (*EventHandler)(EventType type, EventDestination destination,
|
||||
const std::string &path);
|
||||
virtual void SetEventHandler(EventHandler handler) = 0;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -100,10 +100,32 @@ protected:
|
||||
ssize_t onPread(int uniqueId, DecryptHandle* decryptHandle,
|
||||
void* buffer, ssize_t numBytes, off64_t offset);
|
||||
|
||||
class Listener {
|
||||
public:
|
||||
Listener() : mListener(NULL), mUniqueId(-1) {}
|
||||
|
||||
Listener(IDrmEngine::OnInfoListener *listener, int uniqueId)
|
||||
: mListener(listener), mUniqueId(uniqueId) {};
|
||||
|
||||
IDrmEngine::OnInfoListener *GetListener() const {return mListener;}
|
||||
int GetUniqueId() const {return mUniqueId;}
|
||||
|
||||
private:
|
||||
IDrmEngine::OnInfoListener *mListener;
|
||||
int mUniqueId;
|
||||
};
|
||||
|
||||
enum MessageType {
|
||||
MessageType_HeartbeatServer = 4000,
|
||||
MessageType_HeartbeatPeriod = 4001
|
||||
};
|
||||
|
||||
private:
|
||||
static void SendEvent(WVDRMPluginAPI::EventType code, const std::string &path);
|
||||
static IDrmEngine::OnInfoListener *sOnInfoListener;
|
||||
static int sUniqueId;
|
||||
static bool SendEvent(WVDRMPluginAPI::EventType code, WVDRMPluginAPI::EventDestination dest,
|
||||
const std::string &path);
|
||||
|
||||
static Vector<Listener> *sNativeListeners;
|
||||
static Vector<Listener> *sJavaAPIListeners;
|
||||
|
||||
WVDRMPluginAPI *mDrmPluginImpl;
|
||||
};
|
||||
|
||||
Binary file not shown.
@@ -47,17 +47,21 @@ extern "C" void destroy(IDrmEngine* pPlugIn) {
|
||||
}
|
||||
|
||||
// Needed for event callout from implementation object
|
||||
IDrmEngine::OnInfoListener *WVMDrmPlugin::sOnInfoListener = NULL;
|
||||
int WVMDrmPlugin::sUniqueId;
|
||||
Vector<WVMDrmPlugin::Listener> *WVMDrmPlugin::sNativeListeners = NULL;
|
||||
Vector<WVMDrmPlugin::Listener> *WVMDrmPlugin::sJavaAPIListeners = NULL;
|
||||
|
||||
WVMDrmPlugin::WVMDrmPlugin()
|
||||
: DrmEngineBase(),
|
||||
mDrmPluginImpl(WVDRMPluginAPI::create())
|
||||
{
|
||||
sNativeListeners = new Vector<WVMDrmPlugin::Listener>();
|
||||
sJavaAPIListeners = new Vector<WVMDrmPlugin::Listener>();
|
||||
mDrmPluginImpl->SetEventHandler(&SendEvent);
|
||||
}
|
||||
|
||||
WVMDrmPlugin::~WVMDrmPlugin() {
|
||||
delete sNativeListeners;
|
||||
delete sJavaAPIListeners;
|
||||
WVDRMPluginAPI::destroy(mDrmPluginImpl);
|
||||
}
|
||||
|
||||
@@ -86,6 +90,21 @@ status_t WVMDrmPlugin::onInitialize(int uniqueId) {
|
||||
*/
|
||||
status_t WVMDrmPlugin::onTerminate(int uniqueId) {
|
||||
//LOGD("WVMDrmPlugin::onTerminate : %d", uniqueId);
|
||||
|
||||
for (size_t i = 0; i < sNativeListeners->size(); i++) {
|
||||
if ((*sNativeListeners)[i].GetUniqueId() == uniqueId) {
|
||||
sNativeListeners->removeAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < sJavaAPIListeners->size(); i++) {
|
||||
if ((*sJavaAPIListeners)[i].GetUniqueId() == uniqueId) {
|
||||
sJavaAPIListeners->removeAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return DRM_NO_ERROR;
|
||||
}
|
||||
|
||||
@@ -99,39 +118,91 @@ status_t WVMDrmPlugin::onTerminate(int uniqueId) {
|
||||
* 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);
|
||||
sOnInfoListener = const_cast<IDrmEngine::OnInfoListener *>(infoListener);
|
||||
sUniqueId = uniqueId;
|
||||
int uniqueId, const IDrmEngine::OnInfoListener* infoListener) {
|
||||
//LOGD("WVMDrmPlugin::onSetOnInfoListener : add %d", uniqueId);
|
||||
|
||||
Listener newListener = Listener(const_cast<IDrmEngine::OnInfoListener *>(infoListener), uniqueId);
|
||||
bool found = false;
|
||||
|
||||
const int maxNativeUniqueId = 100;
|
||||
if (uniqueId <= maxNativeUniqueId) {
|
||||
// Replace old listener for this id if it exists
|
||||
for (size_t i = 0; i < sNativeListeners->size(); i++) {
|
||||
if ((*sNativeListeners)[i].GetUniqueId() == uniqueId) {
|
||||
sNativeListeners->replaceAt(newListener, i);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
sNativeListeners->push(newListener);
|
||||
} else {
|
||||
// Replace old listener for this id if it exists
|
||||
for (size_t i = 0; i < sJavaAPIListeners->size(); i++) {
|
||||
if ((*sJavaAPIListeners)[i].GetUniqueId() == uniqueId) {
|
||||
sJavaAPIListeners->replaceAt(newListener, i);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
sJavaAPIListeners->push(newListener);
|
||||
}
|
||||
|
||||
return DRM_NO_ERROR;
|
||||
}
|
||||
|
||||
void WVMDrmPlugin::SendEvent(WVDRMPluginAPI::EventType type, const std::string &path)
|
||||
bool WVMDrmPlugin::SendEvent(WVDRMPluginAPI::EventType type,
|
||||
WVDRMPluginAPI::EventDestination destination,
|
||||
const std::string &msg)
|
||||
{
|
||||
int code = -1;
|
||||
bool result = false;
|
||||
|
||||
switch(type) {
|
||||
EventType_AcquireFailed:
|
||||
case WVDRMPluginAPI::EventType_AcquireDrmInfoFailed:
|
||||
code = DrmInfoEvent::TYPE_ACQUIRE_DRM_INFO_FAILED;
|
||||
break;
|
||||
EventType_ProcessDrmInfoFailed:
|
||||
case WVDRMPluginAPI::EventType_ProcessDrmInfoFailed:
|
||||
code = DrmInfoEvent::TYPE_PROCESS_DRM_INFO_FAILED;
|
||||
break;
|
||||
EventType_RightsInstalled:
|
||||
case WVDRMPluginAPI::EventType_RightsInstalled:
|
||||
code = DrmInfoEvent::TYPE_RIGHTS_INSTALLED;
|
||||
break;
|
||||
EventType_RightsRemoved:
|
||||
case WVDRMPluginAPI::EventType_RightsRemoved:
|
||||
code = DrmInfoEvent::TYPE_RIGHTS_REMOVED;
|
||||
break;
|
||||
case WVDRMPluginAPI::EventType_HeartbeatServer:
|
||||
code = MessageType_HeartbeatServer;
|
||||
break;
|
||||
case WVDRMPluginAPI::EventType_HeartbeatPeriod:
|
||||
code = MessageType_HeartbeatPeriod;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (sOnInfoListener) {
|
||||
String8 msg = String8(path.c_str());
|
||||
DrmInfoEvent event(sUniqueId, code, msg);
|
||||
sOnInfoListener->onInfo(event);
|
||||
String8 message = String8(msg.c_str());
|
||||
|
||||
if (destination == WVDRMPluginAPI::EventDestination_JavaAPI) {
|
||||
for (size_t i = 0; i < sJavaAPIListeners->size(); i++) {
|
||||
DrmInfoEvent event((*sJavaAPIListeners)[i].GetUniqueId(), code, message);
|
||||
//LOGD("WVMDrmPlugin::SendEvent [Java]: uniqueId=%d type=%d, code=%d, msg=%s",
|
||||
// (*sJavaAPIListeners)[i].GetUniqueId(), type, code, msg.c_str());
|
||||
(*sJavaAPIListeners)[i].GetListener()->onInfo(event);
|
||||
}
|
||||
result = true;
|
||||
} else if (destination == WVDRMPluginAPI::EventDestination_MediaPlayer) {
|
||||
for (size_t i = 0; i < sNativeListeners->size(); i++) {
|
||||
DrmInfoEvent event((*sNativeListeners)[i].GetUniqueId(), code, message);
|
||||
//LOGD("WVMDrmPlugin::SendEvent [Native]: uniqueId=%d type=%d, code=%d, msg=%s",
|
||||
// (*sNativeListeners)[i].GetUniqueId(), type, code, msg.c_str());
|
||||
(*sNativeListeners)[i].GetListener()->onInfo(event);
|
||||
}
|
||||
result = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -341,7 +412,7 @@ DrmConstraints* WVMDrmPlugin::onGetConstraints(int uniqueId, const String8* path
|
||||
drmConstraints->put(&key, lastError.c_str());
|
||||
|
||||
if (isValid) {
|
||||
char charValue[16]; // max uint32 = 0xffffffff + terminating char
|
||||
char charValue[16]; // max uint32 + terminating char
|
||||
|
||||
memset(charValue, 0, 16);
|
||||
sprintf(charValue, "%lu", (unsigned long)timeSincePlayback);
|
||||
@@ -649,6 +720,7 @@ status_t WVMDrmPlugin::onOpenDecryptSession(
|
||||
decryptHandle->decryptApiType = DecryptApiType::WV_BASED;
|
||||
decryptHandle->status = DRM_NO_ERROR;
|
||||
decryptHandle->decryptInfo = NULL;
|
||||
|
||||
mDrmPluginImpl->OpenSession();
|
||||
result = DRM_NO_ERROR;
|
||||
} else {
|
||||
@@ -675,8 +747,6 @@ status_t WVMDrmPlugin::onOpenDecryptSession(
|
||||
if (!uri)
|
||||
return result;
|
||||
|
||||
size_t len = strlen(uri);
|
||||
|
||||
if (mDrmPluginImpl->IsSupportedMediaType(uri)) {
|
||||
//LOGD("WVMDrmPlugin::onOpenDecryptSession(uri) : %d - match", uniqueId);
|
||||
decryptHandle->mimeType = String8("video/wvm");
|
||||
@@ -712,6 +782,7 @@ status_t WVMDrmPlugin::onCloseDecryptSession(int uniqueId, DecryptHandle* decryp
|
||||
delete decryptHandle; decryptHandle = NULL;
|
||||
}
|
||||
mDrmPluginImpl->CloseSession();
|
||||
|
||||
return DRM_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
@@ -199,7 +199,7 @@ void WVMDrmPluginTest::TestGetConstraints(IDrmEngine *plugin, String8 &url, int
|
||||
}
|
||||
|
||||
if (constraints->getCount() != 6) {
|
||||
fprintf(stderr, "getConstraints returned unexpected count!\n");
|
||||
fprintf(stderr, "getConstraints returned unexpected count: %d!\n", constraints->getCount());
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
|
||||
@@ -470,6 +470,26 @@ WV_Setup(WVSession *&session, WVFileSource *source, const std::string &transport
|
||||
CLIENT_API bool
|
||||
WV_IsWidevineMedia(const char *buffer, size_t length);
|
||||
|
||||
//
|
||||
// METHOD: WV_ConfigureHeartbeat
|
||||
//
|
||||
// Provides a method of configuring the heartbeat after WV_Setup has been
|
||||
// called.
|
||||
//
|
||||
//
|
||||
// Parameters:
|
||||
// [in] heartbeatURL - the URL of the heartbeat server
|
||||
// [in] heartbeatPeriod - the heartbeat interval in seconds
|
||||
//
|
||||
//
|
||||
// Returns:
|
||||
// WV_Status_OK on success, otherwise one of the WVStatus values
|
||||
// indicating the specific error.
|
||||
//
|
||||
CLIENT_API WVStatus
|
||||
WV_ConfigureHeartbeat(WVSession *session, std::string &heartbeatURL,
|
||||
unsigned int heartbeatPeriod);
|
||||
|
||||
//
|
||||
// METHOD: WV_Teardown
|
||||
//
|
||||
@@ -685,6 +705,9 @@ WV_GetData(WVSession *session, unsigned char *buffer, size_t request_size,
|
||||
//
|
||||
// [out] pts - On return, set to MPEG-2 access unit presentation timestamp (PTS)
|
||||
//
|
||||
// [out] sync_frame - On return, indicates whether the data belongs to a sync frame
|
||||
// (video key frame, or audio frame).
|
||||
//
|
||||
// Returns:
|
||||
// WV_Status_OK on success, otherwise one of the WVStatus values
|
||||
// indicating the specific error.
|
||||
@@ -692,7 +715,7 @@ WV_GetData(WVSession *session, unsigned char *buffer, size_t request_size,
|
||||
CLIENT_API WVStatus
|
||||
WV_GetEsData(WVSession *session, WVEsSelector es_selector,
|
||||
unsigned char *buffer, size_t request_size, size_t& return_size,
|
||||
bool& au_start, unsigned long long& dts, unsigned long long& pts);
|
||||
bool& au_start, unsigned long long& dts, unsigned long long& pts, bool& sync_frame);
|
||||
|
||||
|
||||
//
|
||||
|
||||
Binary file not shown.
@@ -8,7 +8,8 @@ LOCAL_SRC_FILES:= \
|
||||
WVMLogging.cpp \
|
||||
WVMExtractorImpl.cpp \
|
||||
WVMFileSource.cpp \
|
||||
WVMMediaSource.cpp
|
||||
WVMMediaSource.cpp \
|
||||
WVMInfoListener.cpp
|
||||
|
||||
LOCAL_C_INCLUDES:= \
|
||||
bionic \
|
||||
|
||||
@@ -20,11 +20,14 @@
|
||||
#include "WVMExtractorImpl.h"
|
||||
#include "WVMMediaSource.h"
|
||||
#include "WVMFileSource.h"
|
||||
#include "WVMInfoListener.h"
|
||||
#include "WVMLogging.h"
|
||||
#include "WVStreamControlAPI.h"
|
||||
#include "media/stagefright/MediaErrors.h"
|
||||
#include "media/stagefright/MediaDefs.h"
|
||||
#include "drm/DrmManagerClient.h"
|
||||
#include "drm/DrmConstraints.h"
|
||||
#include "drm/DrmInfoEvent.h"
|
||||
#include "AndroidHooks.h"
|
||||
|
||||
#define AES_BLOCK_SIZE 16
|
||||
@@ -86,6 +89,8 @@ WVMExtractorImpl::WVMExtractorImpl(sp<DataSource> dataSource)
|
||||
{
|
||||
dataSource->getDrmInfo(sDecryptHandle, &sDrmManagerClient);
|
||||
|
||||
//LOGD("WVMExtractorImpl::WVMExtractorImpl: uniqueId = %d", sDrmManagerClient->mUniqueId);
|
||||
|
||||
_ah006(android_printbuf);
|
||||
_ah002(_cb1);
|
||||
_ah004(_cb2);
|
||||
@@ -99,6 +104,16 @@ WVMExtractorImpl::WVMExtractorImpl(sp<DataSource> dataSource)
|
||||
|
||||
WVCredentials credentials;
|
||||
|
||||
// Set an info listener to handle messages from the drm plugin
|
||||
mInfoListener = new WVMInfoListener();
|
||||
|
||||
// Change #if 0 to #if 1 to enable heartbeats. Since the heartbeat server
|
||||
// is not yet returning valid responses, this will cause the player to
|
||||
// fail with an error, until the heartbeat server is working correctly.
|
||||
#if 0
|
||||
sDrmManagerClient->setOnInfoListener(mInfoListener);
|
||||
#endif
|
||||
|
||||
WVStatus result = WV_Initialize(NULL);
|
||||
if (result != WV_Status_OK) {
|
||||
LOGE("WV_Initialize returned status %d\n", result);
|
||||
@@ -107,22 +122,17 @@ WVMExtractorImpl::WVMExtractorImpl(sp<DataSource> dataSource)
|
||||
// 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);
|
||||
}
|
||||
mFileSource = new WVMFileSource(dataSource);
|
||||
result = WV_Setup(mSession, mFileSource.get(),
|
||||
"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;
|
||||
}
|
||||
|
||||
mInfoListener->setSession(mSession);
|
||||
}
|
||||
|
||||
WV_SetWarningToErrorMS(5000);
|
||||
@@ -241,6 +251,8 @@ status_t WVMExtractorImpl::readMetaData()
|
||||
|
||||
mHaveMetaData = true;
|
||||
|
||||
mInfoListener->configureHeartbeat();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -253,7 +265,7 @@ status_t WVMExtractorImpl::readAVCCMetaData(sp<MetaData> videoMetaData)
|
||||
int limit = 50;
|
||||
do {
|
||||
size_t bytesRead;
|
||||
bool auStart;
|
||||
bool auStart, sync;
|
||||
unsigned long long dts, pts;
|
||||
unsigned char buf[1];
|
||||
size_t bufSize = 0;
|
||||
@@ -263,7 +275,7 @@ status_t WVMExtractorImpl::readAVCCMetaData(sp<MetaData> videoMetaData)
|
||||
// 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);
|
||||
bytesRead, auStart, dts, pts, sync);
|
||||
|
||||
result = WV_Info_GetCodecConfig(mSession, WV_CodecConfigType_AVCC, config, size);
|
||||
if (result != WV_Status_OK)
|
||||
@@ -286,28 +298,7 @@ status_t WVMExtractorImpl::readAVCCMetaData(sp<MetaData> videoMetaData)
|
||||
}
|
||||
#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;
|
||||
}
|
||||
|
||||
@@ -320,7 +311,7 @@ status_t WVMExtractorImpl::readESDSMetaData(sp<MetaData> audioMetaData)
|
||||
int limit = 50;
|
||||
do {
|
||||
size_t bytesRead;
|
||||
bool auStart;
|
||||
bool auStart, sync;
|
||||
unsigned long long dts, pts;
|
||||
unsigned char buf[1];
|
||||
size_t bufSize = 0;
|
||||
@@ -330,7 +321,7 @@ status_t WVMExtractorImpl::readESDSMetaData(sp<MetaData> audioMetaData)
|
||||
// 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);
|
||||
bytesRead, auStart, dts, pts, sync);
|
||||
|
||||
result = WV_Info_GetCodecConfig(mSession, WV_CodecConfigType_ESDS, config, size);
|
||||
if (result != WV_Status_OK)
|
||||
|
||||
60
proprietary/wvm/WVMInfoListener.cpp
Normal file
60
proprietary/wvm/WVMInfoListener.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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 "WVMInfoListener"
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include "WVMExtractorImpl.h"
|
||||
#include "WVMMediaSource.h"
|
||||
#include "WVMFileSource.h"
|
||||
#include "WVMInfoListener.h"
|
||||
#include "WVMLogging.h"
|
||||
#include "WVStreamControlAPI.h"
|
||||
#include "media/stagefright/MediaErrors.h"
|
||||
#include "media/stagefright/MediaDefs.h"
|
||||
#include "drm/DrmInfoEvent.h"
|
||||
|
||||
|
||||
namespace android {
|
||||
|
||||
void WVMInfoListener::setSession(WVSession *session)
|
||||
{
|
||||
mSession = session;
|
||||
}
|
||||
|
||||
void WVMInfoListener::onInfo(const DrmInfoEvent &event)
|
||||
{
|
||||
//LOGD("WVMMediaSource::onInfo: type=%d, msg=%s!!!",
|
||||
// event.getType(), event.getMessage().string());
|
||||
|
||||
if (event.getType() == MessageType_HeartbeatServer)
|
||||
mServerUrl = event.getMessage();
|
||||
else if (event.getType() == MessageType_HeartbeatPeriod)
|
||||
mPeriod = atoi(event.getMessage());
|
||||
}
|
||||
|
||||
void WVMInfoListener::configureHeartbeat()
|
||||
{
|
||||
// send the first time we have all the info
|
||||
if (mSession && mServerUrl.size() && mPeriod != -1) {
|
||||
//LOGD("WVMMediaSource::calling WV_ConfigureHeartbeat()");
|
||||
WV_ConfigureHeartbeat(mSession, mServerUrl, mPeriod);
|
||||
mSession = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -32,8 +32,6 @@ static void _cb(int code)
|
||||
WVMMediaSource::sLastError = (status_t)code;
|
||||
}
|
||||
|
||||
extern DrmManagerClient *gDrmManagerClient;
|
||||
|
||||
status_t WVMMediaSource::sLastError = NO_ERROR;
|
||||
|
||||
WVMMediaSource::WVMMediaSource(WVSession *session, WVEsSelector esSelector,
|
||||
@@ -156,18 +154,28 @@ status_t WVMMediaSource::read(MediaBuffer **buffer, const ReadOptions *options)
|
||||
CHECK(mStarted);
|
||||
|
||||
*buffer = NULL;
|
||||
bool seekNextSync = false;
|
||||
|
||||
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;
|
||||
//LOGD("%s seek mode=%d, seek time=%lld lateby=%lld",
|
||||
// (mESSelector == WV_EsSelector_Video) ? "video" : "audio",
|
||||
// mode, seekTimeUs, options->getLateBy());
|
||||
if (mode == ReadOptions::SEEK_NEXT_SYNC) {
|
||||
// Handle seek next sync by dropping frames on this track that are
|
||||
// prior to the specified time.
|
||||
seekNextSync = true;
|
||||
} else {
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -184,17 +192,20 @@ status_t WVMMediaSource::read(MediaBuffer **buffer, const ReadOptions *options)
|
||||
size_t bytesRead;
|
||||
bool auStart;
|
||||
size_t offset = 0;
|
||||
int64_t keyTime;
|
||||
|
||||
bool syncFrame;
|
||||
|
||||
// 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
|
||||
// get 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);
|
||||
size, bytesRead, auStart, mDts, mPts, syncFrame);
|
||||
if (result == WV_Status_End_Of_Media) {
|
||||
mediaBuf->release();
|
||||
return ERROR_END_OF_STREAM;
|
||||
@@ -222,8 +233,16 @@ status_t WVMMediaSource::read(MediaBuffer **buffer, const ReadOptions *options)
|
||||
}
|
||||
|
||||
if (bytesRead == 0) {
|
||||
// Didn't get anything, sleep a bit so we don't hog the CPU then
|
||||
// try again.
|
||||
// Didn't get anything, sleep a bit so we don't hog the CPU then try again
|
||||
usleep(10000);
|
||||
continue;
|
||||
}
|
||||
|
||||
#define PCR_HZ 90000
|
||||
keyTime = (int64_t)mPts * 1000000 / PCR_HZ;
|
||||
|
||||
if (seekNextSync && ((keyTime < seekTimeUs) || !syncFrame)) {
|
||||
// drop frames up to next sync if requested
|
||||
usleep(10000);
|
||||
continue;
|
||||
}
|
||||
@@ -249,9 +268,6 @@ status_t WVMMediaSource::read(MediaBuffer **buffer, const ReadOptions *options)
|
||||
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);
|
||||
|
||||
@@ -277,9 +293,9 @@ status_t WVMMediaSource::read(MediaBuffer **buffer, const ReadOptions *options)
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
LOGD("[%p] %s set range_length=%d, get range_length=%d kKeyTime=%lld\n", mediaBuf,
|
||||
LOGD("[%p] %s set range_length=%d, get range_length=%d kKeyTime=%lld sync=%d\n", mediaBuf,
|
||||
(mESSelector == WV_EsSelector_Video ? "video" : "audio"),
|
||||
bytesRead + offset, mediaBuf->range_length(), keyTime);
|
||||
bytesRead + offset, mediaBuf->range_length(), keyTime, syncFrame);
|
||||
#endif
|
||||
|
||||
*buffer = mediaBuf;
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "AndroidConfig.h"
|
||||
#include "WVStreamControlAPI.h"
|
||||
#include "WVMInfoListener.h"
|
||||
#include <media/stagefright/MediaExtractor.h>
|
||||
#include <media/stagefright/DataSource.h>
|
||||
#include <utils/RefBase.h>
|
||||
@@ -59,6 +60,7 @@ private:
|
||||
sp<MetaData> mFileMetaData;
|
||||
sp<WVMFileSource> mFileSource;
|
||||
sp<DataSource> mDataSource;
|
||||
sp<WVMInfoListener> mInfoListener;
|
||||
|
||||
bool mHaveMetaData;
|
||||
|
||||
|
||||
51
proprietary/wvm/include/WVMInfoListener.h
Normal file
51
proprietary/wvm/include/WVMInfoListener.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 WVMINFO_LISTENER_H
|
||||
|
||||
#define WVMINFO_LISTENER_H
|
||||
|
||||
#include "AndroidConfig.h"
|
||||
#include "WVMMediaSource.h"
|
||||
#include <media/stagefright/DataSource.h>
|
||||
#include "WVStreamControlAPI.h"
|
||||
#include <utils/RefBase.h>
|
||||
|
||||
|
||||
namespace android {
|
||||
|
||||
// Handles messages from the DRM plugin
|
||||
class WVMInfoListener : public DrmManagerClient::OnInfoListener {
|
||||
enum MessageType {
|
||||
MessageType_HeartbeatServer = 4000,
|
||||
MessageType_HeartbeatPeriod = 4001
|
||||
};
|
||||
|
||||
public:
|
||||
WVMInfoListener() : mPeriod(-1) {};
|
||||
virtual void onInfo(const DrmInfoEvent &event);
|
||||
void setSession(WVSession *session);
|
||||
void configureHeartbeat();
|
||||
|
||||
private:
|
||||
WVSession *mSession;
|
||||
std::string mServerUrl;
|
||||
int mPeriod;
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
|
||||
#endif // WVMINFO_LISTENER_H
|
||||
Reference in New Issue
Block a user