summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp
diff options
context:
space:
mode:
authorAndreas Huber <andih@google.com>2011-03-08 15:59:28 -0800
committerAndreas Huber <andih@google.com>2011-03-09 10:14:46 -0800
commit1156dc913a5ba7b2bc86489468d4914430f03d14 (patch)
tree351803a481df1784b789fdcdfa13cbc9b30a0a12 /media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp
parent271151e65fdc289514317b6e4e1b8805e6c647e1 (diff)
downloadframeworks_av-1156dc913a5ba7b2bc86489468d4914430f03d14.zip
frameworks_av-1156dc913a5ba7b2bc86489468d4914430f03d14.tar.gz
frameworks_av-1156dc913a5ba7b2bc86489468d4914430f03d14.tar.bz2
An HTTP datasource for stagefright using the chromium code.
Use of this new datasource is now the default unless overwritten by adb shell setprop media.stagefright.use-chromium false Change-Id: I156a8eb9a1fff1cb537b4aec6cf3e8e6052be81e
Diffstat (limited to 'media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp')
-rw-r--r--media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp327
1 files changed, 327 insertions, 0 deletions
diff --git a/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp b/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp
new file mode 100644
index 0000000..e3a9829
--- /dev/null
+++ b/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ChromiumHTTPDataSource"
+#include <media/stagefright/foundation/ADebug.h>
+
+#include "include/ChromiumHTTPDataSource.h"
+
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/MediaErrors.h>
+
+#include "support.h"
+
+namespace android {
+
+ChromiumHTTPDataSource::ChromiumHTTPDataSource(uint32_t flags)
+ : mFlags(flags),
+ mState(DISCONNECTED),
+ mDelegate(new SfDelegate),
+ mCurrentOffset(0),
+ mIOResult(OK),
+ mContentSize(-1),
+ mNumBandwidthHistoryItems(0),
+ mTotalTransferTimeUs(0),
+ mTotalTransferBytes(0),
+ mDecryptHandle(NULL),
+ mDrmManagerClient(NULL) {
+ mDelegate->setOwner(this);
+}
+
+ChromiumHTTPDataSource::~ChromiumHTTPDataSource() {
+ disconnect();
+
+ delete mDelegate;
+ mDelegate = NULL;
+
+ if (mDrmManagerClient != NULL) {
+ delete mDrmManagerClient;
+ mDrmManagerClient = NULL;
+ }
+}
+
+status_t ChromiumHTTPDataSource::connect(
+ const char *uri,
+ const KeyedVector<String8, String8> *headers,
+ off64_t offset) {
+ Mutex::Autolock autoLock(mLock);
+
+ return connect_l(uri, headers, offset);
+}
+
+status_t ChromiumHTTPDataSource::connect_l(
+ const char *uri,
+ const KeyedVector<String8, String8> *headers,
+ off64_t offset) {
+ if (mState != DISCONNECTED) {
+ disconnect_l();
+ }
+
+ if (!(mFlags & kFlagIncognito)) {
+ LOG_PRI(ANDROID_LOG_INFO, LOG_TAG, "connect to %s @%lld", uri, offset);
+ } else {
+ LOG_PRI(ANDROID_LOG_INFO, LOG_TAG,
+ "connect to <URL suppressed> @%lld", offset);
+ }
+
+ mURI = uri;
+
+ if (headers != NULL) {
+ mHeaders = *headers;
+ } else {
+ mHeaders.clear();
+ }
+
+ mState = CONNECTING;
+ mContentSize = -1;
+ mCurrentOffset = offset;
+
+ mDelegate->initiateConnection(mURI.c_str(), &mHeaders, offset);
+
+ while (mState == CONNECTING) {
+ mCondition.wait(mLock);
+ }
+
+ return mState == CONNECTED ? OK : mIOResult;
+}
+
+void ChromiumHTTPDataSource::onConnectionEstablished(int64_t contentSize) {
+ Mutex::Autolock autoLock(mLock);
+ mState = CONNECTED;
+ mContentSize = (contentSize < 0) ? -1 : contentSize + mCurrentOffset;
+ mCondition.broadcast();
+}
+
+void ChromiumHTTPDataSource::onConnectionFailed(status_t err) {
+ Mutex::Autolock autoLock(mLock);
+ mState = DISCONNECTED;
+ mCondition.broadcast();
+
+ mURI.clear();
+
+ mIOResult = err;
+
+ clearDRMState_l();
+}
+
+void ChromiumHTTPDataSource::disconnect() {
+ Mutex::Autolock autoLock(mLock);
+ disconnect_l();
+}
+
+void ChromiumHTTPDataSource::disconnect_l() {
+ if (mState == DISCONNECTED) {
+ return;
+ }
+
+ mState = DISCONNECTING;
+ mIOResult = -EINTR;
+
+ mDelegate->initiateDisconnect();
+
+ while (mState == DISCONNECTING) {
+ mCondition.wait(mLock);
+ }
+
+ CHECK_EQ((int)mState, (int)DISCONNECTED);
+}
+
+status_t ChromiumHTTPDataSource::initCheck() const {
+ Mutex::Autolock autoLock(mLock);
+
+ return mState == CONNECTED ? OK : NO_INIT;
+}
+
+ssize_t ChromiumHTTPDataSource::readAt(off64_t offset, void *data, size_t size) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mState != CONNECTED) {
+ return ERROR_NOT_CONNECTED;
+ }
+
+ if (offset != mCurrentOffset) {
+ AString tmp = mURI;
+ KeyedVector<String8, String8> tmpHeaders = mHeaders;
+
+ disconnect_l();
+
+ status_t err = connect_l(tmp.c_str(), &tmpHeaders, offset);
+
+ if (err != OK) {
+ return err;
+ }
+ }
+
+ mState = READING;
+
+ int64_t startTimeUs = ALooper::GetNowUs();
+
+ mDelegate->initiateRead(data, size);
+
+ while (mState == READING) {
+ mCondition.wait(mLock);
+ }
+
+ if (mIOResult < OK) {
+ return mIOResult;
+ }
+
+ if (mState == CONNECTED) {
+ int64_t delayUs = ALooper::GetNowUs() - startTimeUs;
+
+ // The read operation was successful, mIOResult contains
+ // the number of bytes read.
+ addBandwidthMeasurement_l(mIOResult, delayUs);
+
+ mCurrentOffset += mIOResult;
+ return mIOResult;
+ }
+
+ return ERROR_IO;
+}
+
+void ChromiumHTTPDataSource::onReadCompleted(ssize_t size) {
+ Mutex::Autolock autoLock(mLock);
+
+ mIOResult = size;
+
+ if (mState == READING) {
+ mState = CONNECTED;
+ mCondition.broadcast();
+ }
+}
+
+status_t ChromiumHTTPDataSource::getSize(off64_t *size) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mContentSize < 0) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ *size = mContentSize;
+
+ return OK;
+}
+
+uint32_t ChromiumHTTPDataSource::flags() {
+ return kWantsPrefetching;
+}
+
+// static
+void ChromiumHTTPDataSource::InitiateRead(
+ ChromiumHTTPDataSource *me, void *data, size_t size) {
+ me->initiateRead(data, size);
+}
+
+void ChromiumHTTPDataSource::initiateRead(void *data, size_t size) {
+ mDelegate->initiateRead(data, size);
+}
+
+void ChromiumHTTPDataSource::onDisconnectComplete() {
+ Mutex::Autolock autoLock(mLock);
+ CHECK_EQ((int)mState, (int)DISCONNECTING);
+
+ mState = DISCONNECTED;
+ mURI.clear();
+
+ mCondition.broadcast();
+
+ clearDRMState_l();
+}
+
+void ChromiumHTTPDataSource::addBandwidthMeasurement_l(
+ size_t numBytes, int64_t delayUs) {
+ BandwidthEntry entry;
+ entry.mDelayUs = delayUs;
+ entry.mNumBytes = numBytes;
+ mTotalTransferTimeUs += delayUs;
+ mTotalTransferBytes += numBytes;
+
+ mBandwidthHistory.push_back(entry);
+ if (++mNumBandwidthHistoryItems > 100) {
+ BandwidthEntry *entry = &*mBandwidthHistory.begin();
+ mTotalTransferTimeUs -= entry->mDelayUs;
+ mTotalTransferBytes -= entry->mNumBytes;
+ mBandwidthHistory.erase(mBandwidthHistory.begin());
+ --mNumBandwidthHistoryItems;
+ }
+}
+
+bool ChromiumHTTPDataSource::estimateBandwidth(int32_t *bandwidth_bps) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mNumBandwidthHistoryItems < 2) {
+ return false;
+ }
+
+ *bandwidth_bps = ((double)mTotalTransferBytes * 8E6 / mTotalTransferTimeUs);
+
+ return true;
+}
+
+DecryptHandle *ChromiumHTTPDataSource::DrmInitialization() {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mDrmManagerClient == NULL) {
+ mDrmManagerClient = new DrmManagerClient();
+ }
+
+ if (mDrmManagerClient == NULL) {
+ return NULL;
+ }
+
+ if (mDecryptHandle == NULL) {
+ /* Note if redirect occurs, mUri is the redirect uri instead of the
+ * original one
+ */
+ mDecryptHandle = mDrmManagerClient->openDecryptSession(
+ String8(mURI.c_str()));
+ }
+
+ if (mDecryptHandle == NULL) {
+ delete mDrmManagerClient;
+ mDrmManagerClient = NULL;
+ }
+
+ return mDecryptHandle;
+}
+
+void ChromiumHTTPDataSource::getDrmInfo(
+ DecryptHandle **handle, DrmManagerClient **client) {
+ Mutex::Autolock autoLock(mLock);
+
+ *handle = mDecryptHandle;
+ *client = mDrmManagerClient;
+}
+
+String8 ChromiumHTTPDataSource::getUri() {
+ Mutex::Autolock autoLock(mLock);
+
+ return String8(mURI.c_str());
+}
+
+void ChromiumHTTPDataSource::clearDRMState_l() {
+ if (mDecryptHandle != NULL) {
+ // To release mDecryptHandle
+ CHECK(mDrmManagerClient);
+ mDrmManagerClient->closeDecryptSession(mDecryptHandle);
+ mDecryptHandle = NULL;
+ }
+}
+
+} // namespace android
+