Merge "Benchmark: Change library names to begin with libmediabenchmark"
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index a1ee904..9ba6ee1 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -1085,7 +1085,7 @@
const char *filename = argv[k];
sp<DataSource> 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 0634673..22e2ef3 100644
--- a/cmds/stagefright/stream.cpp
+++ b/cmds/stagefright/stream.cpp
@@ -164,7 +164,7 @@
: mCurrentBufferIndex(-1),
mCurrentBufferOffset(0) {
sp<DataSource> 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 e572a53..38eaf88 100644
--- a/media/codec2/components/cmds/codec2.cpp
+++ b/media/codec2/components/cmds/codec2.cpp
@@ -418,7 +418,7 @@
const char *filename = argv[k];
sp<DataSource> 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 dd8ef74..f191c21 100644
--- a/media/libdatasource/Android.bp
+++ b/media/libdatasource/Android.bp
@@ -2,8 +2,6 @@
name: "libdatasource",
srcs: [
- "ClearFileSource.cpp",
- "ClearMediaHTTP.cpp",
"DataSourceFactory.cpp",
"DataURISource.cpp",
"FileSource.cpp",
@@ -31,7 +29,6 @@
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 afafa23..0000000
--- 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 <utils/Log.h>
-
-#include <datasource/ClearFileSource.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/FoundationUtils.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-namespace android {
-
-ClearFileSource::ClearFileSource(const char *filename)
- : mFd(-1),
- mOffset(0),
- mLength(-1),
- mName("<null>") {
-
- 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("<null>") {
- 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 7249c84..0000000
--- 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 <utils/Log.h>
-
-#include <datasource/ClearMediaHTTP.h>
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/ALooper.h>
-#include <media/stagefright/FoundationUtils.h>
-
-#include <media/MediaHTTPConnection.h>
-
-namespace android {
-
-ClearMediaHTTP::ClearMediaHTTP(const sp<MediaHTTPConnection> &conn)
- : mInitCheck((conn != NULL) ? OK : NO_INIT),
- mHTTPConnection(conn),
- mCachedSizeValid(false),
- mCachedSize(0ll) {
-}
-
-ClearMediaHTTP::~ClearMediaHTTP() {
-}
-
-status_t ClearMediaHTTP::connect(
- const char *uri,
- const KeyedVector<String8, String8> *headers,
- off64_t /* offset */) {
- if (mInitCheck != OK) {
- return mInitCheck;
- }
-
- KeyedVector<String8, String8> 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(<disconnected>)");
- 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<status_t>(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 8c772dd..bb6a08c 100644
--- a/media/libdatasource/DataSourceFactory.cpp
+++ b/media/libdatasource/DataSourceFactory.cpp
@@ -30,6 +30,19 @@
namespace android {
// static
+sp<DataSourceFactory> DataSourceFactory::sInstance;
+// static
+Mutex DataSourceFactory::sInstanceLock;
+
+// static
+sp<DataSourceFactory> DataSourceFactory::getInstance() {
+ Mutex::Autolock l(sInstanceLock);
+ if (!sInstance) {
+ sInstance = new DataSourceFactory();
+ }
+ return sInstance;
+}
+
sp<DataSource> DataSourceFactory::CreateFromURI(
const sp<MediaHTTPService> &httpService,
const char *uri,
@@ -42,20 +55,16 @@
sp<DataSource> 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<MediaHTTPConnection> conn = httpService->makeHTTPConnection();
- if (conn == NULL) {
- ALOGE("Failed to make http connection from http service!");
- return NULL;
- }
- httpSource = new MediaHTTP(conn);
+ sp<HTTPBase> mediaHTTP = httpSource;
+ if (mediaHTTP == NULL) {
+ mediaHTTP = static_cast<HTTPBase *>(CreateMediaHTTP(httpService).get());
}
String8 cacheConfig;
@@ -69,24 +78,24 @@
&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<MediaHTTPConnection> conn = httpService->makeHTTPConnection();
if (conn == NULL) {
+ ALOGE("Failed to make http connection from http service!");
return NULL;
} else {
return new MediaHTTP(conn);
}
}
+sp<DataSource> DataSourceFactory::CreateFileSource(const char *uri) {
+ return new FileSource(uri);
+}
+
} // namespace android
diff --git a/media/libdatasource/FileSource.cpp b/media/libdatasource/FileSource.cpp
index 65780e3..bbf7dda 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 <datasource/FileSource.h>
#include <media/stagefright/foundation/ADebug.h>
-#include <private/android_filesystem_config.h>
+#include <media/stagefright/FoundationUtils.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
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("<null>") {
+
+ 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("<null>") {
+ 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 (mFd >= 0) {
+ ::close(mFd);
+ mFd = -1;
}
+}
- if (mDecryptHandle != NULL) {
- // To release mDecryptHandle
- CHECK(mDrmManagerClient);
- mDrmManagerClient->closeDecryptSession(mDecryptHandle);
- mDecryptHandle = NULL;
- }
-
- 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 @@
}
Mutex::Autolock autoLock(mLock);
-
if (mLength >= 0) {
if (offset >= mLength) {
return 0; // read beyond EOF.
@@ -77,79 +115,29 @@
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<DecryptHandle> FileSource::DrmInitialization(const char *mime) {
- if (getuid() == AID_MEDIA_EX) return nullptr; // no DRM in media extractor
- if (mDrmManagerClient == NULL) {
- mDrmManagerClient = new DrmManagerClient();
+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;
}
- if (mDrmManagerClient == NULL) {
- return NULL;
- }
-
- if (mDecryptHandle == NULL) {
- mDecryptHandle = mDrmManagerClient->openDecryptSession(
- mFd, mOffset, mLength, mime);
- }
-
- if (mDecryptHandle == NULL) {
- delete mDrmManagerClient;
- mDrmManagerClient = NULL;
- }
-
- 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 (mFd < 0) {
+ return NO_INIT;
}
- if (mDrmBuf != NULL && mDrmBufSize > 0 && (offset + mOffset) >= mDrmBufOffset
- && (offset + mOffset + size) <= static_cast<size_t>(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<size_t>(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);
- }
-}
+ *size = mLength;
-/* static */
-bool FileSource::requiresDrm(int fd, int64_t offset, int64_t length, const char *mime) {
- std::unique_ptr<DrmManagerClient> drmClient(new DrmManagerClient());
- sp<DecryptHandle> decryptHandle =
- drmClient->openDecryptSession(fd, offset, length, mime);
- bool requiresDrm = false;
- if (decryptHandle != nullptr) {
- requiresDrm = decryptHandle->decryptApiType == DecryptApiType::CONTAINER_BASED;
- drmClient->closeDecryptSession(decryptHandle);
- }
- return requiresDrm;
+ return OK;
}
} // namespace android
diff --git a/media/libdatasource/MediaHTTP.cpp b/media/libdatasource/MediaHTTP.cpp
index e57510d..58c1ce8 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 <datasource/MediaHTTP.h>
-#include <binder/IServiceManager.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/ALooper.h>
#include <media/stagefright/FoundationUtils.h>
@@ -30,45 +29,156 @@
namespace android {
MediaHTTP::MediaHTTP(const sp<MediaHTTPConnection> &conn)
- : ClearMediaHTTP(conn),
- mDrmManagerClient(NULL) {
+ : mInitCheck((conn != NULL) ? OK : NO_INIT),
+ mHTTPConnection(conn),
+ mCachedSizeValid(false),
+ mCachedSize(0ll) {
}
MediaHTTP::~MediaHTTP() {
- clearDRMState_l();
}
-// DRM...
-
-sp<DecryptHandle> MediaHTTP::DrmInitialization(const char* mime) {
- if (mDrmManagerClient == NULL) {
- mDrmManagerClient = new DrmManagerClient();
+status_t MediaHTTP::connect(
+ const char *uri,
+ const KeyedVector<String8, String8> *headers,
+ off64_t /* offset */) {
+ if (mInitCheck != OK) {
+ return mInitCheck;
}
- if (mDrmManagerClient == NULL) {
- return NULL;
+ KeyedVector<String8, String8> extHeaders;
+ if (headers != NULL) {
+ extHeaders = *headers;
}
- if (mDecryptHandle == NULL) {
- mDecryptHandle = mDrmManagerClient->openDecryptSession(
- String8(mLastURI.c_str()), mime);
+ if (extHeaders.indexOfKey(String8("User-Agent")) < 0) {
+ extHeaders.add(String8("User-Agent"), String8(MakeUserAgent().c_str()));
}
- if (mDecryptHandle == NULL) {
- delete mDrmManagerClient;
- mDrmManagerClient = NULL;
+ 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 mDecryptHandle;
+ return success ? OK : UNKNOWN_ERROR;
}
-void MediaHTTP::clearDRMState_l() {
- if (mDecryptHandle != NULL) {
- // To release mDecryptHandle
- CHECK(mDrmManagerClient);
- mDrmManagerClient->closeDecryptSession(mDecryptHandle);
- mDecryptHandle = NULL;
+void MediaHTTP::close() {
+ disconnect();
+}
+
+void MediaHTTP::disconnect() {
+ mName = String8("MediaHTTP(<disconnected>)");
+ 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;
+ }
+
+ 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 MediaHTTP::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<status_t>(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();
+ }
+
+ String8 uri;
+ if (OK == mHTTPConnection->getUri(&uri)) {
+ return uri;
+ }
+ return String8(mLastURI.c_str());
+}
+
+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 be83748..0000000
--- 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 <stdio.h>
-
-#include <media/DataSource.h>
-#include <media/stagefright/MediaErrors.h>
-#include <utils/threads.h>
-
-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 5440a3a..0000000
--- 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 <media/stagefright/foundation/AString.h>
-
-#include "HTTPBase.h"
-
-namespace android {
-
-struct MediaHTTPConnection;
-
-struct ClearMediaHTTP : public HTTPBase {
- ClearMediaHTTP(const sp<MediaHTTPConnection> &conn);
-
- virtual status_t connect(
- const char *uri,
- const KeyedVector<String8, String8> *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<MediaHTTPConnection> mHTTPConnection;
-
- KeyedVector<String8, String8> 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 6e313d3..194abe2 100644
--- a/media/libdatasource/include/datasource/DataSourceFactory.h
+++ b/media/libdatasource/include/datasource/DataSourceFactory.h
@@ -29,17 +29,27 @@
class String8;
struct HTTPBase;
-class DataSourceFactory {
+class DataSourceFactory : public RefBase {
public:
- static sp<DataSource> CreateFromURI(
+ static sp<DataSourceFactory> getInstance();
+ sp<DataSource> CreateFromURI(
const sp<MediaHTTPService> &httpService,
const char *uri,
const KeyedVector<String8, String8> *headers = NULL,
String8 *contentType = NULL,
HTTPBase *httpSource = NULL);
- static sp<DataSource> CreateMediaHTTP(const sp<MediaHTTPService> &httpService);
- static sp<DataSource> CreateFromFd(int fd, int64_t offset, int64_t length);
+ virtual sp<DataSource> CreateMediaHTTP(const sp<MediaHTTPService> &httpService);
+ sp<DataSource> CreateFromFd(int fd, int64_t offset, int64_t length);
+
+protected:
+ virtual sp<DataSource> CreateFileSource(const char *uri);
+ DataSourceFactory() {};
+ virtual ~DataSourceFactory() {};
+
+private:
+ static sp<DataSourceFactory> sInstance;
+ static Mutex sInstanceLock;
};
} // namespace android
diff --git a/media/libdatasource/include/datasource/FileSource.h b/media/libdatasource/include/datasource/FileSource.h
index 9249842..dee0c33 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 <stdio.h>
-#include <datasource/ClearFileSource.h>
+#include <media/DataSource.h>
#include <media/stagefright/MediaErrors.h>
#include <utils/threads.h>
-#include <drm/DrmManagerClient.h>
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<DecryptHandle> DrmInitialization(const char *mime);
+ virtual status_t getSize(off64_t *size);
- static bool requiresDrm(int fd, int64_t offset, int64_t length, const char *mime);
+ virtual uint32_t flags() {
+ return kIsLocalFileSource;
+ }
+
+ 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<DecryptHandle> 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 60252ce..a8d203b 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 <datasource/ClearMediaHTTP.h>
#include <media/stagefright/foundation/AString.h>
+#include "HTTPBase.h"
+
namespace android {
struct MediaHTTPConnection;
-struct MediaHTTP : public ClearMediaHTTP {
+struct MediaHTTP : public HTTPBase {
MediaHTTP(const sp<MediaHTTPConnection> &conn);
+ virtual status_t connect(
+ const char *uri,
+ const KeyedVector<String8, String8> *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<DecryptHandle> DrmInitialization(const char* mime);
+ virtual String8 getUri();
+ virtual String8 getMIMEType() const;
+
+ AString mLastURI;
private:
- sp<DecryptHandle> mDecryptHandle;
- DrmManagerClient *mDrmManagerClient;
+ status_t mInitCheck;
+ sp<MediaHTTPConnection> mHTTPConnection;
- void clearDRMState_l();
+ KeyedVector<String8, String8> mLastHeaders;
+
+ bool mCachedSizeValid;
+ off64_t mCachedSize;
DISALLOW_EVIL_CONSTRUCTORS(MediaHTTP);
};
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index fdab14a..ec4751c 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -285,7 +285,6 @@
"mediarecorder.cpp",
"IMediaMetadataRetriever.cpp",
"mediametadataretriever.cpp",
- "MidiDeviceInfo.cpp",
"MediaScanner.cpp",
"MediaScannerClient.cpp",
"CharacterEncodingDetector.cpp",
diff --git a/media/libmedia/MidiDeviceInfo.cpp b/media/libmedia/MidiDeviceInfo.cpp
deleted file mode 100644
index 7588e00..0000000
--- a/media/libmedia/MidiDeviceInfo.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2016 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 "MidiDeviceInfo"
-
-#include <media/MidiDeviceInfo.h>
-
-#include <binder/Parcel.h>
-#include <log/log.h>
-#include <utils/Errors.h>
-#include <utils/String16.h>
-
-namespace android {
-namespace media {
-namespace midi {
-
-// The constant values need to be kept in sync with MidiDeviceInfo.java.
-// static
-const char* const MidiDeviceInfo::PROPERTY_NAME = "name";
-const char* const MidiDeviceInfo::PROPERTY_MANUFACTURER = "manufacturer";
-const char* const MidiDeviceInfo::PROPERTY_PRODUCT = "product";
-const char* const MidiDeviceInfo::PROPERTY_VERSION = "version";
-const char* const MidiDeviceInfo::PROPERTY_SERIAL_NUMBER = "serial_number";
-const char* const MidiDeviceInfo::PROPERTY_ALSA_CARD = "alsa_card";
-const char* const MidiDeviceInfo::PROPERTY_ALSA_DEVICE = "alsa_device";
-
-String16 MidiDeviceInfo::getProperty(const char* propertyName) {
- String16 value;
- if (mProperties.getString(String16(propertyName), &value)) {
- return value;
- } else {
- return String16();
- }
-}
-
-#define RETURN_IF_FAILED(calledOnce) \
- { \
- status_t returnStatus = calledOnce; \
- if (returnStatus) { \
- ALOGE("Failed at %s:%d (%s)", __FILE__, __LINE__, __func__); \
- return returnStatus; \
- } \
- }
-
-status_t MidiDeviceInfo::writeToParcel(Parcel* parcel) const {
- // Needs to be kept in sync with code in MidiDeviceInfo.java
- RETURN_IF_FAILED(parcel->writeInt32(mType));
- RETURN_IF_FAILED(parcel->writeInt32(mId));
- RETURN_IF_FAILED(parcel->writeInt32((int32_t)mInputPortNames.size()));
- RETURN_IF_FAILED(parcel->writeInt32((int32_t)mOutputPortNames.size()));
- RETURN_IF_FAILED(writeStringVector(parcel, mInputPortNames));
- RETURN_IF_FAILED(writeStringVector(parcel, mOutputPortNames));
- RETURN_IF_FAILED(parcel->writeInt32(mIsPrivate ? 1 : 0));
- RETURN_IF_FAILED(mProperties.writeToParcel(parcel));
- // This corresponds to "extra" properties written by Java code
- RETURN_IF_FAILED(mProperties.writeToParcel(parcel));
- return OK;
-}
-
-status_t MidiDeviceInfo::readFromParcel(const Parcel* parcel) {
- // Needs to be kept in sync with code in MidiDeviceInfo.java
- RETURN_IF_FAILED(parcel->readInt32(&mType));
- RETURN_IF_FAILED(parcel->readInt32(&mId));
- int32_t inputPortCount;
- RETURN_IF_FAILED(parcel->readInt32(&inputPortCount));
- int32_t outputPortCount;
- RETURN_IF_FAILED(parcel->readInt32(&outputPortCount));
- RETURN_IF_FAILED(readStringVector(parcel, &mInputPortNames, inputPortCount));
- RETURN_IF_FAILED(readStringVector(parcel, &mOutputPortNames, outputPortCount));
- int32_t isPrivate;
- RETURN_IF_FAILED(parcel->readInt32(&isPrivate));
- mIsPrivate = isPrivate == 1;
- RETURN_IF_FAILED(mProperties.readFromParcel(parcel));
- // Ignore "extra" properties as they may contain Java Parcelables
- return OK;
-}
-
-status_t MidiDeviceInfo::readStringVector(
- const Parcel* parcel, Vector<String16> *vectorPtr, size_t defaultLength) {
- std::unique_ptr<std::vector<std::unique_ptr<String16>>> v;
- status_t result = parcel->readString16Vector(&v);
- if (result != OK) return result;
- vectorPtr->clear();
- if (v.get() != nullptr) {
- for (const auto& iter : *v) {
- if (iter.get() != nullptr) {
- vectorPtr->push_back(*iter);
- } else {
- vectorPtr->push_back(String16());
- }
- }
- } else {
- vectorPtr->resize(defaultLength);
- }
- return OK;
-}
-
-status_t MidiDeviceInfo::writeStringVector(Parcel* parcel, const Vector<String16>& vector) const {
- std::vector<String16> v;
- for (size_t i = 0; i < vector.size(); ++i) {
- v.push_back(vector[i]);
- }
- return parcel->writeString16Vector(v);
-}
-
-// Vector does not define operator==
-static inline bool areVectorsEqual(const Vector<String16>& lhs, const Vector<String16>& rhs) {
- if (lhs.size() != rhs.size()) return false;
- for (size_t i = 0; i < lhs.size(); ++i) {
- if (lhs[i] != rhs[i]) return false;
- }
- return true;
-}
-
-bool operator==(const MidiDeviceInfo& lhs, const MidiDeviceInfo& rhs) {
- return (lhs.mType == rhs.mType && lhs.mId == rhs.mId &&
- areVectorsEqual(lhs.mInputPortNames, rhs.mInputPortNames) &&
- areVectorsEqual(lhs.mOutputPortNames, rhs.mOutputPortNames) &&
- lhs.mProperties == rhs.mProperties &&
- lhs.mIsPrivate == rhs.mIsPrivate);
-}
-
-} // namespace midi
-} // namespace media
-} // namespace android
diff --git a/media/libmedia/include/media/MidiDeviceInfo.h b/media/libmedia/include/media/MidiDeviceInfo.h
deleted file mode 100644
index 5b4a241..0000000
--- a/media/libmedia/include/media/MidiDeviceInfo.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2016 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 ANDROID_MEDIA_MIDI_DEVICE_INFO_H
-#define ANDROID_MEDIA_MIDI_DEVICE_INFO_H
-
-#include <binder/Parcelable.h>
-#include <binder/PersistableBundle.h>
-#include <utils/String16.h>
-#include <utils/Vector.h>
-
-namespace android {
-namespace media {
-namespace midi {
-
-class MidiDeviceInfo : public Parcelable {
-public:
- MidiDeviceInfo() = default;
- virtual ~MidiDeviceInfo() = default;
- MidiDeviceInfo(const MidiDeviceInfo& midiDeviceInfo) = default;
-
- status_t writeToParcel(Parcel* parcel) const override;
- status_t readFromParcel(const Parcel* parcel) override;
-
- int getType() const { return mType; }
- int getUid() const { return mId; }
- bool isPrivate() const { return mIsPrivate; }
- const Vector<String16>& getInputPortNames() const { return mInputPortNames; }
- const Vector<String16>& getOutputPortNames() const { return mOutputPortNames; }
- String16 getProperty(const char* propertyName);
-
- // The constants need to be kept in sync with MidiDeviceInfo.java
- enum {
- TYPE_USB = 1,
- TYPE_VIRTUAL = 2,
- TYPE_BLUETOOTH = 3,
- };
- static const char* const PROPERTY_NAME;
- static const char* const PROPERTY_MANUFACTURER;
- static const char* const PROPERTY_PRODUCT;
- static const char* const PROPERTY_VERSION;
- static const char* const PROPERTY_SERIAL_NUMBER;
- static const char* const PROPERTY_ALSA_CARD;
- static const char* const PROPERTY_ALSA_DEVICE;
-
- friend bool operator==(const MidiDeviceInfo& lhs, const MidiDeviceInfo& rhs);
- friend bool operator!=(const MidiDeviceInfo& lhs, const MidiDeviceInfo& rhs) {
- return !(lhs == rhs);
- }
-
-private:
- status_t readStringVector(
- const Parcel* parcel, Vector<String16> *vectorPtr, size_t defaultLength);
- status_t writeStringVector(Parcel* parcel, const Vector<String16>& vector) const;
-
- int32_t mType;
- int32_t mId;
- Vector<String16> mInputPortNames;
- Vector<String16> mOutputPortNames;
- os::PersistableBundle mProperties;
- bool mIsPrivate;
-};
-
-} // namespace midi
-} // namespace media
-} // namespace android
-
-#endif // ANDROID_MEDIA_MIDI_DEVICE_INFO_H
diff --git a/media/libmediaplayerservice/Android.bp b/media/libmediaplayerservice/Android.bp
index 6701017..5301f5c 100644
--- a/media/libmediaplayerservice/Android.bp
+++ b/media/libmediaplayerservice/Android.bp
@@ -7,6 +7,7 @@
"MediaPlayerService.cpp",
"MediaRecorderClient.cpp",
"MetadataRetrieverClient.cpp",
+ "StagefrightMetadataRetriever.cpp",
"StagefrightRecorder.cpp",
"TestPlayerStub.cpp",
],
@@ -23,6 +24,7 @@
"libcutils",
"libdatasource",
"libdl",
+ "libdrmframework",
"libgui",
"libhidlbase",
"liblog",
@@ -46,6 +48,7 @@
],
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 c157ede..1aae241 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
@@ -22,11 +22,11 @@
#include <utils/Log.h>
#include <cutils/properties.h>
-#include "include/FrameDecoder.h"
-#include "include/StagefrightMetadataRetriever.h"
+#include "StagefrightMetadataRetriever.h"
+#include "FrameDecoder.h"
-#include <datasource/DataSourceFactory.h>
-#include <datasource/FileSource.h>
+#include <datasource/PlayerServiceDataSourceFactory.h>
+#include <datasource/PlayerServiceFileSource.h>
#include <media/IMediaHTTPService.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
@@ -63,7 +63,8 @@
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 @@
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 0000000..71fa50b
--- /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 0000000..ef946e9
--- /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 <datasource/PlayerServiceDataSourceFactory.h>
+#include <datasource/PlayerServiceFileSource.h>
+#include <datasource/PlayerServiceMediaHTTP.h>
+#include <media/MediaHTTPConnection.h>
+#include <media/MediaHTTPService.h>
+
+namespace android {
+
+// static
+sp<PlayerServiceDataSourceFactory> PlayerServiceDataSourceFactory::sInstance;
+// static
+Mutex PlayerServiceDataSourceFactory::sInstanceLock;
+
+// static
+sp<PlayerServiceDataSourceFactory> PlayerServiceDataSourceFactory::getInstance() {
+ Mutex::Autolock l(sInstanceLock);
+ if (!sInstance) {
+ sInstance = new PlayerServiceDataSourceFactory();
+ }
+ return sInstance;
+}
+
+sp<DataSource> PlayerServiceDataSourceFactory::CreateMediaHTTP(
+ const sp<MediaHTTPService> &httpService) {
+ if (httpService == NULL) {
+ return NULL;
+ }
+
+ sp<MediaHTTPConnection> conn = httpService->makeHTTPConnection();
+ if (conn == NULL) {
+ ALOGE("Failed to make http connection from http service!");
+ return NULL;
+ } else {
+ return new PlayerServiceMediaHTTP(conn);
+ }
+}
+
+sp<DataSource> 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 0000000..1580891
--- /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 <utils/Log.h>
+
+#include <datasource/PlayerServiceFileSource.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <private/android_filesystem_config.h>
+
+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<DecryptHandle> 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<size_t>(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<size_t>(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<DrmManagerClient> drmClient(new DrmManagerClient());
+ sp<DecryptHandle> 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 0000000..0124720
--- /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 <utils/Log.h>
+
+#include <datasource/PlayerServiceMediaHTTP.h>
+
+#include <binder/IServiceManager.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/FoundationUtils.h>
+
+#include <media/MediaHTTPConnection.h>
+
+namespace android {
+
+PlayerServiceMediaHTTP::PlayerServiceMediaHTTP(const sp<MediaHTTPConnection> &conn)
+ : MediaHTTP(conn),
+ mDrmManagerClient(NULL) {
+}
+
+PlayerServiceMediaHTTP::~PlayerServiceMediaHTTP() {
+ clearDRMState_l();
+}
+
+// DRM...
+
+sp<DecryptHandle> 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 0000000..7d58c5c
--- /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 <datasource/DataSourceFactory.h>
+#include <media/DataSource.h>
+#include <sys/types.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+struct MediaHTTPService;
+class String8;
+struct HTTPBase;
+
+class PlayerServiceDataSourceFactory : public DataSourceFactory {
+public:
+ static sp<PlayerServiceDataSourceFactory> getInstance();
+ virtual sp<DataSource> CreateMediaHTTP(const sp<MediaHTTPService> &httpService);
+
+protected:
+ virtual sp<DataSource> CreateFileSource(const char *uri);
+
+private:
+ static sp<PlayerServiceDataSourceFactory> 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 0000000..08a013e
--- /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 <stdio.h>
+
+#include <datasource/FileSource.h>
+#include <media/stagefright/MediaErrors.h>
+#include <utils/threads.h>
+#include <drm/DrmManagerClient.h>
+
+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<DecryptHandle> 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<DecryptHandle> 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 0000000..0032cd7
--- /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 <datasource/MediaHTTP.h>
+#include <media/stagefright/foundation/AString.h>
+
+namespace android {
+
+struct MediaHTTPConnection;
+
+// MediaHTTP implementation which works on MediaPlayerService.
+// Supports OMA(forword-lock) stream.
+struct PlayerServiceMediaHTTP : public MediaHTTP {
+ PlayerServiceMediaHTTP(const sp<MediaHTTPConnection> &conn);
+
+protected:
+ virtual ~PlayerServiceMediaHTTP();
+
+ virtual sp<DecryptHandle> DrmInitialization(const char* mime);
+
+private:
+ sp<DecryptHandle> 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 19c8e76..c8f48a2 100644
--- a/media/libmediaplayerservice/nuplayer/Android.bp
+++ b/media/libmediaplayerservice/nuplayer/Android.bp
@@ -54,6 +54,10 @@
"libpowermanager",
],
+ static_libs: [
+ "libplayerservice_datasource",
+ ],
+
name: "libstagefright_nuplayer",
sanitize: {
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index e26f1e6..f17520a 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -23,8 +23,8 @@
#include "AnotherPacketSource.h"
#include <binder/IServiceManager.h>
#include <cutils/properties.h>
-#include <datasource/DataSourceFactory.h>
-#include <datasource/FileSource.h>
+#include <datasource/PlayerServiceDataSourceFactory.h>
+#include <datasource/PlayerServiceFileSource.h>
#include <datasource/HTTPBase.h>
#include <datasource/NuCachedSource2.h>
#include <media/DataSource.h>
@@ -385,7 +385,8 @@
if (!strncasecmp("http://", uri, 7) || !strncasecmp("https://", uri, 8)) {
sp<DataSource> 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 @@
mLock.unlock();
mDisconnectLock.unlock();
// This might take long time if connection has some issue.
- sp<DataSource> dataSource = DataSourceFactory::CreateFromURI(
- mHTTPService, uri, &mUriHeaders, &contentType,
- static_cast<HTTPBase *>(mHttpSource.get()));
+ sp<DataSource> dataSource = PlayerServiceDataSourceFactory::getInstance()
+ ->CreateFromURI(mHTTPService, uri, &mUriHeaders, &contentType,
+ static_cast<HTTPBase *>(mHttpSource.get()));
mDisconnectLock.lock();
mLock.lock();
if (!mDisconnected) {
@@ -411,7 +412,8 @@
}
} else {
if (property_get_bool("media.stagefright.extractremote", true) &&
- !FileSource::requiresDrm(mFd, mOffset, mLength, nullptr /* mime */)) {
+ !PlayerServiceFileSource::requiresDrm(
+ mFd, mOffset, mLength, nullptr /* mime */)) {
sp<IBinder> binder =
defaultServiceManager()->getService(String16("media.extractor"));
if (binder != nullptr) {
@@ -438,7 +440,7 @@
}
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 a6dbce3..59cc24b 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -161,7 +161,6 @@
"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 b89dcdf..66fb4b0 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -82,7 +82,7 @@
}
sp<DataSource> 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 7183dbd..68f1de9 100644
--- a/media/libstagefright/httplive/HTTPDownloader.cpp
+++ b/media/libstagefright/httplive/HTTPDownloader.cpp
@@ -21,8 +21,8 @@
#include "HTTPDownloader.h"
#include "M3UParser.h"
-#include <datasource/ClearMediaHTTP.h>
-#include <datasource/ClearFileSource.h>
+#include <datasource/MediaHTTP.h>
+#include <datasource/FileSource.h>
#include <media/DataSource.h>
#include <media/MediaHTTPConnection.h>
#include <media/MediaHTTPService.h>
@@ -38,7 +38,7 @@
HTTPDownloader::HTTPDownloader(
const sp<MediaHTTPService> &httpService,
const KeyedVector<String8, String8> &headers) :
- mHTTPDataSource(new ClearMediaHTTP(httpService->makeHTTPConnection())),
+ mHTTPDataSource(new MediaHTTP(httpService->makeHTTPConnection())),
mExtraHeaders(headers),
mDisconnecting(false) {
}
@@ -91,7 +91,7 @@
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 ee01d6c..6848a83 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -278,7 +278,7 @@
static sp<IMediaExtractor> CreateExtractorFromURI(const char *uri) {
sp<DataSource> 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 5bd218d..e236267 100644
--- a/media/libstagefright/rtsp/SDPLoader.cpp
+++ b/media/libstagefright/rtsp/SDPLoader.cpp
@@ -22,7 +22,7 @@
#include "ASessionDescription.h"
-#include <datasource/ClearMediaHTTP.h>
+#include <datasource/MediaHTTP.h>
#include <media/MediaHTTPConnection.h>
#include <media/MediaHTTPService.h>
#include <media/stagefright/foundation/ABuffer.h>
@@ -42,7 +42,7 @@
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 f6892e6..c1d4686 100644
--- a/media/ndk/NdkMediaDataSource.cpp
+++ b/media/ndk/NdkMediaDataSource.cpp
@@ -202,7 +202,7 @@
headers.add(key8, value8);
}
- sp<DataSource> source = DataSourceFactory::CreateFromURI(service, uri, &headers);
+ sp<DataSource> source = DataSourceFactory::getInstance()->CreateFromURI(service, uri, &headers);
if (source == NULL) {
ALOGE("AMediaDataSource_newUri source is null");
return NULL;
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/EncoderTest.java b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/EncoderTest.java
new file mode 100644
index 0000000..9db9c84
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/EncoderTest.java
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+package com.android.media.benchmark.tests;
+
+import android.content.Context;
+import android.media.MediaCodec;
+import android.media.MediaFormat;
+import android.util.Log;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.media.benchmark.R;
+import com.android.media.benchmark.library.CodecUtils;
+import com.android.media.benchmark.library.Decoder;
+import com.android.media.benchmark.library.Encoder;
+import com.android.media.benchmark.library.Extractor;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.nio.ByteBuffer;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+
+@RunWith(Parameterized.class)
+public class EncoderTest {
+ private static final Context mContext =
+ InstrumentationRegistry.getInstrumentation().getTargetContext();
+ private static final String mInputFilePath = mContext.getString(R.string.input_file_path);
+ private static final String mOutputFilePath = mContext.getString(R.string.output_file_path);
+ private static final String TAG = "EncoderTest";
+ private static final long PER_TEST_TIMEOUT_MS = 120000;
+ private static final boolean DEBUG = false;
+ private static final boolean WRITE_OUTPUT = false;
+ private static final int ENCODE_DEFAULT_FRAME_RATE = 25;
+ private static final int ENCODE_DEFAULT_BIT_RATE = 8000000 /* 8 Mbps */;
+ private static final int ENCODE_MIN_BIT_RATE = 600000 /* 600 Kbps */;
+
+ private String mInputFile;
+
+ @Parameterized.Parameters
+ public static Collection<Object[]> inputFiles() {
+ return Arrays.asList(new Object[][]{
+ // Audio Test
+ {"bbb_44100hz_2ch_128kbps_aac_30sec.mp4"},
+ {"bbb_8000hz_1ch_8kbps_amrnb_30sec.3gp"},
+ {"bbb_16000hz_1ch_9kbps_amrwb_30sec.3gp"},
+ {"bbb_44100hz_2ch_600kbps_flac_30sec.mp4"},
+ {"bbb_48000hz_2ch_100kbps_opus_30sec.webm"},
+ // Video Test
+ {"crowd_1920x1080_25fps_4000kbps_vp8.webm"},
+ {"crowd_1920x1080_25fps_6700kbps_h264.ts"},
+ {"crowd_1920x1080_25fps_4000kbps_h265.mkv"},
+ {"crowd_1920x1080_25fps_4000kbps_vp9.webm"},
+ {"crowd_176x144_25fps_6000kbps_mpeg4.mp4"},
+ {"crowd_176x144_25fps_6000kbps_h263.3gp"}});
+ }
+
+ public EncoderTest(String inputFileName) {
+ this.mInputFile = inputFileName;
+ }
+
+ @Test(timeout = PER_TEST_TIMEOUT_MS)
+ public void sampleEncoderTest() throws Exception {
+ int status;
+ int frameSize;
+
+ //Parameters for video
+ int width = 0;
+ int height = 0;
+ int profile = 0;
+ int level = 0;
+ int frameRate = 0;
+
+ //Parameters for audio
+ int bitRate = 0;
+ int sampleRate = 0;
+ int numChannels = 0;
+
+ File inputFile = new File(mInputFilePath + mInputFile);
+ if (inputFile.exists()) {
+ FileInputStream fileInput = new FileInputStream(inputFile);
+ FileDescriptor fileDescriptor = fileInput.getFD();
+ Extractor extractor = new Extractor();
+ int trackCount = extractor.setUpExtractor(fileDescriptor);
+ if (trackCount <= 0) {
+ Log.e(TAG, "Extraction failed. No tracks for file: " + mInputFile);
+ return;
+ }
+ ArrayList<ByteBuffer> inputBuffer = new ArrayList<>();
+ ArrayList<MediaCodec.BufferInfo> frameInfo = new ArrayList<>();
+ for (int currentTrack = 0; currentTrack < trackCount; currentTrack++) {
+ extractor.selectExtractorTrack(currentTrack);
+ MediaFormat format = extractor.getFormat(currentTrack);
+ // Get samples from extractor
+ int sampleSize;
+ do {
+ sampleSize = extractor.getFrameSample();
+ MediaCodec.BufferInfo bufInfo = new MediaCodec.BufferInfo();
+ MediaCodec.BufferInfo info = extractor.getBufferInfo();
+ ByteBuffer dataBuffer = ByteBuffer.allocate(info.size);
+ dataBuffer.put(extractor.getFrameBuffer().array(), 0, info.size);
+ bufInfo.set(info.offset, info.size, info.presentationTimeUs, info.flags);
+ inputBuffer.add(dataBuffer);
+ frameInfo.add(bufInfo);
+ if (DEBUG) {
+ Log.d(TAG, "Extracted bufInfo: flag = " + bufInfo.flags + " timestamp = " +
+ bufInfo.presentationTimeUs + " size = " + bufInfo.size);
+ }
+ } while (sampleSize > 0);
+
+ int tid = android.os.Process.myTid();
+ File decodedFile = new File(mContext.getFilesDir() + "/decoder_" + tid + ".out");
+ FileOutputStream decodeOutputStream = new FileOutputStream(decodedFile);
+ Decoder decoder = new Decoder();
+ decoder.setupDecoder(decodeOutputStream);
+ status = decoder.decode(inputBuffer, frameInfo, false, format, "");
+ if (status == 0) {
+ Log.i(TAG, "Decoding complete.");
+ } else {
+ Log.e(TAG, "Decode returned error. Encoding did not take place." + status);
+ return;
+ }
+ decoder.deInitCodec();
+ extractor.unselectExtractorTrack(currentTrack);
+ inputBuffer.clear();
+ frameInfo.clear();
+ if (decodeOutputStream != null) {
+ decodeOutputStream.close();
+ }
+ String mime = format.getString(MediaFormat.KEY_MIME);
+ ArrayList<String> mediaCodecs = CodecUtils.selectCodecs(mime, true);
+ if (mediaCodecs.size() <= 0) {
+ Log.e(TAG, "No suitable codecs found for file: " + mInputFile + " track : " +
+ currentTrack + " mime: " + mime);
+ return;
+ }
+ Boolean[] encodeMode = {true, false};
+ /* Encoding the decoder's output */
+ for (Boolean asyncMode : encodeMode) {
+ for (String codecName : mediaCodecs) {
+ FileOutputStream encodeOutputStream = null;
+ if (WRITE_OUTPUT) {
+ File outEncodeFile = new File(mOutputFilePath + "encoder.out");
+ if (outEncodeFile.exists()) {
+ if (!outEncodeFile.delete()) {
+ Log.e(TAG, "Unable to delete existing file" +
+ decodedFile.toString());
+ }
+ }
+ if (outEncodeFile.createNewFile()) {
+ encodeOutputStream = new FileOutputStream(outEncodeFile);
+ } else {
+ Log.e(TAG, "Unable to create file to write encoder output: " +
+ outEncodeFile.toString());
+ }
+ }
+ File rawFile =
+ new File(mContext.getFilesDir() + "/decoder_" + tid + ".out");
+ if (rawFile.exists()) {
+ if (DEBUG) {
+ Log.i(TAG, "Path of decoded input file: " + rawFile.toString());
+ }
+ FileInputStream eleStream = new FileInputStream(rawFile);
+ if (mime.startsWith("video/")) {
+ width = format.getInteger(MediaFormat.KEY_WIDTH);
+ height = format.getInteger(MediaFormat.KEY_HEIGHT);
+ if (format.containsKey(MediaFormat.KEY_FRAME_RATE)) {
+ frameRate = format.getInteger(MediaFormat.KEY_FRAME_RATE);
+ } else if (frameRate <= 0) {
+ frameRate = ENCODE_DEFAULT_FRAME_RATE;
+ }
+ if (format.containsKey(MediaFormat.KEY_BIT_RATE)) {
+ bitRate = format.getInteger(MediaFormat.KEY_BIT_RATE);
+ } else if (bitRate <= 0) {
+ if (mime.contains("video/3gpp") ||
+ mime.contains("video/mp4v-es")) {
+ bitRate = ENCODE_MIN_BIT_RATE;
+ } else {
+ bitRate = ENCODE_DEFAULT_BIT_RATE;
+ }
+ }
+ if (format.containsKey(MediaFormat.KEY_PROFILE)) {
+ profile = format.getInteger(MediaFormat.KEY_PROFILE);
+ }
+ if (format.containsKey(MediaFormat.KEY_PROFILE)) {
+ level = format.getInteger(MediaFormat.KEY_LEVEL);
+ }
+ } else {
+ sampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
+ numChannels = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
+ bitRate = sampleRate * numChannels * 16;
+ }
+ /*Setup Encode Format*/
+ MediaFormat encodeFormat;
+ if (mime.startsWith("video/")) {
+ frameSize = width * height * 3 / 2;
+ encodeFormat = MediaFormat.createVideoFormat(mime, width, height);
+ encodeFormat.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate);
+ encodeFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitRate);
+ encodeFormat.setInteger(MediaFormat.KEY_PROFILE, profile);
+ encodeFormat.setInteger(MediaFormat.KEY_LEVEL, level);
+ encodeFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1);
+ encodeFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, frameSize);
+ } else {
+ encodeFormat = MediaFormat
+ .createAudioFormat(mime, sampleRate, numChannels);
+ encodeFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitRate);
+ frameSize = 4096;
+ }
+ Encoder encoder = new Encoder();
+ encoder.setupEncoder(encodeOutputStream, eleStream);
+ status = encoder.encode(codecName, encodeFormat, mime, frameRate,
+ sampleRate, frameSize, asyncMode);
+ encoder.deInitEncoder();
+ if (status == 0) {
+ encoder.dumpStatistics(mInputFile + "with " + codecName + " for " +
+ "aSyncMode = " + asyncMode, extractor.getClipDuration());
+ Log.i(TAG, "Encoding complete for file: " + mInputFile +
+ " with codec: " + codecName + " for aSyncMode = " +
+ asyncMode);
+ } else {
+ Log.e(TAG,
+ codecName + " encoder returned error " + status + " for " +
+ "file:" + " " + mInputFile);
+ }
+ encoder.resetEncoder();
+ eleStream.close();
+ if (encodeOutputStream != null) {
+ encodeOutputStream.close();
+ }
+ }
+ }
+ }
+ //Cleanup temporary input file
+ if (decodedFile.exists()) {
+ if (decodedFile.delete()) {
+ Log.i(TAG, "Successfully deleted decoded file");
+ } else {
+ Log.e(TAG, "Unable to delete decoded file");
+ }
+ }
+ }
+ extractor.deinitExtractor();
+ fileInput.close();
+ } else {
+ Log.w(TAG, "Warning: Test Skipped. Cannot find " + mInputFile + " in directory " +
+ mInputFilePath);
+ }
+ }
+}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Encoder.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Encoder.java
new file mode 100644
index 0000000..03db294
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Encoder.java
@@ -0,0 +1,349 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+package com.android.media.benchmark.library;
+
+import android.media.MediaCodec;
+import android.media.MediaCodec.CodecException;
+import android.media.MediaFormat;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+public class Encoder {
+ private static final int ENCODE_DEFAULT_MAX_INPUT_SIZE = 3840;
+ private static final String TAG = "Encoder";
+ private static final boolean DEBUG = false;
+ private static final int kQueueDequeueTimeoutUs = 1000;
+
+ private final Object mLock = new Object();
+ private MediaCodec mCodec;
+ private String mMime;
+ private Stats mStats;
+
+ private int mOffset;
+ private int mFrameSize;
+ private int mNumInputFrame;
+ private int mNumFrames;
+ private int mFrameRate;
+ private int mSampleRate;
+ private long mInputBufferSize;
+
+ private boolean mSawInputEOS;
+ private boolean mSawOutputEOS;
+ private boolean mSignalledError;
+
+ private FileInputStream mInputStream;
+ private FileOutputStream mOutputStream;
+
+ public Encoder() {
+ mStats = new Stats();
+ mNumInputFrame = 0;
+ mSawInputEOS = false;
+ mSawOutputEOS = false;
+ mSignalledError = false;
+ }
+
+ /**
+ * Setup of encoder
+ *
+ * @param encoderOutputStream Will dump the encoder output in this stream if not null.
+ * @param fileInputStream Will read the decoded output from this stream
+ */
+ public void setupEncoder(FileOutputStream encoderOutputStream,
+ FileInputStream fileInputStream) {
+ this.mInputStream = fileInputStream;
+ this.mOutputStream = encoderOutputStream;
+ }
+
+ private MediaCodec createCodec(String codecName, String mime) throws IOException {
+ try {
+ MediaCodec codec;
+ if (codecName.isEmpty()) {
+ Log.i(TAG, "Mime type: " + mime);
+ if (mime != null) {
+ codec = MediaCodec.createEncoderByType(mime);
+ Log.i(TAG, "Encoder created for mime type " + mime);
+ return codec;
+ } else {
+ Log.e(TAG, "Mime type is null, please specify a mime type to create encoder");
+ return null;
+ }
+ } else {
+ codec = MediaCodec.createByCodecName(codecName);
+ Log.i(TAG, "Encoder created with codec name: " + codecName + " and mime: " + mime);
+ return codec;
+ }
+ } catch (IllegalArgumentException ex) {
+ ex.printStackTrace();
+ Log.e(TAG, "Failed to create encoder for " + codecName + " mime: " + mime);
+ return null;
+ }
+ }
+
+ /**
+ * Encodes the given raw input file and measures the performance of encode operation,
+ * provided a valid list of parameters are passed as inputs.
+ *
+ * @param codecName Will create the encoder with codecName
+ * @param mime For creating encode format
+ * @param encodeFormat Format of the output data
+ * @param frameSize Size of the frame
+ * @param asyncMode Will run on async implementation if true
+ * @return 0 if encode was successful , -1 for fail, -2 for encoder not created
+ * @throws IOException If the codec cannot be created.
+ */
+ public int encode(String codecName, MediaFormat encodeFormat, String mime, int frameRate,
+ int sampleRate, int frameSize, boolean asyncMode) throws IOException {
+ mInputBufferSize = mInputStream.getChannel().size();
+ mMime = mime;
+ mOffset = 0;
+ mFrameRate = frameRate;
+ mSampleRate = sampleRate;
+ long sTime = mStats.getCurTime();
+ mCodec = createCodec(codecName, mime);
+ if (mCodec == null) {
+ return -2;
+ }
+ /*Configure Codec*/
+ try {
+ mCodec.configure(encodeFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
+ } catch (IllegalArgumentException | IllegalStateException | MediaCodec.CryptoException e) {
+ Log.e(TAG, "Failed to configure " + mCodec.getName() + " encoder.");
+ e.printStackTrace();
+ return -2;
+ }
+ if (mMime.startsWith("video/")) {
+ mFrameSize = frameSize;
+ } else {
+ int maxInputSize = ENCODE_DEFAULT_MAX_INPUT_SIZE;
+ MediaFormat format = mCodec.getInputFormat();
+ if (format.containsKey(MediaFormat.KEY_MAX_INPUT_SIZE)) {
+ maxInputSize = format.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE);
+ }
+ mFrameSize = frameSize;
+ if (mFrameSize > maxInputSize && maxInputSize > 0) {
+ mFrameSize = maxInputSize;
+ }
+ }
+ mNumFrames = (int) ((mInputBufferSize + mFrameSize - 1) / mFrameSize);
+ if (asyncMode) {
+ mCodec.setCallback(new MediaCodec.Callback() {
+ @Override
+ public void onInputBufferAvailable(@NonNull MediaCodec mediaCodec,
+ int inputBufferId) {
+ try {
+ mStats.addInputTime();
+ onInputAvailable(mediaCodec, inputBufferId);
+ } catch (Exception e) {
+ e.printStackTrace();
+ Log.e(TAG, e.toString());
+ }
+ }
+
+ @Override
+ public void onOutputBufferAvailable(@NonNull MediaCodec mediaCodec,
+ int outputBufferId,
+ @NonNull MediaCodec.BufferInfo bufferInfo) {
+ mStats.addOutputTime();
+ onOutputAvailable(mediaCodec, outputBufferId, bufferInfo);
+ if (mSawOutputEOS) {
+ Log.i(TAG, "Saw output EOS");
+ synchronized (mLock) { mLock.notify(); }
+ }
+ }
+
+ @Override
+ public void onError(@NonNull MediaCodec mediaCodec, @NonNull CodecException e) {
+ mediaCodec.stop();
+ mediaCodec.release();
+ Log.e(TAG, "CodecError: " + e.toString());
+ e.printStackTrace();
+ }
+
+ @Override
+ public void onOutputFormatChanged(@NonNull MediaCodec mediaCodec,
+ @NonNull MediaFormat format) {
+ Log.i(TAG, "Output format changed. Format: " + format.toString());
+ }
+ });
+ }
+ mCodec.start();
+ long eTime = mStats.getCurTime();
+ mStats.setInitTime(mStats.getTimeDiff(sTime, eTime));
+ mStats.setStartTime();
+ if (asyncMode) {
+ try {
+ synchronized (mLock) { mLock.wait(); }
+ if (mSignalledError) {
+ return -1;
+ }
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ } else {
+ while (!mSawOutputEOS && !mSignalledError) {
+ /* Queue input data */
+ if (!mSawInputEOS) {
+ int inputBufferId = mCodec.dequeueInputBuffer(kQueueDequeueTimeoutUs);
+ if (inputBufferId < 0 && inputBufferId != MediaCodec.INFO_TRY_AGAIN_LATER) {
+ Log.e(TAG, "MediaCodec.dequeueInputBuffer " + "returned invalid index : " +
+ inputBufferId);
+ return -1;
+ }
+ mStats.addInputTime();
+ onInputAvailable(mCodec, inputBufferId);
+ }
+ /* Dequeue output data */
+ MediaCodec.BufferInfo outputBufferInfo = new MediaCodec.BufferInfo();
+ int outputBufferId =
+ mCodec.dequeueOutputBuffer(outputBufferInfo, kQueueDequeueTimeoutUs);
+ if (outputBufferId < 0) {
+ if (outputBufferId == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
+ MediaFormat outFormat = mCodec.getOutputFormat();
+ Log.i(TAG, "Output format changed. Format: " + outFormat.toString());
+ } else if (outputBufferId != MediaCodec.INFO_TRY_AGAIN_LATER) {
+ Log.e(TAG, "MediaCodec.dequeueOutputBuffer" + " returned invalid index " +
+ outputBufferId);
+ return -1;
+ }
+ } else {
+ mStats.addOutputTime();
+ if (DEBUG) {
+ Log.d(TAG, "Dequeue O/P buffer with BufferID " + outputBufferId);
+ }
+ onOutputAvailable(mCodec, outputBufferId, outputBufferInfo);
+ }
+ }
+ }
+ return 0;
+ }
+
+ private void onOutputAvailable(MediaCodec mediaCodec, int outputBufferId,
+ MediaCodec.BufferInfo outputBufferInfo) {
+ if (mSawOutputEOS || outputBufferId < 0) {
+ if (mSawOutputEOS) {
+ Log.i(TAG, "Saw output EOS");
+ }
+ return;
+ }
+ ByteBuffer outputBuffer = mediaCodec.getOutputBuffer(outputBufferId);
+ if (mOutputStream != null) {
+ try {
+
+ byte[] bytesOutput = new byte[outputBuffer.remaining()];
+ outputBuffer.get(bytesOutput);
+ mOutputStream.write(bytesOutput);
+ } catch (IOException e) {
+ e.printStackTrace();
+ Log.d(TAG, "Error Dumping File: Exception " + e.toString());
+ return;
+ }
+ }
+ mStats.addFrameSize(outputBuffer.remaining());
+ mediaCodec.releaseOutputBuffer(outputBufferId, false);
+ mSawOutputEOS = (outputBufferInfo.flags == MediaCodec.BUFFER_FLAG_END_OF_STREAM);
+ }
+
+ private void onInputAvailable(MediaCodec mediaCodec, int inputBufferId) throws IOException {
+ if (mSawOutputEOS || inputBufferId < 0) {
+ if (mSawOutputEOS) {
+ Log.i(TAG, "Saw input EOS");
+ }
+ return;
+ }
+ if (mInputBufferSize < mOffset) {
+ Log.e(TAG, "Out of bound access of input buffer");
+ mSignalledError = true;
+ return;
+ }
+ ByteBuffer inputBuffer = mCodec.getInputBuffer(inputBufferId);
+ if (inputBuffer == null) {
+ mSignalledError = true;
+ return;
+ }
+ int bufSize = inputBuffer.capacity();
+ int bytesRead = mFrameSize;
+ if (mInputBufferSize - mOffset < mFrameSize) {
+ bytesRead = (int) (mInputBufferSize - mOffset);
+ }
+ if (bufSize < bytesRead) {
+ mSignalledError = true;
+ return;
+ }
+ byte[] inputArray = new byte[bytesRead];
+ mInputStream.read(inputArray, 0, bytesRead);
+ inputBuffer.put(inputArray);
+ int flag = 0;
+ if (mNumInputFrame >= mNumFrames - 1 || bytesRead == 0) {
+ Log.i(TAG, "Sending EOS on input last frame");
+ mSawInputEOS = true;
+ flag = MediaCodec.BUFFER_FLAG_END_OF_STREAM;
+ }
+ int presentationTimeUs;
+ if (mMime.startsWith("video/")) {
+ presentationTimeUs = mNumInputFrame * (1000000 / mFrameRate);
+ } else {
+ presentationTimeUs = mNumInputFrame * mFrameSize * 1000000 / mSampleRate;
+ }
+ mediaCodec.queueInputBuffer(inputBufferId, 0, bytesRead, presentationTimeUs, flag);
+ mNumInputFrame++;
+ mOffset += bytesRead;
+ }
+
+ /**
+ * Stops the codec and releases codec resources.
+ */
+ public void deInitEncoder() {
+ long sTime = mStats.getCurTime();
+ if (mCodec != null) {
+ mCodec.stop();
+ mCodec.release();
+ mCodec = null;
+ }
+ long eTime = mStats.getCurTime();
+ mStats.setDeInitTime(mStats.getTimeDiff(sTime, eTime));
+ }
+
+ /**
+ * Prints out the statistics in the information log
+ *
+ * @param inputReference The operation being performed, in this case encode
+ * @param durationUs Duration of the clip in microseconds
+ */
+ public void dumpStatistics(String inputReference, long durationUs) {
+ String operation = "encode";
+ mStats.dumpStatistics(operation, inputReference, durationUs);
+ }
+
+ /**
+ * Resets the stats
+ */
+ public void resetEncoder() {
+ mOffset = 0;
+ mInputBufferSize = 0;
+ mNumInputFrame = 0;
+ mSawInputEOS = false;
+ mSawOutputEOS = false;
+ mSignalledError = false;
+ mStats.reset();
+ }
+}
diff --git a/media/tests/benchmark/README.md b/media/tests/benchmark/README.md
index 1c1ef4f..487ddb8 100644
--- a/media/tests/benchmark/README.md
+++ b/media/tests/benchmark/README.md
@@ -99,7 +99,6 @@
adb shell am instrument -w -r -e class 'com.android.media.benchmark.tests.ExtractorTest' com.android.media.benchmark/androidx.test.runner.AndroidJUnitRunner
```
-
## Decoder
The test decodes input stream and benchmarks the decoders available in SDK.
@@ -107,11 +106,17 @@
adb shell am instrument -w -r -e class 'com.android.media.benchmark.tests.DecoderTest' com.android.media.benchmark/androidx.test.runner.AndroidJUnitRunner
```
-
## Muxer
The test muxes elementary stream and benchmarks different writers available in SDK.
```
adb shell am instrument -w -r -e class 'com.android.media.benchmark.tests.MuxerTest' com.android.media.benchmark/androidx.test.runner.AndroidJUnitRunner
+```
+
+## Encoder
+
+The test encodes input stream and benchmarks the encoders available in SDK.
+```
+adb shell am instrument -w -r -e class 'com.android.media.benchmark.tests.EncoderTest' com.android.media.benchmark/androidx.test.runner.AndroidJUnitRunner
```
diff --git a/services/mediaextractor/MediaExtractorService.cpp b/services/mediaextractor/MediaExtractorService.cpp
index ac6b771..6239fb2 100644
--- a/services/mediaextractor/MediaExtractorService.cpp
+++ b/services/mediaextractor/MediaExtractorService.cpp
@@ -55,7 +55,7 @@
sp<IDataSource> MediaExtractorService::makeIDataSource(int fd, int64_t offset, int64_t length)
{
- sp<DataSource> source = DataSourceFactory::CreateFromFd(fd, offset, length);
+ sp<DataSource> source = DataSourceFactory::getInstance()->CreateFromFd(fd, offset, length);
return CreateIDataSourceFromDataSource(source);
}