Loading media/libstagefright/AwesomePlayer.cpp +111 −28 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -447,6 +449,7 @@ void AwesomePlayer::reset_l() { cancelPlayerEvents(); mWVMExtractor.clear(); mCachedSource.clear(); mAudioTrack.clear(); mVideoTrack.clear(); Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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. Loading Loading @@ -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); Loading @@ -1670,6 +1713,9 @@ status_t AwesomePlayer::finishSetDataSource_l() { return err; } if (!isWidevineStreaming) { // The widevine extractor does its own caching. #if 0 mCachedSource = new NuCachedSource2( new ThrottledSource( Loading @@ -1677,10 +1723,15 @@ status_t AwesomePlayer::finishSetDataSource_l() { #else mCachedSource = new NuCachedSource2(mConnectingDataSource); #endif mConnectingDataSource.clear(); dataSource = mCachedSource; } else { dataSource = mConnectingDataSource; } 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. Loading @@ -1703,6 +1754,7 @@ status_t AwesomePlayer::finishSetDataSource_l() { } mLock.lock(); } if (mFlags & PREPARE_CANCELLED) { LOGI("Prepare cancelled while waiting for initial cache fill."); Loading Loading @@ -1740,11 +1792,30 @@ status_t AwesomePlayer::finishSetDataSource_l() { return UNKNOWN_ERROR; } sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource); sp<MediaExtractor> extractor; 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); if (mDecryptHandle != NULL) { Loading @@ -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) { Loading Loading @@ -1815,7 +1894,7 @@ void AwesomePlayer::onPrepareAsyncEvent() { mFlags |= PREPARING_CONNECTED; if (mCachedSource != NULL || mRTSPController != NULL) { if (isStreamingHTTP() || mRTSPController != NULL) { postBufferingEvent_l(); } else { finishAsyncPrepare_l(); Loading Loading @@ -1852,4 +1931,8 @@ void AwesomePlayer::postAudioSeekComplete() { postCheckAudioStatusEvent_l(); } bool AwesomePlayer::isStreamingHTTP() const { return mCachedSource != NULL || mWVMExtractor != NULL; } } // namespace android media/libstagefright/WVMExtractor.cpp +18 −1 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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 media/libstagefright/include/AwesomePlayer.h +6 −0 Original line number Diff line number Diff line Loading @@ -44,6 +44,8 @@ struct ARTSPController; class DrmManagerClinet; class DecryptHandle; struct WVMExtractor; struct AwesomeRenderer : public RefBase { AwesomeRenderer() {} Loading Loading @@ -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); Loading Loading @@ -268,6 +272,8 @@ private: status_t startAudioPlayer_l(); bool isStreamingHTTP() const; AwesomePlayer(const AwesomePlayer &); AwesomePlayer &operator=(const AwesomePlayer &); }; Loading media/libstagefright/include/WVMExtractor.h +20 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #define WVM_EXTRACTOR_H_ #include <media/stagefright/MediaExtractor.h> #include <utils/Errors.h> namespace android { Loading @@ -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 &); Loading Loading
media/libstagefright/AwesomePlayer.cpp +111 −28 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -447,6 +449,7 @@ void AwesomePlayer::reset_l() { cancelPlayerEvents(); mWVMExtractor.clear(); mCachedSource.clear(); mAudioTrack.clear(); mVideoTrack.clear(); Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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. Loading Loading @@ -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); Loading @@ -1670,6 +1713,9 @@ status_t AwesomePlayer::finishSetDataSource_l() { return err; } if (!isWidevineStreaming) { // The widevine extractor does its own caching. #if 0 mCachedSource = new NuCachedSource2( new ThrottledSource( Loading @@ -1677,10 +1723,15 @@ status_t AwesomePlayer::finishSetDataSource_l() { #else mCachedSource = new NuCachedSource2(mConnectingDataSource); #endif mConnectingDataSource.clear(); dataSource = mCachedSource; } else { dataSource = mConnectingDataSource; } 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. Loading @@ -1703,6 +1754,7 @@ status_t AwesomePlayer::finishSetDataSource_l() { } mLock.lock(); } if (mFlags & PREPARE_CANCELLED) { LOGI("Prepare cancelled while waiting for initial cache fill."); Loading Loading @@ -1740,11 +1792,30 @@ status_t AwesomePlayer::finishSetDataSource_l() { return UNKNOWN_ERROR; } sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource); sp<MediaExtractor> extractor; 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); if (mDecryptHandle != NULL) { Loading @@ -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) { Loading Loading @@ -1815,7 +1894,7 @@ void AwesomePlayer::onPrepareAsyncEvent() { mFlags |= PREPARING_CONNECTED; if (mCachedSource != NULL || mRTSPController != NULL) { if (isStreamingHTTP() || mRTSPController != NULL) { postBufferingEvent_l(); } else { finishAsyncPrepare_l(); Loading Loading @@ -1852,4 +1931,8 @@ void AwesomePlayer::postAudioSeekComplete() { postCheckAudioStatusEvent_l(); } bool AwesomePlayer::isStreamingHTTP() const { return mCachedSource != NULL || mWVMExtractor != NULL; } } // namespace android
media/libstagefright/WVMExtractor.cpp +18 −1 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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
media/libstagefright/include/AwesomePlayer.h +6 −0 Original line number Diff line number Diff line Loading @@ -44,6 +44,8 @@ struct ARTSPController; class DrmManagerClinet; class DecryptHandle; struct WVMExtractor; struct AwesomeRenderer : public RefBase { AwesomeRenderer() {} Loading Loading @@ -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); Loading Loading @@ -268,6 +272,8 @@ private: status_t startAudioPlayer_l(); bool isStreamingHTTP() const; AwesomePlayer(const AwesomePlayer &); AwesomePlayer &operator=(const AwesomePlayer &); }; Loading
media/libstagefright/include/WVMExtractor.h +20 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #define WVM_EXTRACTOR_H_ #include <media/stagefright/MediaExtractor.h> #include <utils/Errors.h> namespace android { Loading @@ -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 &); Loading