diff --git a/proprietary/drmwvmplugin/include/WVDRMPluginAPI.h b/proprietary/drmwvmplugin/include/WVDRMPluginAPI.h index d9cb47b4..b17527d4 100644 --- a/proprietary/drmwvmplugin/include/WVDRMPluginAPI.h +++ b/proprietary/drmwvmplugin/include/WVDRMPluginAPI.h @@ -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: diff --git a/proprietary/drmwvmplugin/include/WVMDrmPlugin.h b/proprietary/drmwvmplugin/include/WVMDrmPlugin.h index 93c06c02..94646701 100644 --- a/proprietary/drmwvmplugin/include/WVMDrmPlugin.h +++ b/proprietary/drmwvmplugin/include/WVMDrmPlugin.h @@ -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 *sNativeListeners; + static Vector *sJavaAPIListeners; WVDRMPluginAPI *mDrmPluginImpl; }; diff --git a/proprietary/drmwvmplugin/lib/libwvdrm.so b/proprietary/drmwvmplugin/lib/libwvdrm.so index 784de9d2..90c93a89 100644 Binary files a/proprietary/drmwvmplugin/lib/libwvdrm.so and b/proprietary/drmwvmplugin/lib/libwvdrm.so differ diff --git a/proprietary/drmwvmplugin/src/WVMDrmPlugin.cpp b/proprietary/drmwvmplugin/src/WVMDrmPlugin.cpp index 5fda8110..42e2a2f6 100644 --- a/proprietary/drmwvmplugin/src/WVMDrmPlugin.cpp +++ b/proprietary/drmwvmplugin/src/WVMDrmPlugin.cpp @@ -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::sNativeListeners = NULL; +Vector *WVMDrmPlugin::sJavaAPIListeners = NULL; WVMDrmPlugin::WVMDrmPlugin() : DrmEngineBase(), mDrmPluginImpl(WVDRMPluginAPI::create()) { + sNativeListeners = new Vector(); + sJavaAPIListeners = new Vector(); 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(infoListener); - sUniqueId = uniqueId; + int uniqueId, const IDrmEngine::OnInfoListener* infoListener) { + //LOGD("WVMDrmPlugin::onSetOnInfoListener : add %d", uniqueId); + + Listener newListener = Listener(const_cast(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; } diff --git a/proprietary/drmwvmplugin/test/TestPlugin.cpp b/proprietary/drmwvmplugin/test/TestPlugin.cpp index f991bc23..4cec87a0 100644 --- a/proprietary/drmwvmplugin/test/TestPlugin.cpp +++ b/proprietary/drmwvmplugin/test/TestPlugin.cpp @@ -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); } diff --git a/proprietary/streamcontrol/include/WVStreamControlAPI.h b/proprietary/streamcontrol/include/WVStreamControlAPI.h index 48323f4d..40712b02 100644 --- a/proprietary/streamcontrol/include/WVStreamControlAPI.h +++ b/proprietary/streamcontrol/include/WVStreamControlAPI.h @@ -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); // diff --git a/proprietary/streamcontrol/lib/libWVStreamControlAPI.so b/proprietary/streamcontrol/lib/libWVStreamControlAPI.so index 40df6be6..3d02826d 100644 Binary files a/proprietary/streamcontrol/lib/libWVStreamControlAPI.so and b/proprietary/streamcontrol/lib/libWVStreamControlAPI.so differ diff --git a/proprietary/wvm/Android.mk b/proprietary/wvm/Android.mk index c0136d0a..006fe59a 100644 --- a/proprietary/wvm/Android.mk +++ b/proprietary/wvm/Android.mk @@ -8,7 +8,8 @@ LOCAL_SRC_FILES:= \ WVMLogging.cpp \ WVMExtractorImpl.cpp \ WVMFileSource.cpp \ - WVMMediaSource.cpp + WVMMediaSource.cpp \ + WVMInfoListener.cpp LOCAL_C_INCLUDES:= \ bionic \ diff --git a/proprietary/wvm/WVMExtractorImpl.cpp b/proprietary/wvm/WVMExtractorImpl.cpp index 8ed486a8..1a5afd9d 100644 --- a/proprietary/wvm/WVMExtractorImpl.cpp +++ b/proprietary/wvm/WVMExtractorImpl.cpp @@ -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->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) 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) // 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); @@ -233,6 +243,8 @@ status_t WVMExtractorImpl::readMetaData() mHaveMetaData = true; + mInfoListener->configureHeartbeat(); + return OK; } @@ -245,7 +257,7 @@ status_t WVMExtractorImpl::readAVCCMetaData(sp 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; @@ -255,7 +267,7 @@ status_t WVMExtractorImpl::readAVCCMetaData(sp 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) @@ -278,28 +290,7 @@ status_t WVMExtractorImpl::readAVCCMetaData(sp 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; } @@ -312,7 +303,7 @@ status_t WVMExtractorImpl::readESDSMetaData(sp 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; @@ -322,7 +313,7 @@ status_t WVMExtractorImpl::readESDSMetaData(sp 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) diff --git a/proprietary/wvm/WVMInfoListener.cpp b/proprietary/wvm/WVMInfoListener.cpp new file mode 100644 index 00000000..33c7b4c7 --- /dev/null +++ b/proprietary/wvm/WVMInfoListener.cpp @@ -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 + +#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; + } +} + +}; + diff --git a/proprietary/wvm/WVMMediaSource.cpp b/proprietary/wvm/WVMMediaSource.cpp index e74d59e8..cb2df116 100644 --- a/proprietary/wvm/WVMMediaSource.cpp +++ b/proprietary/wvm/WVMMediaSource.cpp @@ -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; diff --git a/proprietary/wvm/include/WVMExtractorImpl.h b/proprietary/wvm/include/WVMExtractorImpl.h index ba04c1d1..f97ee692 100644 --- a/proprietary/wvm/include/WVMExtractorImpl.h +++ b/proprietary/wvm/include/WVMExtractorImpl.h @@ -20,6 +20,7 @@ #include "AndroidConfig.h" #include "WVStreamControlAPI.h" +#include "WVMInfoListener.h" #include #include #include @@ -57,6 +58,7 @@ private: sp mFileMetaData; sp mFileSource; sp mDataSource; + sp mInfoListener; bool mHaveMetaData; diff --git a/proprietary/wvm/include/WVMInfoListener.h b/proprietary/wvm/include/WVMInfoListener.h new file mode 100644 index 00000000..6b8b2f80 --- /dev/null +++ b/proprietary/wvm/include/WVMInfoListener.h @@ -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 +#include "WVStreamControlAPI.h" +#include + + +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