diff options
-rw-r--r-- | include/media/stagefright/DataSource.h | 8 | ||||
-rw-r--r-- | include/media/stagefright/MediaExtractor.h | 2 | ||||
-rw-r--r-- | media/libmediaplayerservice/nuplayer/GenericSource.cpp | 60 | ||||
-rw-r--r-- | media/libmediaplayerservice/nuplayer/GenericSource.h | 18 | ||||
-rw-r--r-- | media/libmediaplayerservice/nuplayer/NuPlayer.cpp | 46 | ||||
-rw-r--r-- | media/libstagefright/DataSource.cpp | 80 | ||||
-rw-r--r-- | media/libstagefright/include/WVMExtractor.h | 3 |
7 files changed, 161 insertions, 56 deletions
diff --git a/include/media/stagefright/DataSource.h b/include/media/stagefright/DataSource.h index f8787dd..3fb9e36 100644 --- a/include/media/stagefright/DataSource.h +++ b/include/media/stagefright/DataSource.h @@ -31,6 +31,7 @@ namespace android { struct AMessage; +struct AString; struct IMediaHTTPService; class String8; @@ -46,7 +47,8 @@ public: static sp<DataSource> CreateFromURI( const sp<IMediaHTTPService> &httpService, const char *uri, - const KeyedVector<String8, String8> *headers = NULL); + const KeyedVector<String8, String8> *headers = NULL, + AString *sniffedMIME = NULL); DataSource() {} @@ -100,6 +102,10 @@ protected: virtual ~DataSource() {} private: + enum { + kDefaultMetaSize = 200000, + }; + static Mutex gSnifferMutex; static List<SnifferFunc> gSniffers; static bool gSniffersRegistered; diff --git a/include/media/stagefright/MediaExtractor.h b/include/media/stagefright/MediaExtractor.h index 3076a96..183933a 100644 --- a/include/media/stagefright/MediaExtractor.h +++ b/include/media/stagefright/MediaExtractor.h @@ -65,6 +65,8 @@ public: virtual char* getDrmTrackInfo(size_t trackID, int *len) { return NULL; } + virtual void setUID(uid_t uid) { + } protected: MediaExtractor() : mIsDrm(false) {} diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp index 32842bb..a18407f 100644 --- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp +++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp @@ -37,10 +37,6 @@ namespace android { NuPlayer::GenericSource::GenericSource( const sp<AMessage> ¬ify, - const sp<IMediaHTTPService> &httpService, - const char *url, - const KeyedVector<String8, String8> *headers, - bool isWidevine, bool uidValid, uid_t uid) : Source(notify), @@ -48,38 +44,41 @@ NuPlayer::GenericSource::GenericSource( mFetchTimedTextDataGeneration(0), mDurationUs(0ll), mAudioIsVorbis(false), - mIsWidevine(isWidevine), + mIsWidevine(false), mUIDValid(uidValid), mUID(uid) { DataSource::RegisterDefaultSniffers(); +} + +status_t NuPlayer::GenericSource::init( + const sp<IMediaHTTPService> &httpService, + const char *url, + const KeyedVector<String8, String8> *headers) { + mIsWidevine = !strncasecmp(url, "widevine://", 11); + + AString sniffedMIME; sp<DataSource> dataSource = - DataSource::CreateFromURI(httpService, url, headers); - CHECK(dataSource != NULL); + DataSource::CreateFromURI(httpService, url, headers, &sniffedMIME); - initFromDataSource(dataSource); -} + if (dataSource == NULL) { + return UNKNOWN_ERROR; + } -NuPlayer::GenericSource::GenericSource( - const sp<AMessage> ¬ify, - int fd, int64_t offset, int64_t length) - : Source(notify), - mFetchSubtitleDataGeneration(0), - mFetchTimedTextDataGeneration(0), - mDurationUs(0ll), - mAudioIsVorbis(false), - mIsWidevine(false), - mUIDValid(false), - mUID(0) { - DataSource::RegisterDefaultSniffers(); + return initFromDataSource( + dataSource, sniffedMIME.empty() ? NULL : sniffedMIME.c_str()); +} +status_t NuPlayer::GenericSource::init( + int fd, int64_t offset, int64_t length) { sp<DataSource> dataSource = new FileSource(dup(fd), offset, length); - initFromDataSource(dataSource); + return initFromDataSource(dataSource, NULL); } -void NuPlayer::GenericSource::initFromDataSource( - const sp<DataSource> &dataSource) { +status_t NuPlayer::GenericSource::initFromDataSource( + const sp<DataSource> &dataSource, + const char* mime) { sp<MediaExtractor> extractor; if (mIsWidevine) { @@ -93,7 +92,7 @@ void NuPlayer::GenericSource::initFromDataSource( || strcasecmp( mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) { ALOGE("unsupported widevine mime: %s", mimeType.string()); - return; + return UNKNOWN_ERROR; } sp<WVMExtractor> wvmExtractor = new WVMExtractor(dataSource); @@ -103,10 +102,12 @@ void NuPlayer::GenericSource::initFromDataSource( } extractor = wvmExtractor; } else { - extractor = MediaExtractor::Create(dataSource); + extractor = MediaExtractor::Create(dataSource, mime); } - CHECK(extractor != NULL); + if (extractor == NULL) { + return UNKNOWN_ERROR; + } sp<MetaData> fileMeta = extractor->getMetaData(); if (fileMeta != NULL) { @@ -144,6 +145,9 @@ void NuPlayer::GenericSource::initFromDataSource( int32_t secure; if (meta->findInt32(kKeyRequiresSecureBuffers, &secure) && secure) { mIsWidevine = true; + if (mUIDValid) { + extractor->setUID(mUID); + } } } } @@ -158,6 +162,8 @@ void NuPlayer::GenericSource::initFromDataSource( } } } + + return OK; } status_t NuPlayer::GenericSource::setBuffers(bool audio, Vector<MediaBuffer *> &buffers) { diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.h b/media/libmediaplayerservice/nuplayer/GenericSource.h index 3c5f55c..76e628b 100644 --- a/media/libmediaplayerservice/nuplayer/GenericSource.h +++ b/media/libmediaplayerservice/nuplayer/GenericSource.h @@ -34,18 +34,14 @@ struct MediaSource; class MediaBuffer; struct NuPlayer::GenericSource : public NuPlayer::Source { - GenericSource( - const sp<AMessage> ¬ify, + GenericSource(const sp<AMessage> ¬ify, bool uidValid, uid_t uid); + + status_t init( const sp<IMediaHTTPService> &httpService, const char *url, - const KeyedVector<String8, String8> *headers, - bool isWidevine = false, - bool uidValid = false, - uid_t uid = 0); + const KeyedVector<String8, String8> *headers); - GenericSource( - const sp<AMessage> ¬ify, - int fd, int64_t offset, int64_t length); + status_t init(int fd, int64_t offset, int64_t length); virtual void prepareAsync(); @@ -101,7 +97,9 @@ private: bool mUIDValid; uid_t mUID; - void initFromDataSource(const sp<DataSource> &dataSource); + status_t initFromDataSource( + const sp<DataSource> &dataSource, + const char *mime); void fetchTextData( uint32_t what, media_track_type type, diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index 17038a4..d56b1f0 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -207,6 +207,7 @@ void NuPlayer::setDataSourceAsync( const sp<IMediaHTTPService> &httpService, const char *url, const KeyedVector<String8, String8> *headers) { + sp<AMessage> msg = new AMessage(kWhatSetDataSource, id()); size_t len = strlen(url); @@ -224,16 +225,21 @@ void NuPlayer::setDataSourceAsync( || strstr(url, ".sdp?"))) { source = new RTSPSource( notify, httpService, url, headers, mUIDValid, mUID, true); - } else if ((!strncasecmp(url, "widevine://", 11))) { - source = new GenericSource(notify, httpService, url, headers, - true /* isWidevine */, mUIDValid, mUID); - // Don't set FLAG_SECURE on mSourceFlags here, the correct flags - // will be updated in Source::kWhatFlagsChanged handler when - // GenericSource is prepared. } else { - source = new GenericSource(notify, httpService, url, headers); - } + sp<GenericSource> genericSource = + new GenericSource(notify, mUIDValid, mUID); + // Don't set FLAG_SECURE on mSourceFlags here for widevine. + // The correct flags will be updated in Source::kWhatFlagsChanged + // handler when GenericSource is prepared. + status_t err = genericSource->init(httpService, url, headers); + + if (err == OK) { + source = genericSource; + } else { + ALOGE("Failed to initialize generic source!"); + } + } msg->setObject("source", source); msg->post(); } @@ -243,7 +249,16 @@ void NuPlayer::setDataSourceAsync(int fd, int64_t offset, int64_t length) { sp<AMessage> notify = new AMessage(kWhatSourceNotify, id()); - sp<Source> source = new GenericSource(notify, fd, offset, length); + sp<GenericSource> source = + new GenericSource(notify, mUIDValid, mUID); + + status_t err = source->init(fd, offset, length); + + if (err != OK) { + ALOGE("Failed to initialize generic source!"); + source = NULL; + } + msg->setObject("source", source); msg->post(); } @@ -352,17 +367,20 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { CHECK(mSource == NULL); + status_t err = OK; sp<RefBase> obj; CHECK(msg->findObject("source", &obj)); - - mSource = static_cast<Source *>(obj.get()); - - looper()->registerHandler(mSource); + if (obj != NULL) { + mSource = static_cast<Source *>(obj.get()); + looper()->registerHandler(mSource); + } else { + err = UNKNOWN_ERROR; + } CHECK(mDriver != NULL); sp<NuPlayerDriver> driver = mDriver.promote(); if (driver != NULL) { - driver->notifySetDataSourceCompleted(OK); + driver->notifySetDataSourceCompleted(err); } break; } diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp index 6e0f37a..908cdca 100644 --- a/media/libstagefright/DataSource.cpp +++ b/media/libstagefright/DataSource.cpp @@ -13,6 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +//#define LOG_NDEBUG 0 +#define LOG_TAG "DataSource" #include "include/AMRExtractor.h" @@ -33,6 +35,7 @@ #include <media/IMediaHTTPConnection.h> #include <media/IMediaHTTPService.h> +#include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/foundation/AMessage.h> #include <media/stagefright/DataSource.h> #include <media/stagefright/DataURISource.h> @@ -182,7 +185,12 @@ void DataSource::RegisterDefaultSniffers() { sp<DataSource> DataSource::CreateFromURI( const sp<IMediaHTTPService> &httpService, const char *uri, - const KeyedVector<String8, String8> *headers) { + const KeyedVector<String8, String8> *headers, + AString *sniffedMIME) { + if (sniffedMIME != NULL) { + *sniffedMIME = ""; + } + bool isWidevine = !strncasecmp("widevine://", uri, 11); sp<DataSource> source; @@ -202,6 +210,7 @@ sp<DataSource> DataSource::CreateFromURI( } if (httpSource->connect(uri, headers) != OK) { + ALOGE("Failed to connect http source!"); return NULL; } @@ -214,9 +223,76 @@ sp<DataSource> DataSource::CreateFromURI( ©, &cacheConfig, &disconnectAtHighwatermark); } - source = new NuCachedSource2( + sp<NuCachedSource2> cachedSource = new NuCachedSource2( httpSource, cacheConfig.isEmpty() ? NULL : cacheConfig.string()); + + String8 contentType = httpSource->getMIMEType(); + + if (strncasecmp(contentType.string(), "audio/", 6)) { + // We're not doing this for streams that appear to be audio-only + // streams to ensure that even low bandwidth streams start + // playing back fairly instantly. + + // 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. + + // Initially make sure we have at least 192 KB for the sniff + // to complete without blocking. + static const size_t kMinBytesForSniffing = 192 * 1024; + + off64_t metaDataSize = -1ll; + for (;;) { + status_t finalStatus; + size_t cachedDataRemaining = + cachedSource->approxDataRemaining(&finalStatus); + + if (finalStatus != OK || (metaDataSize >= 0 + && (off64_t)cachedDataRemaining >= metaDataSize)) { + ALOGV("stop caching, status %d, " + "metaDataSize %lld, cachedDataRemaining %zu", + finalStatus, metaDataSize, cachedDataRemaining); + break; + } + + ALOGV("now cached %zu bytes of data", cachedDataRemaining); + + if (metaDataSize < 0 + && cachedDataRemaining >= kMinBytesForSniffing) { + String8 tmp; + float confidence; + sp<AMessage> meta; + if (!cachedSource->sniff(&tmp, &confidence, &meta)) { + return NULL; + } + + // We successfully identified the file's extractor to + // be, remember this mime type so we don't have to + // sniff it again when we call MediaExtractor::Create() + if (sniffedMIME != NULL) { + *sniffedMIME = tmp.string(); + } + + if (meta == NULL + || !meta->findInt64("meta-data-size", + reinterpret_cast<int64_t*>(&metaDataSize))) { + metaDataSize = kDefaultMetaSize; + } + + if (metaDataSize < 0ll) { + ALOGE("invalid metaDataSize = %lld bytes", metaDataSize); + return NULL; + } + } + + usleep(200000); + } + } + + source = cachedSource; } else { // We do not want that prefetching, caching, datasource wrapper // in the widevine:// case. diff --git a/media/libstagefright/include/WVMExtractor.h b/media/libstagefright/include/WVMExtractor.h index 8e62946..ab7e8b8 100644 --- a/media/libstagefright/include/WVMExtractor.h +++ b/media/libstagefright/include/WVMExtractor.h @@ -49,6 +49,7 @@ public: virtual sp<MediaSource> getTrack(size_t index); virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags); virtual sp<MetaData> getMetaData(); + virtual void setUID(uid_t uid); // Return the amount of data cached from the current // playback positiion (in us). @@ -74,8 +75,6 @@ public: // codec. void setCryptoPluginMode(bool cryptoPluginMode); - void setUID(uid_t uid); - static bool getVendorLibHandle(); status_t getError(); |