From 95d4dc7776b0202f22bd743e1e2b86a444a247a3 Mon Sep 17 00:00:00 2001 From: Jeff Tinker Date: Wed, 7 Dec 2011 20:28:03 -0800 Subject: [PATCH] Fix ANRs due to Widevine DRM plugin sniff taking too long. Add a Widevine-specific format sniffer to avoid having to refetch data from the remote server. related-to-bug: 5725548 Change-Id: I622e39930f8d243111e4731557b0df17c4e2651d --- proprietary/drmwvmplugin/src/WVMDrmPlugin.cpp | 58 +++++-------------- proprietary/wvm/WVMExtractorImpl.cpp | 21 +++++++ proprietary/wvm/include/WVMExtractorImpl.h | 2 +- 3 files changed, 36 insertions(+), 45 deletions(-) diff --git a/proprietary/drmwvmplugin/src/WVMDrmPlugin.cpp b/proprietary/drmwvmplugin/src/WVMDrmPlugin.cpp index ba7707e7..60b5972f 100644 --- a/proprietary/drmwvmplugin/src/WVMDrmPlugin.cpp +++ b/proprietary/drmwvmplugin/src/WVMDrmPlugin.cpp @@ -710,42 +710,14 @@ status_t WVMDrmPlugin::onRemoveAllRights(int uniqueId) { status_t WVMDrmPlugin::onOpenDecryptSession( int uniqueId, DecryptHandle *decryptHandle, int fd, off64_t offset, off64_t length) { - status_t result = DRM_ERROR_CANNOT_HANDLE; + // For efficiency, we rely on the WVMExtractor's sniff result instead of + // setting mimeType and decryptApiType here for the DRMExtractor's sniff. + // WVMExtractor's sniff uses the cached data source for the sniff. + decryptHandle->decryptInfo = NULL; + decryptHandle->status = DRM_NO_ERROR; - //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; - - mDrmPluginImpl->OpenSession(NULL); - result = DRM_NO_ERROR; - } else { - //LOGD("WVMDrmPlugin::onOpenDecryptSession - not Widevine media"); - } - - return result; + mDrmPluginImpl->OpenSession(NULL); + return DRM_NO_ERROR; } /** @@ -760,21 +732,19 @@ status_t WVMDrmPlugin::onOpenDecryptSession( status_t WVMDrmPlugin::onOpenDecryptSession( int uniqueId, DecryptHandle* decryptHandle, const char* uri) { + // For efficiency, we rely on the WVMExtractor's sniff result instead of + // setting mimeType and decryptApiType here for the DRMExtractor's sniff. + // WVMExtractor's sniff uses the cached data source for the sniff. status_t result = DRM_ERROR_CANNOT_HANDLE; if (!uri) return result; - if (mDrmPluginImpl->IsSupportedMediaType(uri)) { - //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; + decryptHandle->decryptInfo = NULL; + decryptHandle->status = DRM_NO_ERROR; - if (mDrmPluginImpl->OpenSession(uri)) { - result = DRM_NO_ERROR; - } + if (mDrmPluginImpl->OpenSession(uri)) { + result = DRM_NO_ERROR; } else { //LOGD("WVMDrmPlugin::onOpenDecryptSession(uri) - not Widevine media"); } diff --git a/proprietary/wvm/WVMExtractorImpl.cpp b/proprietary/wvm/WVMExtractorImpl.cpp index 8b27adc3..6af475f3 100644 --- a/proprietary/wvm/WVMExtractorImpl.cpp +++ b/proprietary/wvm/WVMExtractorImpl.cpp @@ -80,6 +80,27 @@ WVMLoadableExtractor *GetInstance(sp dataSource) { return new WVMExtractorImpl(dataSource); } +bool IsWidevineMedia(sp dataSource) { + char buffer[64 * 1024]; + + String8 uri = dataSource->getUri(); + if (uri.getPathExtension() == ".m3u8" || uri.find(".m3u8?") != -1) { + // can't sniff live streams - check for .m3u8 file extension + return true; + } + + ssize_t bytesRead = dataSource->readAt(0, buffer, sizeof(buffer)); + if (bytesRead < (ssize_t)sizeof(buffer)) { + LOGW("IsWidevineMedia - insufficient data: %d", (int)bytesRead); + return false; + } + + bool result = WV_IsWidevineMedia(buffer, sizeof(buffer)); + return result; +} + + + WVMExtractorImpl::WVMExtractorImpl(sp dataSource) : mFileMetaData(new MetaData()), mDataSource(dataSource), diff --git a/proprietary/wvm/include/WVMExtractorImpl.h b/proprietary/wvm/include/WVMExtractorImpl.h index 63e016c7..c8c9b9b3 100644 --- a/proprietary/wvm/include/WVMExtractorImpl.h +++ b/proprietary/wvm/include/WVMExtractorImpl.h @@ -31,7 +31,7 @@ namespace android { WVMLoadableExtractor *GetInstance(sp dataSource); - +bool IsWidevineMedia(sp dataSource); class WVMMediaSource; class WVMFileSource;