diff --git a/proprietary/wvm/WVMExtractorImpl.cpp b/proprietary/wvm/WVMExtractorImpl.cpp index 54b0f159..a12826f3 100644 --- a/proprietary/wvm/WVMExtractorImpl.cpp +++ b/proprietary/wvm/WVMExtractorImpl.cpp @@ -48,15 +48,17 @@ static int _cb2(char *in, char *out, int length, char *iv) DrmBuffer *decryptedDrmBufferPtr = &decryptedDrmBuffer; char ivout[AES_BLOCK_SIZE]; - if (in && length) + if (in && length) { memcpy(ivout, in + length - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + } status = sDrmManagerClient->decrypt(sDecryptHandle, 0, &encryptedDrmBuffer, &decryptedDrmBufferPtr, &ivBuffer); - if (iv) + if (iv) { memcpy(iv, ivout, AES_BLOCK_SIZE); + } } return status; @@ -100,6 +102,7 @@ WVMExtractorImpl::WVMExtractorImpl(sp dataSource) mIsLiveStream(false), mSession(NULL), mDuration(0), + mError(OK), mSetupStatus(OK) { dataSource->getDrmInfo(sDecryptHandle, &sDrmManagerClient); @@ -114,8 +117,9 @@ WVMExtractorImpl::WVMExtractorImpl(sp dataSource) if (sDecryptHandle->status != RightsStatus::RIGHTS_VALID) { mSetupStatus = ERROR_DRM_NO_LICENSE; } - } else + } else { mSetupStatus = ERROR_DRM_NO_LICENSE; + } // Set an info listener to handle messages from the drm plugin mInfoListener = new WVMInfoListener(); @@ -129,6 +133,11 @@ void WVMExtractorImpl::Initialize() WVCredentials credentials; WVStatus result; + if (mSetupStatus != OK) { + setError(mSetupStatus); + return; + } + if (mDataSource->getUri().size() > 0 && getAdaptiveStreamingMode()) { mIsLiveStream = (mDataSource->getUri().getPathExtension().find(".m3u8") == 0); } @@ -179,6 +188,10 @@ void WVMExtractorImpl::Initialize() } } + if (mSetupStatus != OK) { + setError(mSetupStatus); + } + WV_SetWarningToErrorMS(10000); } @@ -227,13 +240,15 @@ void WVMExtractorImpl::SocketInfoCallback(int fd, int closing, void *context) // status_t WVMExtractorImpl::readMetaData() { - if (mHaveMetaData) + if (mHaveMetaData) { return OK; + } Initialize(); - if (mSetupStatus != OK) + if (mSetupStatus != OK) { return mSetupStatus; + } // Get Video Configuration WVVideoType videoType; @@ -247,8 +262,9 @@ status_t WVMExtractorImpl::readMetaData() WVStatus result = WV_Info_GetVideoConfiguration(mSession, &videoType, &videoStreamID, &videoProfile, &level, &width, &height, &aspect, &frameRate, &videoBitRate); - if (result != WV_Status_OK) + if (result != WV_Status_OK) { return ERROR_MALFORMED; + } // Get Audio Configuration WVAudioType audioType; @@ -260,8 +276,9 @@ status_t WVMExtractorImpl::readMetaData() result = WV_Info_GetAudioConfiguration(mSession, &audioType, &audioStreamID, &audioProfile, &numChannels, &sampleRate, &audioBitRate); - if (result != WV_Status_OK) + if (result != WV_Status_OK) { return ERROR_MALFORMED; + } if (numChannels == 0) { ALOGD("numChannels is 0!"); @@ -272,10 +289,11 @@ status_t WVMExtractorImpl::readMetaData() if (durationString == "") { // We won't have a duration for live streams, and Stagefright doesn't seem to // have a way to represent that. Give a default duration of 1 hour for now. - if (mIsLiveStream) + if (mIsLiveStream) { durationString = "3600"; - else + } else { return ERROR_MALFORMED; + } } mDuration = (int64_t)(strtod(durationString.c_str(), NULL) * 1000000); @@ -328,8 +346,9 @@ status_t WVMExtractorImpl::readMetaData() status_t status; status = readESDSMetaData(audioMetaData); - if (status != OK) + if (status != OK) { return status; + } if (mIsLiveStream) { result = WV_Pause(mSession, ""); @@ -347,8 +366,9 @@ status_t WVMExtractorImpl::readMetaData() // Since the WVExtractor goes away soon after this, we delegate ownership of some resources // to the constructed media source - if (mFileSource.get()) + if (mFileSource.get()) { mVideoSource->delegateFileSource(mFileSource); + } mVideoSource->delegateDataSource(mDataSource); @@ -411,8 +431,9 @@ status_t WVMExtractorImpl::readESDSMetaData(sp audioMetaData) bytesRead, auStart, dts, pts, sync); result = WV_Info_GetCodecConfig(mSession, WV_CodecConfigType_ESDS, config, size); - if (result != WV_Status_OK) + if (result != WV_Status_OK) { usleep(10000); + } } while (result == WV_Status_Warning_Not_Available && limit-- > 0); if (result != WV_Status_OK) { @@ -423,9 +444,9 @@ status_t WVMExtractorImpl::readESDSMetaData(sp audioMetaData) #if 0 char *filename = "/data/wvm/esds"; FILE *f = fopen(filename, "w"); - if (!f) + if (!f) { ALOGD("Failed to open %s", filename); - else { + } else { fwrite(config, size, 1, f); fclose(f); } @@ -437,6 +458,7 @@ status_t WVMExtractorImpl::readESDSMetaData(sp audioMetaData) size_t WVMExtractorImpl::countTracks() { status_t err; if ((err = readMetaData()) != OK) { + setError(err); return 0; } @@ -447,6 +469,7 @@ sp WVMExtractorImpl::getTrack(size_t index) { status_t err; if ((err = readMetaData()) != OK) { + setError(err); return NULL; } @@ -470,18 +493,21 @@ sp WVMExtractorImpl::getTrackMetaData(size_t index, uint32_t flags) { status_t err; if ((err = readMetaData()) != OK) { + setError(err); return NULL; } sp result; switch(index) { case 0: - if (mVideoSource != NULL) + if (mVideoSource != NULL) { result = mVideoSource->getFormat(); + } break; case 1: - if (mAudioSource != NULL) + if (mAudioSource != NULL) { result = mAudioSource->getFormat(); + } break; default: break; @@ -553,7 +579,6 @@ int64_t WVMExtractorImpl::getCachedDurationUs(status_t *finalStatus) { } } } - return durationUs; } @@ -604,4 +629,33 @@ size_t WVMExtractorImpl::getStreamCacheSize() const return atol(value); } +status_t WVMExtractorImpl::getError() { + Mutex::Autolock autoLock(mLock); + + status_t err = mError; + mError = OK; + + // + // MediaPlayer.java documents these MEDIA_ERROR codes for applications: + // MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_SERVER_DIED, MEDIA_ERROR_IO, + // MEDIA_ERROR_MALFORMED, MEDIA_ERROR_UNSUPPORTED and MEDIA_ERROR_TIMED_OUT. + // In order to not change the behavior of WVMExtractorImpl.cpp, + // we return all ERROR_ codes used by the WVMExtractor in addition to + // those documented in MediaPlayer.java. + // + if (err == ERROR_DRM_NO_LICENSE || err == ERROR_END_OF_STREAM || + err == ERROR_IO || err == ERROR_MALFORMED || err == OK || + err == ERROR_UNSUPPORTED) { + return err; + } else { + return UNKNOWN_ERROR; + } +} + +void WVMExtractorImpl::setError(status_t err) { + Mutex::Autolock autoLock(mLock); + + mError = err; +} + } // namespace android diff --git a/proprietary/wvm/include/WVMExtractorImpl.h b/proprietary/wvm/include/WVMExtractorImpl.h index 7d160680..fb4397be 100644 --- a/proprietary/wvm/include/WVMExtractorImpl.h +++ b/proprietary/wvm/include/WVMExtractorImpl.h @@ -13,7 +13,6 @@ #include #include - // DLL entry - given a data source, instantiate a WVMExtractor object namespace android { @@ -52,11 +51,17 @@ public: static void SocketInfoCallback(int fd, int op, void *context); static void cleanup(); + status_t getError() ; + + void setError(status_t err); + protected: virtual ~WVMExtractorImpl(); void Initialize(); private: + Mutex mLock; + status_t readAVCCMetaData(sp videoMetaData); status_t readESDSMetaData(sp audioMetaData); @@ -77,6 +82,8 @@ private: int64_t mDuration; // usec. + status_t mError; + status_t mSetupStatus; status_t readMetaData();