diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp index a1ee90483f..9ba6ee17a3 100644 --- a/cmds/stagefright/stagefright.cpp +++ b/cmds/stagefright/stagefright.cpp @@ -1085,7 +1085,7 @@ int main(int argc, char **argv) { const char *filename = argv[k]; sp dataSource = - DataSourceFactory::CreateFromURI(NULL /* httpService */, filename); + DataSourceFactory::getInstance()->CreateFromURI(NULL /* httpService */, filename); if (strncasecmp(filename, "sine:", 5) && dataSource == NULL) { fprintf(stderr, "Unable to create data source.\n"); diff --git a/cmds/stagefright/stream.cpp b/cmds/stagefright/stream.cpp index 06346733fc..22e2ef3bae 100644 --- a/cmds/stagefright/stream.cpp +++ b/cmds/stagefright/stream.cpp @@ -164,7 +164,7 @@ MyConvertingStreamSource::MyConvertingStreamSource(const char *filename) : mCurrentBufferIndex(-1), mCurrentBufferOffset(0) { sp dataSource = - DataSourceFactory::CreateFromURI(NULL /* httpService */, filename); + DataSourceFactory::getInstance()->CreateFromURI(NULL /* httpService */, filename); CHECK(dataSource != NULL); diff --git a/media/codec2/components/cmds/codec2.cpp b/media/codec2/components/cmds/codec2.cpp index e572a53c47..38eaf885b0 100644 --- a/media/codec2/components/cmds/codec2.cpp +++ b/media/codec2/components/cmds/codec2.cpp @@ -418,7 +418,7 @@ int main(int argc, char **argv) { const char *filename = argv[k]; sp dataSource = - DataSourceFactory::CreateFromURI(nullptr /* httpService */, filename); + DataSourceFactory::getInstance()->CreateFromURI(nullptr /* httpService */, filename); if (strncasecmp(filename, "sine:", 5) && dataSource == nullptr) { fprintf(stderr, "Unable to create data source.\n"); diff --git a/media/libdatasource/Android.bp b/media/libdatasource/Android.bp index dd8ef74585..f191c2169e 100644 --- a/media/libdatasource/Android.bp +++ b/media/libdatasource/Android.bp @@ -2,8 +2,6 @@ cc_library { name: "libdatasource", srcs: [ - "ClearFileSource.cpp", - "ClearMediaHTTP.cpp", "DataSourceFactory.cpp", "DataURISource.cpp", "FileSource.cpp", @@ -31,7 +29,6 @@ cc_library { shared_libs: [ "liblog", "libcutils", - "libdrmframework", "libutils", "libstagefright_foundation", "libdl", diff --git a/media/libdatasource/ClearFileSource.cpp b/media/libdatasource/ClearFileSource.cpp deleted file mode 100644 index afafa23c8e..0000000000 --- a/media/libdatasource/ClearFileSource.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (C) 2018 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 "ClearFileSource" -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace android { - -ClearFileSource::ClearFileSource(const char *filename) - : mFd(-1), - mOffset(0), - mLength(-1), - mName("") { - - if (filename) { - mName = String8::format("FileSource(%s)", filename); - } - ALOGV("%s", filename); - mFd = open(filename, O_LARGEFILE | O_RDONLY); - - if (mFd >= 0) { - mLength = lseek64(mFd, 0, SEEK_END); - } else { - ALOGE("Failed to open file '%s'. (%s)", filename, strerror(errno)); - } -} - -ClearFileSource::ClearFileSource(int fd, int64_t offset, int64_t length) - : mFd(fd), - mOffset(offset), - mLength(length), - mName("") { - ALOGV("fd=%d (%s), offset=%lld, length=%lld", - fd, nameForFd(fd).c_str(), (long long) offset, (long long) length); - - if (mOffset < 0) { - mOffset = 0; - } - if (mLength < 0) { - mLength = 0; - } - if (mLength > INT64_MAX - mOffset) { - mLength = INT64_MAX - mOffset; - } - struct stat s; - if (fstat(fd, &s) == 0) { - if (mOffset > s.st_size) { - mOffset = s.st_size; - mLength = 0; - } - if (mOffset + mLength > s.st_size) { - mLength = s.st_size - mOffset; - } - } - if (mOffset != offset || mLength != length) { - ALOGW("offset/length adjusted from %lld/%lld to %lld/%lld", - (long long) offset, (long long) length, - (long long) mOffset, (long long) mLength); - } - - mName = String8::format( - "FileSource(fd(%s), %lld, %lld)", - nameForFd(fd).c_str(), - (long long) mOffset, - (long long) mLength); - -} - -ClearFileSource::~ClearFileSource() { - if (mFd >= 0) { - ::close(mFd); - mFd = -1; - } -} - -status_t ClearFileSource::initCheck() const { - return mFd >= 0 ? OK : NO_INIT; -} - -ssize_t ClearFileSource::readAt(off64_t offset, void *data, size_t size) { - if (mFd < 0) { - return NO_INIT; - } - - Mutex::Autolock autoLock(mLock); - if (mLength >= 0) { - if (offset >= mLength) { - return 0; // read beyond EOF. - } - uint64_t numAvailable = mLength - offset; - if ((uint64_t)size > numAvailable) { - size = numAvailable; - } - } - return readAt_l(offset, data, size); -} - -ssize_t ClearFileSource::readAt_l(off64_t offset, void *data, size_t size) { - off64_t result = lseek64(mFd, offset + mOffset, SEEK_SET); - if (result == -1) { - ALOGE("seek to %lld failed", (long long)(offset + mOffset)); - return UNKNOWN_ERROR; - } - - return ::read(mFd, data, size); -} - -status_t ClearFileSource::getSize(off64_t *size) { - Mutex::Autolock autoLock(mLock); - - if (mFd < 0) { - return NO_INIT; - } - - *size = mLength; - - return OK; -} - -} // namespace android diff --git a/media/libdatasource/ClearMediaHTTP.cpp b/media/libdatasource/ClearMediaHTTP.cpp deleted file mode 100644 index 7249c84126..0000000000 --- a/media/libdatasource/ClearMediaHTTP.cpp +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (C) 2018 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 "ClearMediaHTTP" -#include - -#include - -#include -#include -#include - -#include - -namespace android { - -ClearMediaHTTP::ClearMediaHTTP(const sp &conn) - : mInitCheck((conn != NULL) ? OK : NO_INIT), - mHTTPConnection(conn), - mCachedSizeValid(false), - mCachedSize(0ll) { -} - -ClearMediaHTTP::~ClearMediaHTTP() { -} - -status_t ClearMediaHTTP::connect( - const char *uri, - const KeyedVector *headers, - off64_t /* offset */) { - if (mInitCheck != OK) { - return mInitCheck; - } - - KeyedVector extHeaders; - if (headers != NULL) { - extHeaders = *headers; - } - - if (extHeaders.indexOfKey(String8("User-Agent")) < 0) { - extHeaders.add(String8("User-Agent"), String8(MakeUserAgent().c_str())); - } - - mLastURI = uri; - // reconnect() calls with uri == old mLastURI.c_str(), which gets zapped - // as part of the above assignment. Ensure no accidental later use. - uri = NULL; - - bool success = mHTTPConnection->connect(mLastURI.c_str(), &extHeaders); - - mLastHeaders = extHeaders; - - mCachedSizeValid = false; - - if (success) { - AString sanitized = uriDebugString(mLastURI); - mName = String8::format("ClearMediaHTTP(%s)", sanitized.c_str()); - } - - return success ? OK : UNKNOWN_ERROR; -} - -void ClearMediaHTTP::close() { - disconnect(); -} - -void ClearMediaHTTP::disconnect() { - mName = String8("ClearMediaHTTP()"); - if (mInitCheck != OK) { - return; - } - - mHTTPConnection->disconnect(); -} - -status_t ClearMediaHTTP::initCheck() const { - return mInitCheck; -} - -ssize_t ClearMediaHTTP::readAt(off64_t offset, void *data, size_t size) { - if (mInitCheck != OK) { - return mInitCheck; - } - - int64_t startTimeUs = ALooper::GetNowUs(); - - size_t numBytesRead = 0; - while (numBytesRead < size) { - size_t copy = size - numBytesRead; - - if (copy > 64 * 1024) { - // limit the buffer sizes transferred across binder boundaries - // to avoid spurious transaction failures. - copy = 64 * 1024; - } - - ssize_t n = mHTTPConnection->readAt( - offset + numBytesRead, (uint8_t *)data + numBytesRead, copy); - - if (n < 0) { - return n; - } else if (n == 0) { - break; - } - - numBytesRead += n; - } - - int64_t delayUs = ALooper::GetNowUs() - startTimeUs; - - addBandwidthMeasurement(numBytesRead, delayUs); - - return numBytesRead; -} - -status_t ClearMediaHTTP::getSize(off64_t *size) { - if (mInitCheck != OK) { - return mInitCheck; - } - - // Caching the returned size so that it stays valid even after a - // disconnect. NuCachedSource2 relies on this. - - if (!mCachedSizeValid) { - mCachedSize = mHTTPConnection->getSize(); - mCachedSizeValid = true; - } - - *size = mCachedSize; - - return *size < 0 ? *size : static_cast(OK); -} - -uint32_t ClearMediaHTTP::flags() { - return kWantsPrefetching | kIsHTTPBasedSource; -} - -status_t ClearMediaHTTP::reconnectAtOffset(off64_t offset) { - return connect(mLastURI.c_str(), &mLastHeaders, offset); -} - - -String8 ClearMediaHTTP::getUri() { - if (mInitCheck != OK) { - return String8::empty(); - } - - String8 uri; - if (OK == mHTTPConnection->getUri(&uri)) { - return uri; - } - return String8(mLastURI.c_str()); -} - -String8 ClearMediaHTTP::getMIMEType() const { - if (mInitCheck != OK) { - return String8("application/octet-stream"); - } - - String8 mimeType; - status_t err = mHTTPConnection->getMIMEType(&mimeType); - - if (err != OK) { - return String8("application/octet-stream"); - } - - return mimeType; -} - -} // namespace android diff --git a/media/libdatasource/DataSourceFactory.cpp b/media/libdatasource/DataSourceFactory.cpp index 8c772ddda8..bb6a08cc1f 100644 --- a/media/libdatasource/DataSourceFactory.cpp +++ b/media/libdatasource/DataSourceFactory.cpp @@ -30,6 +30,19 @@ namespace android { // static +sp DataSourceFactory::sInstance; +// static +Mutex DataSourceFactory::sInstanceLock; + +// static +sp DataSourceFactory::getInstance() { + Mutex::Autolock l(sInstanceLock); + if (!sInstance) { + sInstance = new DataSourceFactory(); + } + return sInstance; +} + sp DataSourceFactory::CreateFromURI( const sp &httpService, const char *uri, @@ -42,20 +55,16 @@ sp DataSourceFactory::CreateFromURI( sp source; if (!strncasecmp("file://", uri, 7)) { - source = new FileSource(uri + 7); + source = CreateFileSource(uri + 7); } else if (!strncasecmp("http://", uri, 7) || !strncasecmp("https://", uri, 8)) { if (httpService == NULL) { ALOGE("Invalid http service!"); return NULL; } - if (httpSource == NULL) { - sp conn = httpService->makeHTTPConnection(); - if (conn == NULL) { - ALOGE("Failed to make http connection from http service!"); - return NULL; - } - httpSource = new MediaHTTP(conn); + sp mediaHTTP = httpSource; + if (mediaHTTP == NULL) { + mediaHTTP = static_cast(CreateMediaHTTP(httpService).get()); } String8 cacheConfig; @@ -69,24 +78,24 @@ sp DataSourceFactory::CreateFromURI( &disconnectAtHighwatermark); } - if (httpSource->connect(uri, &nonCacheSpecificHeaders) != OK) { + if (mediaHTTP->connect(uri, &nonCacheSpecificHeaders) != OK) { ALOGE("Failed to connect http source!"); return NULL; } if (contentType != NULL) { - *contentType = httpSource->getMIMEType(); + *contentType = mediaHTTP->getMIMEType(); } source = NuCachedSource2::Create( - httpSource, + mediaHTTP, cacheConfig.isEmpty() ? NULL : cacheConfig.string(), disconnectAtHighwatermark); } else if (!strncasecmp("data:", uri, 5)) { source = DataURISource::Create(uri); } else { // Assume it's a filename. - source = new FileSource(uri); + source = CreateFileSource(uri); } if (source == NULL || source->initCheck() != OK) { @@ -108,10 +117,15 @@ sp DataSourceFactory::CreateMediaHTTP(const sp &ht sp conn = httpService->makeHTTPConnection(); if (conn == NULL) { + ALOGE("Failed to make http connection from http service!"); return NULL; } else { return new MediaHTTP(conn); } } +sp DataSourceFactory::CreateFileSource(const char *uri) { + return new FileSource(uri); +} + } // namespace android diff --git a/media/libdatasource/FileSource.cpp b/media/libdatasource/FileSource.cpp index 65780e3480..bbf7dda234 100644 --- a/media/libdatasource/FileSource.cpp +++ b/media/libdatasource/FileSource.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 The Android Open Source Project + * Copyright (C) 2018 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. @@ -20,45 +20,84 @@ #include #include -#include +#include +#include +#include +#include +#include +#include namespace android { FileSource::FileSource(const char *filename) - : ClearFileSource(filename), - mDecryptHandle(NULL), - mDrmManagerClient(NULL), - mDrmBufOffset(0), - mDrmBufSize(0), - mDrmBuf(NULL){ + : mFd(-1), + mOffset(0), + mLength(-1), + mName("") { + + if (filename) { + mName = String8::format("FileSource(%s)", filename); + } + ALOGV("%s", filename); + mFd = open(filename, O_LARGEFILE | O_RDONLY); + + if (mFd >= 0) { + mLength = lseek64(mFd, 0, SEEK_END); + } else { + ALOGE("Failed to open file '%s'. (%s)", filename, strerror(errno)); + } } FileSource::FileSource(int fd, int64_t offset, int64_t length) - : ClearFileSource(fd, offset, length), - mDecryptHandle(NULL), - mDrmManagerClient(NULL), - mDrmBufOffset(0), - mDrmBufSize(0), - mDrmBuf(NULL) { + : mFd(fd), + mOffset(offset), + mLength(length), + mName("") { + ALOGV("fd=%d (%s), offset=%lld, length=%lld", + fd, nameForFd(fd).c_str(), (long long) offset, (long long) length); + + if (mOffset < 0) { + mOffset = 0; + } + if (mLength < 0) { + mLength = 0; + } + if (mLength > INT64_MAX - mOffset) { + mLength = INT64_MAX - mOffset; + } + struct stat s; + if (fstat(fd, &s) == 0) { + if (mOffset > s.st_size) { + mOffset = s.st_size; + mLength = 0; + } + if (mOffset + mLength > s.st_size) { + mLength = s.st_size - mOffset; + } + } + if (mOffset != offset || mLength != length) { + ALOGW("offset/length adjusted from %lld/%lld to %lld/%lld", + (long long) offset, (long long) length, + (long long) mOffset, (long long) mLength); + } + + mName = String8::format( + "FileSource(fd(%s), %lld, %lld)", + nameForFd(fd).c_str(), + (long long) mOffset, + (long long) mLength); + } FileSource::~FileSource() { - if (mDrmBuf != NULL) { - delete[] mDrmBuf; - mDrmBuf = NULL; - } - - if (mDecryptHandle != NULL) { - // To release mDecryptHandle - CHECK(mDrmManagerClient); - mDrmManagerClient->closeDecryptSession(mDecryptHandle); - mDecryptHandle = NULL; + if (mFd >= 0) { + ::close(mFd); + mFd = -1; } +} - if (mDrmManagerClient != NULL) { - delete mDrmManagerClient; - mDrmManagerClient = NULL; - } +status_t FileSource::initCheck() const { + return mFd >= 0 ? OK : NO_INIT; } ssize_t FileSource::readAt(off64_t offset, void *data, size_t size) { @@ -67,7 +106,6 @@ ssize_t FileSource::readAt(off64_t offset, void *data, size_t size) { } Mutex::Autolock autoLock(mLock); - if (mLength >= 0) { if (offset >= mLength) { return 0; // read beyond EOF. @@ -77,79 +115,29 @@ ssize_t FileSource::readAt(off64_t offset, void *data, size_t size) { size = numAvailable; } } - - if (mDecryptHandle != NULL && DecryptApiType::CONTAINER_BASED - == mDecryptHandle->decryptApiType) { - return readAtDRM_l(offset, data, size); - } else { - return readAt_l(offset, data, size); - } + return readAt_l(offset, data, size); } -sp FileSource::DrmInitialization(const char *mime) { - if (getuid() == AID_MEDIA_EX) return nullptr; // no DRM in media extractor - if (mDrmManagerClient == NULL) { - mDrmManagerClient = new DrmManagerClient(); - } - - if (mDrmManagerClient == NULL) { - return NULL; - } - - if (mDecryptHandle == NULL) { - mDecryptHandle = mDrmManagerClient->openDecryptSession( - mFd, mOffset, mLength, mime); - } - - if (mDecryptHandle == NULL) { - delete mDrmManagerClient; - mDrmManagerClient = NULL; +ssize_t FileSource::readAt_l(off64_t offset, void *data, size_t size) { + off64_t result = lseek64(mFd, offset + mOffset, SEEK_SET); + if (result == -1) { + ALOGE("seek to %lld failed", (long long)(offset + mOffset)); + return UNKNOWN_ERROR; } - return mDecryptHandle; + return ::read(mFd, data, size); } -ssize_t FileSource::readAtDRM_l(off64_t offset, void *data, size_t size) { - size_t DRM_CACHE_SIZE = 1024; - if (mDrmBuf == NULL) { - mDrmBuf = new unsigned char[DRM_CACHE_SIZE]; - } +status_t FileSource::getSize(off64_t *size) { + Mutex::Autolock autoLock(mLock); - if (mDrmBuf != NULL && mDrmBufSize > 0 && (offset + mOffset) >= mDrmBufOffset - && (offset + mOffset + size) <= static_cast(mDrmBufOffset + mDrmBufSize)) { - /* Use buffered data */ - memcpy(data, (void*)(mDrmBuf+(offset+mOffset-mDrmBufOffset)), size); - return size; - } else if (size <= DRM_CACHE_SIZE) { - /* Buffer new data */ - mDrmBufOffset = offset + mOffset; - mDrmBufSize = mDrmManagerClient->pread(mDecryptHandle, mDrmBuf, - DRM_CACHE_SIZE, offset + mOffset); - if (mDrmBufSize > 0) { - int64_t dataRead = 0; - dataRead = size > static_cast(mDrmBufSize) ? mDrmBufSize : size; - memcpy(data, (void*)mDrmBuf, dataRead); - return dataRead; - } else { - return mDrmBufSize; - } - } else { - /* Too big chunk to cache. Call DRM directly */ - return mDrmManagerClient->pread(mDecryptHandle, data, size, offset + mOffset); + if (mFd < 0) { + return NO_INIT; } -} -/* static */ -bool FileSource::requiresDrm(int fd, int64_t offset, int64_t length, const char *mime) { - std::unique_ptr drmClient(new DrmManagerClient()); - sp decryptHandle = - drmClient->openDecryptSession(fd, offset, length, mime); - bool requiresDrm = false; - if (decryptHandle != nullptr) { - requiresDrm = decryptHandle->decryptApiType == DecryptApiType::CONTAINER_BASED; - drmClient->closeDecryptSession(decryptHandle); - } - return requiresDrm; + *size = mLength; + + return OK; } } // namespace android diff --git a/media/libdatasource/MediaHTTP.cpp b/media/libdatasource/MediaHTTP.cpp index e57510dc30..58c1ce8991 100644 --- a/media/libdatasource/MediaHTTP.cpp +++ b/media/libdatasource/MediaHTTP.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 The Android Open Source Project + * Copyright (C) 2018 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. @@ -20,7 +20,6 @@ #include -#include #include #include #include @@ -30,45 +29,156 @@ namespace android { MediaHTTP::MediaHTTP(const sp &conn) - : ClearMediaHTTP(conn), - mDrmManagerClient(NULL) { + : mInitCheck((conn != NULL) ? OK : NO_INIT), + mHTTPConnection(conn), + mCachedSizeValid(false), + mCachedSize(0ll) { } MediaHTTP::~MediaHTTP() { - clearDRMState_l(); } -// DRM... +status_t MediaHTTP::connect( + const char *uri, + const KeyedVector *headers, + off64_t /* offset */) { + if (mInitCheck != OK) { + return mInitCheck; + } + + KeyedVector extHeaders; + if (headers != NULL) { + extHeaders = *headers; + } + + if (extHeaders.indexOfKey(String8("User-Agent")) < 0) { + extHeaders.add(String8("User-Agent"), String8(MakeUserAgent().c_str())); + } + + mLastURI = uri; + // reconnect() calls with uri == old mLastURI.c_str(), which gets zapped + // as part of the above assignment. Ensure no accidental later use. + uri = NULL; + + bool success = mHTTPConnection->connect(mLastURI.c_str(), &extHeaders); + + mLastHeaders = extHeaders; + + mCachedSizeValid = false; + + if (success) { + AString sanitized = uriDebugString(mLastURI); + mName = String8::format("MediaHTTP(%s)", sanitized.c_str()); + } + + return success ? OK : UNKNOWN_ERROR; +} + +void MediaHTTP::close() { + disconnect(); +} + +void MediaHTTP::disconnect() { + mName = String8("MediaHTTP()"); + if (mInitCheck != OK) { + return; + } + + mHTTPConnection->disconnect(); +} + +status_t MediaHTTP::initCheck() const { + return mInitCheck; +} + +ssize_t MediaHTTP::readAt(off64_t offset, void *data, size_t size) { + if (mInitCheck != OK) { + return mInitCheck; + } -sp MediaHTTP::DrmInitialization(const char* mime) { - if (mDrmManagerClient == NULL) { - mDrmManagerClient = new DrmManagerClient(); + int64_t startTimeUs = ALooper::GetNowUs(); + + size_t numBytesRead = 0; + while (numBytesRead < size) { + size_t copy = size - numBytesRead; + + if (copy > 64 * 1024) { + // limit the buffer sizes transferred across binder boundaries + // to avoid spurious transaction failures. + copy = 64 * 1024; + } + + ssize_t n = mHTTPConnection->readAt( + offset + numBytesRead, (uint8_t *)data + numBytesRead, copy); + + if (n < 0) { + return n; + } else if (n == 0) { + break; + } + + numBytesRead += n; } - if (mDrmManagerClient == NULL) { - return NULL; + int64_t delayUs = ALooper::GetNowUs() - startTimeUs; + + addBandwidthMeasurement(numBytesRead, delayUs); + + return numBytesRead; +} + +status_t MediaHTTP::getSize(off64_t *size) { + if (mInitCheck != OK) { + return mInitCheck; } - if (mDecryptHandle == NULL) { - mDecryptHandle = mDrmManagerClient->openDecryptSession( - String8(mLastURI.c_str()), mime); + // Caching the returned size so that it stays valid even after a + // disconnect. NuCachedSource2 relies on this. + + if (!mCachedSizeValid) { + mCachedSize = mHTTPConnection->getSize(); + mCachedSizeValid = true; } - if (mDecryptHandle == NULL) { - delete mDrmManagerClient; - mDrmManagerClient = NULL; + *size = mCachedSize; + + return *size < 0 ? *size : static_cast(OK); +} + +uint32_t MediaHTTP::flags() { + return kWantsPrefetching | kIsHTTPBasedSource; +} + +status_t MediaHTTP::reconnectAtOffset(off64_t offset) { + return connect(mLastURI.c_str(), &mLastHeaders, offset); +} + + +String8 MediaHTTP::getUri() { + if (mInitCheck != OK) { + return String8::empty(); } - return mDecryptHandle; + String8 uri; + if (OK == mHTTPConnection->getUri(&uri)) { + return uri; + } + return String8(mLastURI.c_str()); } -void MediaHTTP::clearDRMState_l() { - if (mDecryptHandle != NULL) { - // To release mDecryptHandle - CHECK(mDrmManagerClient); - mDrmManagerClient->closeDecryptSession(mDecryptHandle); - mDecryptHandle = NULL; +String8 MediaHTTP::getMIMEType() const { + if (mInitCheck != OK) { + return String8("application/octet-stream"); } + + String8 mimeType; + status_t err = mHTTPConnection->getMIMEType(&mimeType); + + if (err != OK) { + return String8("application/octet-stream"); + } + + return mimeType; } } // namespace android diff --git a/media/libdatasource/include/datasource/ClearFileSource.h b/media/libdatasource/include/datasource/ClearFileSource.h deleted file mode 100644 index be83748d74..0000000000 --- a/media/libdatasource/include/datasource/ClearFileSource.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2018 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 CLEAR_FILE_SOURCE_H_ - -#define CLEAR_FILE_SOURCE_H_ - -#include - -#include -#include -#include - -namespace android { - -class ClearFileSource : public DataSource { -public: - ClearFileSource(const char *filename); - // ClearFileSource takes ownership and will close the fd - ClearFileSource(int fd, int64_t offset, int64_t length); - - virtual status_t initCheck() const; - - virtual ssize_t readAt(off64_t offset, void *data, size_t size); - - virtual status_t getSize(off64_t *size); - - virtual uint32_t flags() { - return kIsLocalFileSource; - } - - virtual String8 toString() { - return mName; - } - -protected: - virtual ~ClearFileSource(); - virtual ssize_t readAt_l(off64_t offset, void *data, size_t size); - - int mFd; - int64_t mOffset; - int64_t mLength; - Mutex mLock; - -private: - String8 mName; - - ClearFileSource(const ClearFileSource &); - ClearFileSource &operator=(const ClearFileSource &); -}; - -} // namespace android - -#endif // CLEAR_FILE_SOURCE_H_ - diff --git a/media/libdatasource/include/datasource/ClearMediaHTTP.h b/media/libdatasource/include/datasource/ClearMediaHTTP.h deleted file mode 100644 index 5440a3a46c..0000000000 --- a/media/libdatasource/include/datasource/ClearMediaHTTP.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2018 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 CLEAR_MEDIA_HTTP_H_ - -#define CLEAR_MEDIA_HTTP_H_ - -#include - -#include "HTTPBase.h" - -namespace android { - -struct MediaHTTPConnection; - -struct ClearMediaHTTP : public HTTPBase { - ClearMediaHTTP(const sp &conn); - - virtual status_t connect( - const char *uri, - const KeyedVector *headers, - off64_t offset); - - virtual void close(); - - virtual void disconnect(); - - virtual status_t initCheck() const; - - virtual ssize_t readAt(off64_t offset, void *data, size_t size); - - virtual status_t getSize(off64_t *size); - - virtual uint32_t flags(); - - virtual status_t reconnectAtOffset(off64_t offset); - -protected: - virtual ~ClearMediaHTTP(); - - virtual String8 getUri(); - virtual String8 getMIMEType() const; - - AString mLastURI; - -private: - status_t mInitCheck; - sp mHTTPConnection; - - KeyedVector mLastHeaders; - - bool mCachedSizeValid; - off64_t mCachedSize; - - DISALLOW_EVIL_CONSTRUCTORS(ClearMediaHTTP); -}; - -} // namespace android - -#endif // CLEAR_MEDIA_HTTP_H_ diff --git a/media/libdatasource/include/datasource/DataSourceFactory.h b/media/libdatasource/include/datasource/DataSourceFactory.h index 6e313d3712..194abe2309 100644 --- a/media/libdatasource/include/datasource/DataSourceFactory.h +++ b/media/libdatasource/include/datasource/DataSourceFactory.h @@ -29,17 +29,27 @@ struct MediaHTTPService; class String8; struct HTTPBase; -class DataSourceFactory { +class DataSourceFactory : public RefBase { public: - static sp CreateFromURI( + static sp getInstance(); + sp CreateFromURI( const sp &httpService, const char *uri, const KeyedVector *headers = NULL, String8 *contentType = NULL, HTTPBase *httpSource = NULL); - static sp CreateMediaHTTP(const sp &httpService); - static sp CreateFromFd(int fd, int64_t offset, int64_t length); + virtual sp CreateMediaHTTP(const sp &httpService); + sp CreateFromFd(int fd, int64_t offset, int64_t length); + +protected: + virtual sp CreateFileSource(const char *uri); + DataSourceFactory() {}; + virtual ~DataSourceFactory() {}; + +private: + static sp sInstance; + static Mutex sInstanceLock; }; } // namespace android diff --git a/media/libdatasource/include/datasource/FileSource.h b/media/libdatasource/include/datasource/FileSource.h index 92498429b9..dee0c335ea 100644 --- a/media/libdatasource/include/datasource/FileSource.h +++ b/media/libdatasource/include/datasource/FileSource.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 The Android Open Source Project + * Copyright (C) 2018 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. @@ -20,37 +20,43 @@ #include -#include +#include #include #include -#include namespace android { -class FileSource : public ClearFileSource { +class FileSource : public DataSource { public: FileSource(const char *filename); // FileSource takes ownership and will close the fd FileSource(int fd, int64_t offset, int64_t length); + virtual status_t initCheck() const; + virtual ssize_t readAt(off64_t offset, void *data, size_t size); - virtual sp DrmInitialization(const char *mime); + virtual status_t getSize(off64_t *size); + + virtual uint32_t flags() { + return kIsLocalFileSource; + } - static bool requiresDrm(int fd, int64_t offset, int64_t length, const char *mime); + virtual String8 toString() { + return mName; + } protected: virtual ~FileSource(); + virtual ssize_t readAt_l(off64_t offset, void *data, size_t size); + + int mFd; + int64_t mOffset; + int64_t mLength; + Mutex mLock; private: - /*for DRM*/ - sp mDecryptHandle; - DrmManagerClient *mDrmManagerClient; - int64_t mDrmBufOffset; - ssize_t mDrmBufSize; - unsigned char *mDrmBuf; - - ssize_t readAtDRM_l(off64_t offset, void *data, size_t size); + String8 mName; FileSource(const FileSource &); FileSource &operator=(const FileSource &); diff --git a/media/libdatasource/include/datasource/MediaHTTP.h b/media/libdatasource/include/datasource/MediaHTTP.h index 60252ce027..a8d203b245 100644 --- a/media/libdatasource/include/datasource/MediaHTTP.h +++ b/media/libdatasource/include/datasource/MediaHTTP.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 The Android Open Source Project + * Copyright (C) 2018 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. @@ -18,26 +18,52 @@ #define MEDIA_HTTP_H_ -#include #include +#include "HTTPBase.h" + namespace android { struct MediaHTTPConnection; -struct MediaHTTP : public ClearMediaHTTP { +struct MediaHTTP : public HTTPBase { MediaHTTP(const sp &conn); + virtual status_t connect( + const char *uri, + const KeyedVector *headers, + off64_t offset); + + virtual void close(); + + virtual void disconnect(); + + virtual status_t initCheck() const; + + virtual ssize_t readAt(off64_t offset, void *data, size_t size); + + virtual status_t getSize(off64_t *size); + + virtual uint32_t flags(); + + virtual status_t reconnectAtOffset(off64_t offset); + protected: virtual ~MediaHTTP(); - virtual sp DrmInitialization(const char* mime); + virtual String8 getUri(); + virtual String8 getMIMEType() const; + + AString mLastURI; private: - sp mDecryptHandle; - DrmManagerClient *mDrmManagerClient; + status_t mInitCheck; + sp mHTTPConnection; + + KeyedVector mLastHeaders; - void clearDRMState_l(); + bool mCachedSizeValid; + off64_t mCachedSize; DISALLOW_EVIL_CONSTRUCTORS(MediaHTTP); }; diff --git a/media/libmediaplayerservice/Android.bp b/media/libmediaplayerservice/Android.bp index 670101799d..5301f5c571 100644 --- a/media/libmediaplayerservice/Android.bp +++ b/media/libmediaplayerservice/Android.bp @@ -7,6 +7,7 @@ cc_library_shared { "MediaPlayerService.cpp", "MediaRecorderClient.cpp", "MetadataRetrieverClient.cpp", + "StagefrightMetadataRetriever.cpp", "StagefrightRecorder.cpp", "TestPlayerStub.cpp", ], @@ -23,6 +24,7 @@ cc_library_shared { "libcutils", "libdatasource", "libdl", + "libdrmframework", "libgui", "libhidlbase", "liblog", @@ -46,6 +48,7 @@ cc_library_shared { ], static_libs: [ + "libplayerservice_datasource", "libstagefright_nuplayer", "libstagefright_rtsp", "libstagefright_timedtext", diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp similarity index 98% rename from media/libstagefright/StagefrightMetadataRetriever.cpp rename to media/libmediaplayerservice/StagefrightMetadataRetriever.cpp index c157ede890..1aae241889 100644 --- a/media/libstagefright/StagefrightMetadataRetriever.cpp +++ b/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp @@ -22,11 +22,11 @@ #include #include -#include "include/FrameDecoder.h" -#include "include/StagefrightMetadataRetriever.h" +#include "StagefrightMetadataRetriever.h" +#include "FrameDecoder.h" -#include -#include +#include +#include #include #include #include @@ -63,7 +63,8 @@ status_t StagefrightMetadataRetriever::setDataSource( ALOGV("setDataSource(%s)", uri); clearMetadata(); - mSource = DataSourceFactory::CreateFromURI(httpService, uri, headers); + mSource = PlayerServiceDataSourceFactory::getInstance()->CreateFromURI( + httpService, uri, headers); if (mSource == NULL) { ALOGE("Unable to create data source for '%s'.", uri); @@ -91,7 +92,7 @@ status_t StagefrightMetadataRetriever::setDataSource( ALOGV("setDataSource(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length); clearMetadata(); - mSource = new FileSource(fd, offset, length); + mSource = new PlayerServiceFileSource(fd, offset, length); status_t err; if ((err = mSource->initCheck()) != OK) { diff --git a/media/libstagefright/include/StagefrightMetadataRetriever.h b/media/libmediaplayerservice/StagefrightMetadataRetriever.h similarity index 100% rename from media/libstagefright/include/StagefrightMetadataRetriever.h rename to media/libmediaplayerservice/StagefrightMetadataRetriever.h diff --git a/media/libmediaplayerservice/datasource/Android.bp b/media/libmediaplayerservice/datasource/Android.bp new file mode 100644 index 0000000000..71fa50b228 --- /dev/null +++ b/media/libmediaplayerservice/datasource/Android.bp @@ -0,0 +1,43 @@ +cc_library_static { + name: "libplayerservice_datasource", + + srcs: [ + "PlayerServiceDataSourceFactory.cpp", + "PlayerServiceFileSource.cpp", + "PlayerServiceMediaHTTP.cpp", + ], + + header_libs: [ + "media_ndk_headers", + "libmedia_headers", + ], + + shared_libs: [ + "libdatasource", + "libdrmframework", + "liblog", + "libutils", + ], + + local_include_dirs: [ + "include", + ], + + export_include_dirs: [ + "include", + ], + + cflags: [ + "-Werror", + "-Wno-error=deprecated-declarations", + "-Wall", + ], + + sanitize: { + misc_undefined: [ + "unsigned-integer-overflow", + "signed-integer-overflow", + ], + cfi: true, + }, +} diff --git a/media/libmediaplayerservice/datasource/PlayerServiceDataSourceFactory.cpp b/media/libmediaplayerservice/datasource/PlayerServiceDataSourceFactory.cpp new file mode 100644 index 0000000000..ef946e9c1e --- /dev/null +++ b/media/libmediaplayerservice/datasource/PlayerServiceDataSourceFactory.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2017 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 "PlayerServuceDataSourceFactory" + + +#include +#include +#include +#include +#include + +namespace android { + +// static +sp PlayerServiceDataSourceFactory::sInstance; +// static +Mutex PlayerServiceDataSourceFactory::sInstanceLock; + +// static +sp PlayerServiceDataSourceFactory::getInstance() { + Mutex::Autolock l(sInstanceLock); + if (!sInstance) { + sInstance = new PlayerServiceDataSourceFactory(); + } + return sInstance; +} + +sp PlayerServiceDataSourceFactory::CreateMediaHTTP( + const sp &httpService) { + if (httpService == NULL) { + return NULL; + } + + sp conn = httpService->makeHTTPConnection(); + if (conn == NULL) { + ALOGE("Failed to make http connection from http service!"); + return NULL; + } else { + return new PlayerServiceMediaHTTP(conn); + } +} + +sp PlayerServiceDataSourceFactory::CreateFileSource(const char *uri) { + return new PlayerServiceFileSource(uri); +} + +} // namespace android diff --git a/media/libmediaplayerservice/datasource/PlayerServiceFileSource.cpp b/media/libmediaplayerservice/datasource/PlayerServiceFileSource.cpp new file mode 100644 index 0000000000..15808910df --- /dev/null +++ b/media/libmediaplayerservice/datasource/PlayerServiceFileSource.cpp @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2009 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 "PlayerServiceFileSource" +#include + +#include +#include +#include + +namespace android { + +PlayerServiceFileSource::PlayerServiceFileSource(const char *filename) + : FileSource(filename), + mDecryptHandle(NULL), + mDrmManagerClient(NULL), + mDrmBufOffset(0), + mDrmBufSize(0), + mDrmBuf(NULL){ +} + +PlayerServiceFileSource::PlayerServiceFileSource(int fd, int64_t offset, int64_t length) + : FileSource(fd, offset, length), + mDecryptHandle(NULL), + mDrmManagerClient(NULL), + mDrmBufOffset(0), + mDrmBufSize(0), + mDrmBuf(NULL) { +} + +PlayerServiceFileSource::~PlayerServiceFileSource() { + if (mDrmBuf != NULL) { + delete[] mDrmBuf; + mDrmBuf = NULL; + } + + if (mDecryptHandle != NULL) { + // To release mDecryptHandle + CHECK(mDrmManagerClient); + mDrmManagerClient->closeDecryptSession(mDecryptHandle); + mDecryptHandle = NULL; + } + + if (mDrmManagerClient != NULL) { + delete mDrmManagerClient; + mDrmManagerClient = NULL; + } +} + +ssize_t PlayerServiceFileSource::readAt(off64_t offset, void *data, size_t size) { + if (mFd < 0) { + return NO_INIT; + } + + Mutex::Autolock autoLock(mLock); + + if (mLength >= 0) { + if (offset >= mLength) { + return 0; // read beyond EOF. + } + uint64_t numAvailable = mLength - offset; + if ((uint64_t)size > numAvailable) { + size = numAvailable; + } + } + + if (mDecryptHandle != NULL && DecryptApiType::CONTAINER_BASED + == mDecryptHandle->decryptApiType) { + return readAtDRM_l(offset, data, size); + } else { + return readAt_l(offset, data, size); + } +} + +sp PlayerServiceFileSource::DrmInitialization(const char *mime) { + if (getuid() == AID_MEDIA_EX) return nullptr; // no DRM in media extractor + if (mDrmManagerClient == NULL) { + mDrmManagerClient = new DrmManagerClient(); + } + + if (mDrmManagerClient == NULL) { + return NULL; + } + + if (mDecryptHandle == NULL) { + mDecryptHandle = mDrmManagerClient->openDecryptSession( + mFd, mOffset, mLength, mime); + } + + if (mDecryptHandle == NULL) { + delete mDrmManagerClient; + mDrmManagerClient = NULL; + } + + return mDecryptHandle; +} + +ssize_t PlayerServiceFileSource::readAtDRM_l(off64_t offset, void *data, size_t size) { + size_t DRM_CACHE_SIZE = 1024; + if (mDrmBuf == NULL) { + mDrmBuf = new unsigned char[DRM_CACHE_SIZE]; + } + + if (mDrmBuf != NULL && mDrmBufSize > 0 && (offset + mOffset) >= mDrmBufOffset + && (offset + mOffset + size) <= static_cast(mDrmBufOffset + mDrmBufSize)) { + /* Use buffered data */ + memcpy(data, (void*)(mDrmBuf+(offset+mOffset-mDrmBufOffset)), size); + return size; + } else if (size <= DRM_CACHE_SIZE) { + /* Buffer new data */ + mDrmBufOffset = offset + mOffset; + mDrmBufSize = mDrmManagerClient->pread(mDecryptHandle, mDrmBuf, + DRM_CACHE_SIZE, offset + mOffset); + if (mDrmBufSize > 0) { + int64_t dataRead = 0; + dataRead = size > static_cast(mDrmBufSize) ? mDrmBufSize : size; + memcpy(data, (void*)mDrmBuf, dataRead); + return dataRead; + } else { + return mDrmBufSize; + } + } else { + /* Too big chunk to cache. Call DRM directly */ + return mDrmManagerClient->pread(mDecryptHandle, data, size, offset + mOffset); + } +} + +/* static */ +bool PlayerServiceFileSource::requiresDrm(int fd, int64_t offset, int64_t length, const char *mime) { + std::unique_ptr drmClient(new DrmManagerClient()); + sp decryptHandle = + drmClient->openDecryptSession(fd, offset, length, mime); + bool requiresDrm = false; + if (decryptHandle != nullptr) { + requiresDrm = decryptHandle->decryptApiType == DecryptApiType::CONTAINER_BASED; + drmClient->closeDecryptSession(decryptHandle); + } + return requiresDrm; +} + +} // namespace android diff --git a/media/libmediaplayerservice/datasource/PlayerServiceMediaHTTP.cpp b/media/libmediaplayerservice/datasource/PlayerServiceMediaHTTP.cpp new file mode 100644 index 0000000000..0124720d39 --- /dev/null +++ b/media/libmediaplayerservice/datasource/PlayerServiceMediaHTTP.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2013 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 "PlayerServiceMediaHTTP" +#include + +#include + +#include +#include +#include +#include + +#include + +namespace android { + +PlayerServiceMediaHTTP::PlayerServiceMediaHTTP(const sp &conn) + : MediaHTTP(conn), + mDrmManagerClient(NULL) { +} + +PlayerServiceMediaHTTP::~PlayerServiceMediaHTTP() { + clearDRMState_l(); +} + +// DRM... + +sp PlayerServiceMediaHTTP::DrmInitialization(const char* mime) { + if (mDrmManagerClient == NULL) { + mDrmManagerClient = new DrmManagerClient(); + } + + if (mDrmManagerClient == NULL) { + return NULL; + } + + if (mDecryptHandle == NULL) { + mDecryptHandle = mDrmManagerClient->openDecryptSession( + String8(mLastURI.c_str()), mime); + } + + if (mDecryptHandle == NULL) { + delete mDrmManagerClient; + mDrmManagerClient = NULL; + } + + return mDecryptHandle; +} + +void PlayerServiceMediaHTTP::clearDRMState_l() { + if (mDecryptHandle != NULL) { + // To release mDecryptHandle + CHECK(mDrmManagerClient); + mDrmManagerClient->closeDecryptSession(mDecryptHandle); + mDecryptHandle = NULL; + } +} + +} // namespace android diff --git a/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceDataSourceFactory.h b/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceDataSourceFactory.h new file mode 100644 index 0000000000..7d58c5c2f2 --- /dev/null +++ b/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceDataSourceFactory.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2017 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 PLAYER_SERVICE_DATA_SOURCE_FACTORY_H_ + +#define PLAYER_SERVICE_DATA_SOURCE_FACTORY_H_ + +#include +#include +#include +#include + +namespace android { + +struct MediaHTTPService; +class String8; +struct HTTPBase; + +class PlayerServiceDataSourceFactory : public DataSourceFactory { +public: + static sp getInstance(); + virtual sp CreateMediaHTTP(const sp &httpService); + +protected: + virtual sp CreateFileSource(const char *uri); + +private: + static sp sInstance; + static Mutex sInstanceLock; + PlayerServiceDataSourceFactory() {}; +}; + +} // namespace android + +#endif // PLAYER_SERVICE_DATA_SOURCE_FACTORY_H_ diff --git a/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceFileSource.h b/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceFileSource.h new file mode 100644 index 0000000000..08a013e50d --- /dev/null +++ b/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceFileSource.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2009 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 PLAYER_SERVICE_FILE_SOURCE_H_ + +#define PLAYER_SERVICE_FILE_SOURCE_H_ + +#include + +#include +#include +#include +#include + +namespace android { + +// FileSource implementation which works on MediaPlayerService. +// Supports OMA(forword-lock) files. +class PlayerServiceFileSource : public FileSource { +public: + PlayerServiceFileSource(const char *filename); + // PlayerServiceFileSource takes ownership and will close the fd + PlayerServiceFileSource(int fd, int64_t offset, int64_t length); + + virtual ssize_t readAt(off64_t offset, void *data, size_t size); + + virtual sp DrmInitialization(const char *mime); + + static bool requiresDrm(int fd, int64_t offset, int64_t length, const char *mime); + +protected: + virtual ~PlayerServiceFileSource(); + +private: + /*for DRM*/ + sp mDecryptHandle; + DrmManagerClient *mDrmManagerClient; + int64_t mDrmBufOffset; + ssize_t mDrmBufSize; + unsigned char *mDrmBuf; + + ssize_t readAtDRM_l(off64_t offset, void *data, size_t size); + + PlayerServiceFileSource(const PlayerServiceFileSource &); + PlayerServiceFileSource &operator=(const PlayerServiceFileSource &); +}; + +} // namespace android + +#endif // PLAYER_SERVICE_FILE_SOURCE_H_ + diff --git a/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceMediaHTTP.h b/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceMediaHTTP.h new file mode 100644 index 0000000000..0032cd7567 --- /dev/null +++ b/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceMediaHTTP.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2013 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 PLAYER_SERVICE_MEDIA_HTTP_H_ + +#define PLAYER_SERVICE_MEDIA_HTTP_H_ + +#include +#include + +namespace android { + +struct MediaHTTPConnection; + +// MediaHTTP implementation which works on MediaPlayerService. +// Supports OMA(forword-lock) stream. +struct PlayerServiceMediaHTTP : public MediaHTTP { + PlayerServiceMediaHTTP(const sp &conn); + +protected: + virtual ~PlayerServiceMediaHTTP(); + + virtual sp DrmInitialization(const char* mime); + +private: + sp mDecryptHandle; + DrmManagerClient *mDrmManagerClient; + + void clearDRMState_l(); + + DISALLOW_EVIL_CONSTRUCTORS(PlayerServiceMediaHTTP); +}; + +} // namespace android + +#endif // PLAYER_SERVICE_MEDIA_HTTP_H_ diff --git a/media/libmediaplayerservice/nuplayer/Android.bp b/media/libmediaplayerservice/nuplayer/Android.bp index 19c8e765ed..c8f48a2c54 100644 --- a/media/libmediaplayerservice/nuplayer/Android.bp +++ b/media/libmediaplayerservice/nuplayer/Android.bp @@ -54,6 +54,10 @@ cc_library_static { "libpowermanager", ], + static_libs: [ + "libplayerservice_datasource", + ], + name: "libstagefright_nuplayer", sanitize: { diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp index e26f1e635d..f17520a088 100644 --- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp +++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp @@ -23,8 +23,8 @@ #include "AnotherPacketSource.h" #include #include -#include -#include +#include +#include #include #include #include @@ -385,7 +385,8 @@ void NuPlayer::GenericSource::onPrepareAsync() { if (!strncasecmp("http://", uri, 7) || !strncasecmp("https://", uri, 8)) { sp httpSource; mDisconnectLock.unlock(); - httpSource = DataSourceFactory::CreateMediaHTTP(mHTTPService); + httpSource = PlayerServiceDataSourceFactory::getInstance() + ->CreateMediaHTTP(mHTTPService); if (httpSource == NULL) { ALOGE("Failed to create http source!"); notifyPreparedAndCleanup(UNKNOWN_ERROR); @@ -401,9 +402,9 @@ void NuPlayer::GenericSource::onPrepareAsync() { mLock.unlock(); mDisconnectLock.unlock(); // This might take long time if connection has some issue. - sp dataSource = DataSourceFactory::CreateFromURI( - mHTTPService, uri, &mUriHeaders, &contentType, - static_cast(mHttpSource.get())); + sp dataSource = PlayerServiceDataSourceFactory::getInstance() + ->CreateFromURI(mHTTPService, uri, &mUriHeaders, &contentType, + static_cast(mHttpSource.get())); mDisconnectLock.lock(); mLock.lock(); if (!mDisconnected) { @@ -411,7 +412,8 @@ void NuPlayer::GenericSource::onPrepareAsync() { } } else { if (property_get_bool("media.stagefright.extractremote", true) && - !FileSource::requiresDrm(mFd, mOffset, mLength, nullptr /* mime */)) { + !PlayerServiceFileSource::requiresDrm( + mFd, mOffset, mLength, nullptr /* mime */)) { sp binder = defaultServiceManager()->getService(String16("media.extractor")); if (binder != nullptr) { @@ -438,7 +440,7 @@ void NuPlayer::GenericSource::onPrepareAsync() { } if (mDataSource == nullptr) { ALOGD("FileSource local"); - mDataSource = new FileSource(mFd, mOffset, mLength); + mDataSource = new PlayerServiceFileSource(mFd, mOffset, mLength); } // TODO: close should always be done on mFd, see the lines following // CreateDataSourceFromIDataSource above, diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp index a6dbce3d6b..59cc24b71f 100644 --- a/media/libstagefright/Android.bp +++ b/media/libstagefright/Android.bp @@ -161,7 +161,6 @@ cc_library { "SimpleDecodingSource.cpp", "SkipCutBuffer.cpp", "StagefrightMediaScanner.cpp", - "StagefrightMetadataRetriever.cpp", "StagefrightPluginLoader.cpp", "SurfaceUtils.cpp", "ThrottledSource.cpp", diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp index b89dcdf9ab..66fb4b0cd4 100644 --- a/media/libstagefright/NuMediaExtractor.cpp +++ b/media/libstagefright/NuMediaExtractor.cpp @@ -82,7 +82,7 @@ status_t NuMediaExtractor::setDataSource( } sp dataSource = - DataSourceFactory::CreateFromURI(httpService, path, headers); + DataSourceFactory::getInstance()->CreateFromURI(httpService, path, headers); if (dataSource == NULL) { return -ENOENT; diff --git a/media/libstagefright/httplive/HTTPDownloader.cpp b/media/libstagefright/httplive/HTTPDownloader.cpp index 7183dbdaa4..68f1de9ec6 100644 --- a/media/libstagefright/httplive/HTTPDownloader.cpp +++ b/media/libstagefright/httplive/HTTPDownloader.cpp @@ -21,8 +21,8 @@ #include "HTTPDownloader.h" #include "M3UParser.h" -#include -#include +#include +#include #include #include #include @@ -38,7 +38,7 @@ namespace android { HTTPDownloader::HTTPDownloader( const sp &httpService, const KeyedVector &headers) : - mHTTPDataSource(new ClearMediaHTTP(httpService->makeHTTPConnection())), + mHTTPDataSource(new MediaHTTP(httpService->makeHTTPConnection())), mExtraHeaders(headers), mDisconnecting(false) { } @@ -91,7 +91,7 @@ ssize_t HTTPDownloader::fetchBlock( if (reconnect) { if (!strncasecmp(url, "file://", 7)) { - mDataSource = new ClearFileSource(url + 7); + mDataSource = new FileSource(url + 7); } else if (strncasecmp(url, "http://", 7) && strncasecmp(url, "https://", 8)) { return ERROR_UNSUPPORTED; diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp index ee01d6c91d..6848a8386d 100644 --- a/media/libstagefright/omx/tests/OMXHarness.cpp +++ b/media/libstagefright/omx/tests/OMXHarness.cpp @@ -278,7 +278,7 @@ private: static sp CreateExtractorFromURI(const char *uri) { sp source = - DataSourceFactory::CreateFromURI(NULL /* httpService */, uri); + DataSourceFactory::getInstance()->CreateFromURI(NULL /* httpService */, uri); if (source == NULL) { return NULL; diff --git a/media/libstagefright/rtsp/SDPLoader.cpp b/media/libstagefright/rtsp/SDPLoader.cpp index 5bd218d771..e236267a47 100644 --- a/media/libstagefright/rtsp/SDPLoader.cpp +++ b/media/libstagefright/rtsp/SDPLoader.cpp @@ -22,7 +22,7 @@ #include "ASessionDescription.h" -#include +#include #include #include #include @@ -42,7 +42,7 @@ SDPLoader::SDPLoader( mFlags(flags), mNetLooper(new ALooper), mCancelled(false), - mHTTPDataSource(new ClearMediaHTTP(httpService->makeHTTPConnection())) { + mHTTPDataSource(new MediaHTTP(httpService->makeHTTPConnection())) { mNetLooper->setName("sdp net"); mNetLooper->start(false /* runOnCallingThread */, false /* canCallJava */, diff --git a/media/ndk/NdkMediaDataSource.cpp b/media/ndk/NdkMediaDataSource.cpp index f6892e6ccf..c1d4686fc9 100644 --- a/media/ndk/NdkMediaDataSource.cpp +++ b/media/ndk/NdkMediaDataSource.cpp @@ -202,7 +202,7 @@ AMediaDataSource* AMediaDataSource_newUri( headers.add(key8, value8); } - sp source = DataSourceFactory::CreateFromURI(service, uri, &headers); + sp source = DataSourceFactory::getInstance()->CreateFromURI(service, uri, &headers); if (source == NULL) { ALOGE("AMediaDataSource_newUri source is null"); return NULL; diff --git a/services/mediaextractor/MediaExtractorService.cpp b/services/mediaextractor/MediaExtractorService.cpp index ac6b7719fa..6239fb210f 100644 --- a/services/mediaextractor/MediaExtractorService.cpp +++ b/services/mediaextractor/MediaExtractorService.cpp @@ -55,7 +55,7 @@ sp MediaExtractorService::makeExtractor( sp MediaExtractorService::makeIDataSource(int fd, int64_t offset, int64_t length) { - sp source = DataSourceFactory::CreateFromFd(fd, offset, length); + sp source = DataSourceFactory::getInstance()->CreateFromFd(fd, offset, length); return CreateIDataSourceFromDataSource(source); }