Merge "Using widevine:// to stream adaptive bitrate wvm content no longer" into honeycomb-mr2
This commit is contained in:
@@ -24,10 +24,12 @@
|
||||
|
||||
#include "include/ARTSPController.h"
|
||||
#include "include/AwesomePlayer.h"
|
||||
#include "include/DRMExtractor.h"
|
||||
#include "include/SoftwareRenderer.h"
|
||||
#include "include/NuCachedSource2.h"
|
||||
#include "include/ThrottledSource.h"
|
||||
#include "include/MPEG2TSExtractor.h"
|
||||
#include "include/WVMExtractor.h"
|
||||
|
||||
#include <binder/IPCThreadState.h>
|
||||
#include <binder/IServiceManager.h>
|
||||
@@ -447,6 +449,7 @@ void AwesomePlayer::reset_l() {
|
||||
|
||||
cancelPlayerEvents();
|
||||
|
||||
mWVMExtractor.clear();
|
||||
mCachedSource.clear();
|
||||
mAudioTrack.clear();
|
||||
mVideoTrack.clear();
|
||||
@@ -554,6 +557,11 @@ bool AwesomePlayer::getCachedDuration_l(int64_t *durationUs, bool *eos) {
|
||||
*durationUs = cachedDataRemaining * 8000000ll / bitrate;
|
||||
*eos = (finalStatus != OK);
|
||||
return true;
|
||||
} else if (mWVMExtractor != NULL) {
|
||||
status_t finalStatus;
|
||||
*durationUs = mWVMExtractor->getCachedDurationUs(&finalStatus);
|
||||
*eos = (finalStatus != OK);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -646,6 +654,30 @@ void AwesomePlayer::onBufferingUpdate() {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (mWVMExtractor != NULL) {
|
||||
status_t finalStatus;
|
||||
|
||||
int64_t cachedDurationUs
|
||||
= mWVMExtractor->getCachedDurationUs(&finalStatus);
|
||||
|
||||
bool eos = (finalStatus != OK);
|
||||
|
||||
if (eos) {
|
||||
if (finalStatus == ERROR_END_OF_STREAM) {
|
||||
notifyListener_l(MEDIA_BUFFERING_UPDATE, 100);
|
||||
}
|
||||
if (mFlags & PREPARING) {
|
||||
LOGV("cache has reached EOS, prepare is done.");
|
||||
finishAsyncPrepare_l();
|
||||
}
|
||||
} else {
|
||||
int percentage = 100.0 * (double)cachedDurationUs / mDurationUs;
|
||||
if (percentage > 100) {
|
||||
percentage = 100;
|
||||
}
|
||||
|
||||
notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage);
|
||||
}
|
||||
}
|
||||
|
||||
int64_t cachedDurationUs;
|
||||
@@ -1320,7 +1352,7 @@ void AwesomePlayer::onVideoEvent() {
|
||||
mVideoBuffer = NULL;
|
||||
}
|
||||
|
||||
if (mSeeking == SEEK && mCachedSource != NULL && mAudioSource != NULL
|
||||
if (mSeeking == SEEK && isStreamingHTTP() && mAudioSource != NULL
|
||||
&& !(mFlags & SEEK_PREVIEW)) {
|
||||
// We're going to seek the video source first, followed by
|
||||
// the audio source.
|
||||
@@ -1654,8 +1686,19 @@ status_t AwesomePlayer::prepareAsync_l() {
|
||||
status_t AwesomePlayer::finishSetDataSource_l() {
|
||||
sp<DataSource> dataSource;
|
||||
|
||||
bool isWidevineStreaming = false;
|
||||
if (!strncasecmp("widevine://", mUri.string(), 11)) {
|
||||
isWidevineStreaming = true;
|
||||
|
||||
String8 newURI = String8("http://");
|
||||
newURI.append(mUri.string() + 11);
|
||||
|
||||
mUri = newURI;
|
||||
}
|
||||
|
||||
if (!strncasecmp("http://", mUri.string(), 7)
|
||||
|| !strncasecmp("https://", mUri.string(), 8)) {
|
||||
|| !strncasecmp("https://", mUri.string(), 8)
|
||||
|| isWidevineStreaming) {
|
||||
mConnectingDataSource = new NuHTTPDataSource(
|
||||
(mFlags & INCOGNITO) ? NuHTTPDataSource::kFlagIncognito : 0);
|
||||
|
||||
@@ -1670,39 +1713,48 @@ status_t AwesomePlayer::finishSetDataSource_l() {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!isWidevineStreaming) {
|
||||
// The widevine extractor does its own caching.
|
||||
|
||||
#if 0
|
||||
mCachedSource = new NuCachedSource2(
|
||||
new ThrottledSource(
|
||||
mConnectingDataSource, 50 * 1024 /* bytes/sec */));
|
||||
mCachedSource = new NuCachedSource2(
|
||||
new ThrottledSource(
|
||||
mConnectingDataSource, 50 * 1024 /* bytes/sec */));
|
||||
#else
|
||||
mCachedSource = new NuCachedSource2(mConnectingDataSource);
|
||||
mCachedSource = new NuCachedSource2(mConnectingDataSource);
|
||||
#endif
|
||||
mConnectingDataSource.clear();
|
||||
|
||||
dataSource = mCachedSource;
|
||||
|
||||
// We're going to prefill the cache before trying to instantiate
|
||||
// the extractor below, as the latter is an operation that otherwise
|
||||
// could block on the datasource for a significant amount of time.
|
||||
// During that time we'd be unable to abort the preparation phase
|
||||
// without this prefill.
|
||||
|
||||
mLock.unlock();
|
||||
|
||||
for (;;) {
|
||||
status_t finalStatus;
|
||||
size_t cachedDataRemaining =
|
||||
mCachedSource->approxDataRemaining(&finalStatus);
|
||||
|
||||
if (finalStatus != OK || cachedDataRemaining >= kHighWaterMarkBytes
|
||||
|| (mFlags & PREPARE_CANCELLED)) {
|
||||
break;
|
||||
}
|
||||
|
||||
usleep(200000);
|
||||
dataSource = mCachedSource;
|
||||
} else {
|
||||
dataSource = mConnectingDataSource;
|
||||
}
|
||||
|
||||
mLock.lock();
|
||||
mConnectingDataSource.clear();
|
||||
|
||||
if (mCachedSource != NULL) {
|
||||
// We're going to prefill the cache before trying to instantiate
|
||||
// the extractor below, as the latter is an operation that otherwise
|
||||
// could block on the datasource for a significant amount of time.
|
||||
// During that time we'd be unable to abort the preparation phase
|
||||
// without this prefill.
|
||||
|
||||
mLock.unlock();
|
||||
|
||||
for (;;) {
|
||||
status_t finalStatus;
|
||||
size_t cachedDataRemaining =
|
||||
mCachedSource->approxDataRemaining(&finalStatus);
|
||||
|
||||
if (finalStatus != OK || cachedDataRemaining >= kHighWaterMarkBytes
|
||||
|| (mFlags & PREPARE_CANCELLED)) {
|
||||
break;
|
||||
}
|
||||
|
||||
usleep(200000);
|
||||
}
|
||||
|
||||
mLock.lock();
|
||||
}
|
||||
|
||||
if (mFlags & PREPARE_CANCELLED) {
|
||||
LOGI("Prepare cancelled while waiting for initial cache fill.");
|
||||
@@ -1740,10 +1792,29 @@ status_t AwesomePlayer::finishSetDataSource_l() {
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
|
||||
sp<MediaExtractor> extractor;
|
||||
|
||||
if (extractor == NULL) {
|
||||
return UNKNOWN_ERROR;
|
||||
if (isWidevineStreaming) {
|
||||
String8 mimeType;
|
||||
float confidence;
|
||||
sp<AMessage> dummy;
|
||||
bool success = SniffDRM(dataSource, &mimeType, &confidence, &dummy);
|
||||
|
||||
if (!success
|
||||
|| strcasecmp(
|
||||
mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) {
|
||||
return ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
mWVMExtractor = new WVMExtractor(dataSource);
|
||||
mWVMExtractor->setAdaptiveStreamingMode(true);
|
||||
extractor = mWVMExtractor;
|
||||
} else {
|
||||
extractor = MediaExtractor::Create(dataSource);
|
||||
|
||||
if (extractor == NULL) {
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
dataSource->getDrmInfo(&mDecryptHandle, &mDrmManagerClient);
|
||||
@@ -1754,7 +1825,15 @@ status_t AwesomePlayer::finishSetDataSource_l() {
|
||||
}
|
||||
}
|
||||
|
||||
return setDataSource_l(extractor);
|
||||
status_t err = setDataSource_l(extractor);
|
||||
|
||||
if (err != OK) {
|
||||
mWVMExtractor.clear();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
void AwesomePlayer::abortPrepare(status_t err) {
|
||||
@@ -1815,7 +1894,7 @@ void AwesomePlayer::onPrepareAsyncEvent() {
|
||||
|
||||
mFlags |= PREPARING_CONNECTED;
|
||||
|
||||
if (mCachedSource != NULL || mRTSPController != NULL) {
|
||||
if (isStreamingHTTP() || mRTSPController != NULL) {
|
||||
postBufferingEvent_l();
|
||||
} else {
|
||||
finishAsyncPrepare_l();
|
||||
@@ -1852,4 +1931,8 @@ void AwesomePlayer::postAudioSeekComplete() {
|
||||
postCheckAudioStatusEvent_l();
|
||||
}
|
||||
|
||||
bool AwesomePlayer::isStreamingHTTP() const {
|
||||
return mCachedSource != NULL || mWVMExtractor != NULL;
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
|
||||
@@ -45,7 +45,8 @@ namespace android {
|
||||
static Mutex gWVMutex;
|
||||
|
||||
WVMExtractor::WVMExtractor(const sp<DataSource> &source)
|
||||
: mDataSource(source) {
|
||||
: mDataSource(source),
|
||||
mUseAdaptiveStreaming(false) {
|
||||
{
|
||||
Mutex::Autolock autoLock(gWVMutex);
|
||||
if (gVendorLibHandle == NULL) {
|
||||
@@ -100,5 +101,21 @@ sp<MetaData> WVMExtractor::getMetaData() {
|
||||
return mImpl->getMetaData();
|
||||
}
|
||||
|
||||
int64_t WVMExtractor::getCachedDurationUs(status_t *finalStatus) {
|
||||
// TODO: Fill this with life.
|
||||
|
||||
*finalStatus = OK;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void WVMExtractor::setAdaptiveStreamingMode(bool adaptive) {
|
||||
mUseAdaptiveStreaming = adaptive;
|
||||
}
|
||||
|
||||
bool WVMExtractor::getAdaptiveStreamingMode() const {
|
||||
return mUseAdaptiveStreaming;
|
||||
}
|
||||
|
||||
} //namespace android
|
||||
|
||||
|
||||
@@ -44,6 +44,8 @@ struct ARTSPController;
|
||||
class DrmManagerClinet;
|
||||
class DecryptHandle;
|
||||
|
||||
struct WVMExtractor;
|
||||
|
||||
struct AwesomeRenderer : public RefBase {
|
||||
AwesomeRenderer() {}
|
||||
|
||||
@@ -219,6 +221,8 @@ private:
|
||||
DrmManagerClient *mDrmManagerClient;
|
||||
DecryptHandle *mDecryptHandle;
|
||||
|
||||
sp<WVMExtractor> mWVMExtractor;
|
||||
|
||||
status_t setDataSource_l(
|
||||
const char *uri,
|
||||
const KeyedVector<String8, String8> *headers = NULL);
|
||||
@@ -268,6 +272,8 @@ private:
|
||||
|
||||
status_t startAudioPlayer_l();
|
||||
|
||||
bool isStreamingHTTP() const;
|
||||
|
||||
AwesomePlayer(const AwesomePlayer &);
|
||||
AwesomePlayer &operator=(const AwesomePlayer &);
|
||||
};
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#define WVM_EXTRACTOR_H_
|
||||
|
||||
#include <media/stagefright/MediaExtractor.h>
|
||||
#include <utils/Errors.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
@@ -33,12 +34,31 @@ public:
|
||||
virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
|
||||
virtual sp<MetaData> getMetaData();
|
||||
|
||||
// Return the amount of data cached from the current
|
||||
// playback positiion (in us).
|
||||
// While more data is still being fetched *finalStatus == OK,
|
||||
// Once fetching is completed (no more data available), *finalStatus != OK
|
||||
// If fetching completed normally (i.e. reached EOS instead of IO error)
|
||||
// *finalStatus == ERROR_END_OF_STREAM
|
||||
int64_t getCachedDurationUs(status_t *finalStatus);
|
||||
|
||||
// Set to use adaptive streaming mode by the WV component.
|
||||
// If adaptive == true, adaptive streaming mode will be used.
|
||||
// Default mode is non-adaptive streaming mode.
|
||||
// Should set to use adaptive streaming mode only if widevine:// protocol
|
||||
// is used.
|
||||
void setAdaptiveStreamingMode(bool adaptive);
|
||||
|
||||
// Retrieve the adaptive streaming mode used by the WV component.
|
||||
bool getAdaptiveStreamingMode() const;
|
||||
|
||||
protected:
|
||||
virtual ~WVMExtractor();
|
||||
|
||||
private:
|
||||
sp<DataSource> mDataSource;
|
||||
sp<MediaExtractor> mImpl;
|
||||
bool mUseAdaptiveStreaming;
|
||||
|
||||
WVMExtractor(const WVMExtractor &);
|
||||
WVMExtractor &operator=(const WVMExtractor &);
|
||||
|
||||
Reference in New Issue
Block a user