diff options
34 files changed, 1590 insertions, 136 deletions
diff --git a/drm/common/IDrmManagerService.cpp b/drm/common/IDrmManagerService.cpp index 696e305..e2bfb16 100644 --- a/drm/common/IDrmManagerService.cpp +++ b/drm/common/IDrmManagerService.cpp @@ -621,11 +621,6 @@ status_t BpDrmManagerService::closeDecryptSession(int uniqueId, DecryptHandle* d remote()->transact(CLOSE_DECRYPT_SESSION, data, &reply); - if (NULL != decryptHandle->decryptInfo) { - LOGV("deleting decryptInfo"); - delete decryptHandle->decryptInfo; decryptHandle->decryptInfo = NULL; - } - delete decryptHandle; decryptHandle = NULL; return reply.readInt32(); } diff --git a/drm/libdrmframework/DrmManagerClient.cpp b/drm/libdrmframework/DrmManagerClient.cpp index 1d1e258..8b78132 100644 --- a/drm/libdrmframework/DrmManagerClient.cpp +++ b/drm/libdrmframework/DrmManagerClient.cpp @@ -77,12 +77,13 @@ int DrmManagerClient::checkRightsStatus(const String8& path, int action) { return mDrmManagerClientImpl->checkRightsStatus(mUniqueId, path, action); } -status_t DrmManagerClient::consumeRights(DecryptHandle* decryptHandle, int action, bool reserve) { +status_t DrmManagerClient::consumeRights( + sp<DecryptHandle> &decryptHandle, int action, bool reserve) { return mDrmManagerClientImpl->consumeRights(mUniqueId, decryptHandle, action, reserve); } status_t DrmManagerClient::setPlaybackStatus( - DecryptHandle* decryptHandle, int playbackStatus, int64_t position) { + sp<DecryptHandle> &decryptHandle, int playbackStatus, int64_t position) { return mDrmManagerClientImpl ->setPlaybackStatus(mUniqueId, decryptHandle, playbackStatus, position); } @@ -116,37 +117,39 @@ status_t DrmManagerClient::getAllSupportInfo(int* length, DrmSupportInfo** drmSu return mDrmManagerClientImpl->getAllSupportInfo(mUniqueId, length, drmSupportInfoArray); } -DecryptHandle* DrmManagerClient::openDecryptSession(int fd, off64_t offset, off64_t length) { +sp<DecryptHandle> DrmManagerClient::openDecryptSession(int fd, off64_t offset, off64_t length) { return mDrmManagerClientImpl->openDecryptSession(mUniqueId, fd, offset, length); } -DecryptHandle* DrmManagerClient::openDecryptSession(const char* uri) { +sp<DecryptHandle> DrmManagerClient::openDecryptSession(const char* uri) { return mDrmManagerClientImpl->openDecryptSession(mUniqueId, uri); } -status_t DrmManagerClient::closeDecryptSession(DecryptHandle* decryptHandle) { +status_t DrmManagerClient::closeDecryptSession(sp<DecryptHandle> &decryptHandle) { return mDrmManagerClientImpl->closeDecryptSession(mUniqueId, decryptHandle); } status_t DrmManagerClient::initializeDecryptUnit( - DecryptHandle* decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo) { + sp<DecryptHandle> &decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo) { return mDrmManagerClientImpl->initializeDecryptUnit( mUniqueId, decryptHandle, decryptUnitId, headerInfo); } status_t DrmManagerClient::decrypt( - DecryptHandle* decryptHandle, int decryptUnitId, - const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) { + sp<DecryptHandle> &decryptHandle, int decryptUnitId, + const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) { return mDrmManagerClientImpl->decrypt( mUniqueId, decryptHandle, decryptUnitId, encBuffer, decBuffer, IV); } -status_t DrmManagerClient::finalizeDecryptUnit(DecryptHandle* decryptHandle, int decryptUnitId) { - return mDrmManagerClientImpl->finalizeDecryptUnit(mUniqueId, decryptHandle, decryptUnitId); +status_t DrmManagerClient::finalizeDecryptUnit( + sp<DecryptHandle> &decryptHandle, int decryptUnitId) { + return mDrmManagerClientImpl->finalizeDecryptUnit(mUniqueId, + decryptHandle, decryptUnitId); } ssize_t DrmManagerClient::pread( - DecryptHandle* decryptHandle, void* buffer, ssize_t numBytes, off64_t offset) { + sp<DecryptHandle> &decryptHandle, void* buffer, ssize_t numBytes, off64_t offset) { return mDrmManagerClientImpl->pread(mUniqueId, decryptHandle, buffer, numBytes, offset); } diff --git a/drm/libdrmframework/DrmManagerClientImpl.cpp b/drm/libdrmframework/DrmManagerClientImpl.cpp index d20de92..e6ae220 100644 --- a/drm/libdrmframework/DrmManagerClientImpl.cpp +++ b/drm/libdrmframework/DrmManagerClientImpl.cpp @@ -78,14 +78,16 @@ void DrmManagerClientImpl::removeClient(int uniqueId) { } status_t DrmManagerClientImpl::setOnInfoListener( - int uniqueId, const sp<DrmManagerClient::OnInfoListener>& infoListener) { + int uniqueId, + const sp<DrmManagerClient::OnInfoListener>& infoListener) { Mutex::Autolock _l(mLock); mOnInfoListener = infoListener; return getDrmManagerService()->setDrmServiceListener(uniqueId, (NULL != infoListener.get()) ? this : NULL); } -status_t DrmManagerClientImpl::installDrmEngine(int uniqueId, const String8& drmEngineFile) { +status_t DrmManagerClientImpl::installDrmEngine( + int uniqueId, const String8& drmEngineFile) { status_t status = DRM_ERROR_UNKNOWN; if (EMPTY_STRING != drmEngineFile) { status = getDrmManagerService()->installDrmEngine(uniqueId, drmEngineFile); @@ -97,7 +99,8 @@ DrmConstraints* DrmManagerClientImpl::getConstraints( int uniqueId, const String8* path, const int action) { DrmConstraints *drmConstraints = NULL; if ((NULL != path) && (EMPTY_STRING != *path)) { - drmConstraints = getDrmManagerService()->getConstraints(uniqueId, path, action); + drmConstraints = + getDrmManagerService()->getConstraints(uniqueId, path, action); } return drmConstraints; } @@ -110,7 +113,8 @@ DrmMetadata* DrmManagerClientImpl::getMetadata(int uniqueId, const String8* path return drmMetadata; } -bool DrmManagerClientImpl::canHandle(int uniqueId, const String8& path, const String8& mimeType) { +bool DrmManagerClientImpl::canHandle( + int uniqueId, const String8& path, const String8& mimeType) { bool retCode = false; if ((EMPTY_STRING != path) || (EMPTY_STRING != mimeType)) { retCode = getDrmManagerService()->canHandle(uniqueId, path, mimeType); @@ -118,7 +122,8 @@ bool DrmManagerClientImpl::canHandle(int uniqueId, const String8& path, const St return retCode; } -DrmInfoStatus* DrmManagerClientImpl::processDrmInfo(int uniqueId, const DrmInfo* drmInfo) { +DrmInfoStatus* DrmManagerClientImpl::processDrmInfo( + int uniqueId, const DrmInfo* drmInfo) { DrmInfoStatus *drmInfoStatus = NULL; if (NULL != drmInfo) { drmInfoStatus = getDrmManagerService()->processDrmInfo(uniqueId, drmInfo); @@ -126,7 +131,8 @@ DrmInfoStatus* DrmManagerClientImpl::processDrmInfo(int uniqueId, const DrmInfo* return drmInfoStatus; } -DrmInfo* DrmManagerClientImpl::acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) { +DrmInfo* DrmManagerClientImpl::acquireDrmInfo( + int uniqueId, const DrmInfoRequest* drmInfoRequest) { DrmInfo* drmInfo = NULL; if (NULL != drmInfoRequest) { drmInfo = getDrmManagerService()->acquireDrmInfo(uniqueId, drmInfoRequest); @@ -138,12 +144,14 @@ status_t DrmManagerClientImpl::saveRights(int uniqueId, const DrmRights& drmRigh const String8& rightsPath, const String8& contentPath) { status_t status = DRM_ERROR_UNKNOWN; if (EMPTY_STRING != contentPath) { - status = getDrmManagerService()->saveRights(uniqueId, drmRights, rightsPath, contentPath); + status = getDrmManagerService()->saveRights( + uniqueId, drmRights, rightsPath, contentPath); } return status; } -String8 DrmManagerClientImpl::getOriginalMimeType(int uniqueId, const String8& path) { +String8 DrmManagerClientImpl::getOriginalMimeType( + int uniqueId, const String8& path) { String8 mimeType = EMPTY_STRING; if (EMPTY_STRING != path) { mimeType = getDrmManagerService()->getOriginalMimeType(uniqueId, path); @@ -155,7 +163,8 @@ int DrmManagerClientImpl::getDrmObjectType( int uniqueId, const String8& path, const String8& mimeType) { int drmOjectType = DrmObjectType::UNKNOWN; if ((EMPTY_STRING != path) || (EMPTY_STRING != mimeType)) { - drmOjectType = getDrmManagerService()->getDrmObjectType(uniqueId, path, mimeType); + drmOjectType = + getDrmManagerService()->getDrmObjectType(uniqueId, path, mimeType); } return drmOjectType; } @@ -164,35 +173,41 @@ int DrmManagerClientImpl::checkRightsStatus( int uniqueId, const String8& path, int action) { int rightsStatus = RightsStatus::RIGHTS_INVALID; if (EMPTY_STRING != path) { - rightsStatus = getDrmManagerService()->checkRightsStatus(uniqueId, path, action); + rightsStatus = + getDrmManagerService()->checkRightsStatus(uniqueId, path, action); } return rightsStatus; } status_t DrmManagerClientImpl::consumeRights( - int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) { + int uniqueId, sp<DecryptHandle> &decryptHandle, + int action, bool reserve) { status_t status = DRM_ERROR_UNKNOWN; - if (NULL != decryptHandle) { - status = getDrmManagerService()->consumeRights(uniqueId, decryptHandle, action, reserve); + if (NULL != decryptHandle.get()) { + status = getDrmManagerService()->consumeRights( + uniqueId, decryptHandle.get(), action, reserve); } return status; } status_t DrmManagerClientImpl::setPlaybackStatus( - int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position) { + int uniqueId, sp<DecryptHandle> &decryptHandle, + int playbackStatus, int64_t position) { status_t status = DRM_ERROR_UNKNOWN; - if (NULL != decryptHandle) { + if (NULL != decryptHandle.get()) { status = getDrmManagerService()->setPlaybackStatus( - uniqueId, decryptHandle, playbackStatus, position); + uniqueId, decryptHandle.get(), playbackStatus, position); } return status; } bool DrmManagerClientImpl::validateAction( - int uniqueId, const String8& path, int action, const ActionDescription& description) { + int uniqueId, const String8& path, + int action, const ActionDescription& description) { bool retCode = false; if (EMPTY_STRING != path) { - retCode = getDrmManagerService()->validateAction(uniqueId, path, action, description); + retCode = getDrmManagerService()->validateAction( + uniqueId, path, action, description); } return retCode; } @@ -209,7 +224,8 @@ status_t DrmManagerClientImpl::removeAllRights(int uniqueId) { return getDrmManagerService()->removeAllRights(uniqueId); } -int DrmManagerClientImpl::openConvertSession(int uniqueId, const String8& mimeType) { +int DrmManagerClientImpl::openConvertSession( + int uniqueId, const String8& mimeType) { int retCode = INVALID_VALUE; if (EMPTY_STRING != mimeType) { retCode = getDrmManagerService()->openConvertSession(uniqueId, mimeType); @@ -221,12 +237,14 @@ DrmConvertedStatus* DrmManagerClientImpl::convertData( int uniqueId, int convertId, const DrmBuffer* inputData) { DrmConvertedStatus* drmConvertedStatus = NULL; if (NULL != inputData) { - drmConvertedStatus = getDrmManagerService()->convertData(uniqueId, convertId, inputData); + drmConvertedStatus = + getDrmManagerService()->convertData(uniqueId, convertId, inputData); } return drmConvertedStatus; } -DrmConvertedStatus* DrmManagerClientImpl::closeConvertSession(int uniqueId, int convertId) { +DrmConvertedStatus* DrmManagerClientImpl::closeConvertSession( + int uniqueId, int convertId) { return getDrmManagerService()->closeConvertSession(uniqueId, convertId); } @@ -234,17 +252,19 @@ status_t DrmManagerClientImpl::getAllSupportInfo( int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray) { status_t status = DRM_ERROR_UNKNOWN; if ((NULL != drmSupportInfoArray) && (NULL != length)) { - status = getDrmManagerService()->getAllSupportInfo(uniqueId, length, drmSupportInfoArray); + status = getDrmManagerService()->getAllSupportInfo( + uniqueId, length, drmSupportInfoArray); } return status; } -DecryptHandle* DrmManagerClientImpl::openDecryptSession( +sp<DecryptHandle> DrmManagerClientImpl::openDecryptSession( int uniqueId, int fd, off64_t offset, off64_t length) { return getDrmManagerService()->openDecryptSession(uniqueId, fd, offset, length); } -DecryptHandle* DrmManagerClientImpl::openDecryptSession(int uniqueId, const char* uri) { +sp<DecryptHandle> DrmManagerClientImpl::openDecryptSession( + int uniqueId, const char* uri) { DecryptHandle* handle = NULL; if (NULL != uri) { handle = getDrmManagerService()->openDecryptSession(uniqueId, uri); @@ -252,50 +272,57 @@ DecryptHandle* DrmManagerClientImpl::openDecryptSession(int uniqueId, const char return handle; } -status_t DrmManagerClientImpl::closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) { +status_t DrmManagerClientImpl::closeDecryptSession( + int uniqueId, sp<DecryptHandle> &decryptHandle) { status_t status = DRM_ERROR_UNKNOWN; - if (NULL != decryptHandle) { - status = getDrmManagerService()->closeDecryptSession( uniqueId, decryptHandle); + if (NULL != decryptHandle.get()) { + status = getDrmManagerService()->closeDecryptSession( + uniqueId, decryptHandle.get()); } return status; } -status_t DrmManagerClientImpl::initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, - int decryptUnitId, const DrmBuffer* headerInfo) { +status_t DrmManagerClientImpl::initializeDecryptUnit( + int uniqueId, sp<DecryptHandle> &decryptHandle, + int decryptUnitId, const DrmBuffer* headerInfo) { status_t status = DRM_ERROR_UNKNOWN; - if ((NULL != decryptHandle) && (NULL != headerInfo)) { + if ((NULL != decryptHandle.get()) && (NULL != headerInfo)) { status = getDrmManagerService()->initializeDecryptUnit( - uniqueId, decryptHandle, decryptUnitId, headerInfo); + uniqueId, decryptHandle.get(), decryptUnitId, headerInfo); } return status; } -status_t DrmManagerClientImpl::decrypt(int uniqueId, DecryptHandle* decryptHandle, - int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) { +status_t DrmManagerClientImpl::decrypt( + int uniqueId, sp<DecryptHandle> &decryptHandle, + int decryptUnitId, const DrmBuffer* encBuffer, + DrmBuffer** decBuffer, DrmBuffer* IV) { status_t status = DRM_ERROR_UNKNOWN; - if ((NULL != decryptHandle) && (NULL != encBuffer) + if ((NULL != decryptHandle.get()) && (NULL != encBuffer) && (NULL != decBuffer) && (NULL != *decBuffer)) { status = getDrmManagerService()->decrypt( - uniqueId, decryptHandle, decryptUnitId, encBuffer, decBuffer, IV); + uniqueId, decryptHandle.get(), decryptUnitId, + encBuffer, decBuffer, IV); } return status; } status_t DrmManagerClientImpl::finalizeDecryptUnit( - int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) { + int uniqueId, sp<DecryptHandle> &decryptHandle, int decryptUnitId) { status_t status = DRM_ERROR_UNKNOWN; - if (NULL != decryptHandle) { - status - = getDrmManagerService()->finalizeDecryptUnit(uniqueId, decryptHandle, decryptUnitId); + if (NULL != decryptHandle.get()) { + status = getDrmManagerService()->finalizeDecryptUnit( + uniqueId, decryptHandle.get(), decryptUnitId); } return status; } -ssize_t DrmManagerClientImpl::pread(int uniqueId, DecryptHandle* decryptHandle, +ssize_t DrmManagerClientImpl::pread(int uniqueId, sp<DecryptHandle> &decryptHandle, void* buffer, ssize_t numBytes, off64_t offset) { ssize_t retCode = INVALID_VALUE; - if ((NULL != decryptHandle) && (NULL != buffer) && (0 < numBytes)) { - retCode = getDrmManagerService()->pread(uniqueId, decryptHandle, buffer, numBytes, offset); + if ((NULL != decryptHandle.get()) && (NULL != buffer) && (0 < numBytes)) { + retCode = getDrmManagerService()->pread( + uniqueId, decryptHandle.get(), buffer, numBytes, offset); } return retCode; } diff --git a/drm/libdrmframework/include/DrmManagerClientImpl.h b/drm/libdrmframework/include/DrmManagerClientImpl.h index 0a7fcd1..0cba8d4 100644 --- a/drm/libdrmframework/include/DrmManagerClientImpl.h +++ b/drm/libdrmframework/include/DrmManagerClientImpl.h @@ -189,7 +189,7 @@ public: * @return status_t * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure */ - status_t consumeRights(int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve); + status_t consumeRights(int uniqueId, sp<DecryptHandle> &decryptHandle, int action, bool reserve); /** * Informs the DRM engine about the playback actions performed on the DRM files. @@ -203,7 +203,7 @@ public: * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure */ status_t setPlaybackStatus( - int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position); + int uniqueId, sp<DecryptHandle> &decryptHandle, int playbackStatus, int64_t position); /** * Validates whether an action on the DRM content is allowed or not. @@ -303,7 +303,7 @@ public: * @return * Handle for the decryption session */ - DecryptHandle* openDecryptSession(int uniqueId, int fd, off64_t offset, off64_t length); + sp<DecryptHandle> openDecryptSession(int uniqueId, int fd, off64_t offset, off64_t length); /** * Open the decrypt session to decrypt the given protected content @@ -313,7 +313,7 @@ public: * @return * Handle for the decryption session */ - DecryptHandle* openDecryptSession(int uniqueId, const char* uri); + sp<DecryptHandle> openDecryptSession(int uniqueId, const char* uri); /** * Close the decrypt session for the given handle @@ -323,7 +323,7 @@ public: * @return status_t * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure */ - status_t closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle); + status_t closeDecryptSession(int uniqueId, sp<DecryptHandle> &decryptHandle); /** * Initialize decryption for the given unit of the protected content @@ -335,7 +335,7 @@ public: * @return status_t * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure */ - status_t initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, + status_t initializeDecryptUnit(int uniqueId, sp<DecryptHandle> &decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo); /** @@ -355,7 +355,7 @@ public: * DRM_ERROR_SESSION_NOT_OPENED, DRM_ERROR_DECRYPT_UNIT_NOT_INITIALIZED, * DRM_ERROR_DECRYPT for failure. */ - status_t decrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId, + status_t decrypt(int uniqueId, sp<DecryptHandle> &decryptHandle, int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV); /** @@ -367,7 +367,7 @@ public: * @return status_t * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure */ - status_t finalizeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId); + status_t finalizeDecryptUnit(int uniqueId, sp<DecryptHandle> &decryptHandle, int decryptUnitId); /** * Reads the specified number of bytes from an open DRM file. @@ -380,7 +380,7 @@ public: * * @return Number of bytes read. Returns -1 for Failure. */ - ssize_t pread(int uniqueId, DecryptHandle* decryptHandle, + ssize_t pread(int uniqueId, sp<DecryptHandle> &decryptHandle, void* buffer, ssize_t numBytes, off64_t offset); /** diff --git a/include/drm/DrmManagerClient.h b/include/drm/DrmManagerClient.h index 12142bc..5011137 100644 --- a/include/drm/DrmManagerClient.h +++ b/include/drm/DrmManagerClient.h @@ -69,7 +69,7 @@ public: * @return * Handle for the decryption session */ - DecryptHandle* openDecryptSession(int fd, off64_t offset, off64_t length); + sp<DecryptHandle> openDecryptSession(int fd, off64_t offset, off64_t length); /** * Open the decrypt session to decrypt the given protected content @@ -78,7 +78,7 @@ public: * @return * Handle for the decryption session */ - DecryptHandle* openDecryptSession(const char* uri); + sp<DecryptHandle> openDecryptSession(const char* uri); /** * Close the decrypt session for the given handle @@ -87,7 +87,7 @@ public: * @return status_t * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure */ - status_t closeDecryptSession(DecryptHandle* decryptHandle); + status_t closeDecryptSession(sp<DecryptHandle> &decryptHandle); /** * Consumes the rights for a content. @@ -101,7 +101,7 @@ public: * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure. * In case license has been expired, DRM_ERROR_LICENSE_EXPIRED will be returned. */ - status_t consumeRights(DecryptHandle* decryptHandle, int action, bool reserve); + status_t consumeRights(sp<DecryptHandle> &decryptHandle, int action, bool reserve); /** * Informs the DRM engine about the playback actions performed on the DRM files. @@ -113,7 +113,8 @@ public: * @return status_t * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure */ - status_t setPlaybackStatus(DecryptHandle* decryptHandle, int playbackStatus, int64_t position); + status_t setPlaybackStatus( + sp<DecryptHandle> &decryptHandle, int playbackStatus, int64_t position); /** * Initialize decryption for the given unit of the protected content @@ -125,7 +126,7 @@ public: * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure */ status_t initializeDecryptUnit( - DecryptHandle* decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo); + sp<DecryptHandle> &decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo); /** * Decrypt the protected content buffers for the given unit @@ -144,7 +145,7 @@ public: * DRM_ERROR_DECRYPT for failure. */ status_t decrypt( - DecryptHandle* decryptHandle, int decryptUnitId, + sp<DecryptHandle> &decryptHandle, int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV = NULL); /** @@ -155,7 +156,8 @@ public: * @return status_t * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure */ - status_t finalizeDecryptUnit(DecryptHandle* decryptHandle, int decryptUnitId); + status_t finalizeDecryptUnit( + sp<DecryptHandle> &decryptHandle, int decryptUnitId); /** * Reads the specified number of bytes from an open DRM file. @@ -167,7 +169,8 @@ public: * * @return Number of bytes read. Returns -1 for Failure. */ - ssize_t pread(DecryptHandle* decryptHandle, void* buffer, ssize_t numBytes, off64_t offset); + ssize_t pread(sp<DecryptHandle> &decryptHandle, + void* buffer, ssize_t numBytes, off64_t offset); /** * Validates whether an action on the DRM content is allowed or not. diff --git a/include/drm/drm_framework_common.h b/include/drm/drm_framework_common.h index 1758cdd..3ad0330 100644 --- a/include/drm/drm_framework_common.h +++ b/include/drm/drm_framework_common.h @@ -19,6 +19,7 @@ #include <utils/Vector.h> #include <utils/KeyedVector.h> +#include <utils/RefBase.h> #include <utils/String8.h> #include <utils/Errors.h> @@ -240,7 +241,7 @@ public: /** * Defines decryption handle */ -class DecryptHandle { +class DecryptHandle : public RefBase { public: /** * Decryption session Handle @@ -285,10 +286,15 @@ public: decryptId(INVALID_VALUE), mimeType(""), decryptApiType(INVALID_VALUE), - status(INVALID_VALUE) { + status(INVALID_VALUE), + decryptInfo(NULL) { } + ~DecryptHandle() { + delete decryptInfo; decryptInfo = NULL; + } + bool operator<(const DecryptHandle& handle) const { return (decryptId < handle.decryptId); } diff --git a/include/media/mediametadataretriever.h b/include/media/mediametadataretriever.h index e905006..a5cb949 100644 --- a/include/media/mediametadataretriever.h +++ b/include/media/mediametadataretriever.h @@ -47,6 +47,12 @@ enum { METADATA_KEY_ALBUMARTIST = 13, METADATA_KEY_DISC_NUMBER = 14, METADATA_KEY_COMPILATION = 15, + METADATA_KEY_HAS_AUDIO = 16, + METADATA_KEY_HAS_VIDEO = 17, + METADATA_KEY_VIDEO_WIDTH = 18, + METADATA_KEY_VIDEO_HEIGHT = 19, + METADATA_KEY_BITRATE = 20, + // Add more here... }; diff --git a/include/media/stagefright/DataSource.h b/include/media/stagefright/DataSource.h index f95e56a..d30e908 100644 --- a/include/media/stagefright/DataSource.h +++ b/include/media/stagefright/DataSource.h @@ -75,10 +75,10 @@ public: static void RegisterDefaultSniffers(); // for DRM - virtual DecryptHandle* DrmInitialization() { + virtual sp<DecryptHandle> DrmInitialization() { return NULL; } - virtual void getDrmInfo(DecryptHandle **handle, DrmManagerClient **client) {}; + virtual void getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client) {}; virtual String8 getUri() { return String8(); diff --git a/include/media/stagefright/FileSource.h b/include/media/stagefright/FileSource.h index 51a4343..6cf86dc 100644 --- a/include/media/stagefright/FileSource.h +++ b/include/media/stagefright/FileSource.h @@ -38,9 +38,9 @@ public: virtual status_t getSize(off64_t *size); - virtual DecryptHandle* DrmInitialization(); + virtual sp<DecryptHandle> DrmInitialization(); - virtual void getDrmInfo(DecryptHandle **handle, DrmManagerClient **client); + virtual void getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client); protected: virtual ~FileSource(); @@ -52,7 +52,7 @@ private: Mutex mLock; /*for DRM*/ - DecryptHandle *mDecryptHandle; + sp<DecryptHandle> mDecryptHandle; DrmManagerClient *mDrmManagerClient; int64_t mDrmBufOffset; int64_t mDrmBufSize; diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp index 7fb7aed..ca5bc38 100644 --- a/media/libmedia/MediaProfiles.cpp +++ b/media/libmedia/MediaProfiles.cpp @@ -721,6 +721,9 @@ MediaProfiles::createDefaultCamcorderProfiles(MediaProfiles *profiles) createDefaultCamcorderTimeLapseHighProfiles(&highTimeLapseProfile, &highSpecificTimeLapseProfile); profiles->mCamcorderProfiles.add(highTimeLapseProfile); profiles->mCamcorderProfiles.add(highSpecificTimeLapseProfile); + + // We only have the back-facing camera support by default. + profiles->mCameraIds.add(0); } /*static*/ void diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk index 88069e9..e445b74 100644 --- a/media/libstagefright/Android.mk +++ b/media/libstagefright/Android.mk @@ -19,6 +19,7 @@ LOCAL_SRC_FILES:= \ ESDS.cpp \ FileSource.cpp \ FLACExtractor.cpp \ + HTTPBase.cpp \ HTTPStream.cpp \ JPEGSource.cpp \ MP3Extractor.cpp \ @@ -75,7 +76,7 @@ LOCAL_SHARED_LIBRARIES := \ libdrmframework \ libcrypto \ libssl \ - libgui + libgui \ LOCAL_STATIC_LIBRARIES := \ libstagefright_color_conversion \ @@ -101,6 +102,60 @@ LOCAL_STATIC_LIBRARIES := \ libstagefright_g711dec \ libFLAC \ +################################################################################ + +# The following was shamelessly copied from external/webkit/Android.mk and +# currently must follow the same logic to determine how webkit was built and +# if it's safe to link against libchromium.net + +# V8 also requires an ARMv7 CPU, and since we must use jsc, we cannot +# use the Chrome http stack either. +ifneq ($(strip $(ARCH_ARM_HAVE_ARMV7A)),true) + USE_ALT_HTTP := true +endif + +# See if the user has specified a stack they want to use +HTTP_STACK = $(HTTP) +# We default to the Chrome HTTP stack. +DEFAULT_HTTP = chrome +ALT_HTTP = android + +ifneq ($(HTTP_STACK),chrome) + ifneq ($(HTTP_STACK),android) + # No HTTP stack is specified, pickup the one we want as default. + ifeq ($(USE_ALT_HTTP),true) + HTTP_STACK = $(ALT_HTTP) + else + HTTP_STACK = $(DEFAULT_HTTP) + endif + endif +endif + +ifeq ($(HTTP_STACK),chrome) + +LOCAL_SHARED_LIBRARIES += \ + liblog \ + libicuuc \ + libicui18n \ + libz \ + libdl \ + +LOCAL_STATIC_LIBRARIES += \ + libstagefright_chromium_http \ + libchromium_net \ + libwebcore \ + +ifneq ($(TARGET_SIMULATOR),true) +LOCAL_SHARED_LIBRARIES += libstlport +include external/stlport/libstlport.mk +endif + +LOCAL_CPPFLAGS += -DCHROMIUM_AVAILABLE=1 + +endif # ifeq ($(HTTP_STACK),chrome) + +################################################################################ + LOCAL_SHARED_LIBRARIES += \ libstagefright_amrnb_common \ libstagefright_enc_common \ diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp index 5734c7e..0de1988 100644 --- a/media/libstagefright/AwesomePlayer.cpp +++ b/media/libstagefright/AwesomePlayer.cpp @@ -304,7 +304,7 @@ status_t AwesomePlayer::setDataSource_l( return UNKNOWN_ERROR; } - dataSource->getDrmInfo(&mDecryptHandle, &mDrmManagerClient); + dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient); if (mDecryptHandle != NULL) { CHECK(mDrmManagerClient); if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) { @@ -1611,8 +1611,10 @@ status_t AwesomePlayer::finishSetDataSource_l() { if (!strncasecmp("http://", mUri.string(), 7) || !strncasecmp("https://", mUri.string(), 8)) { - mConnectingDataSource = new NuHTTPDataSource( - (mFlags & INCOGNITO) ? NuHTTPDataSource::kFlagIncognito : 0); + mConnectingDataSource = HTTPBase::Create( + (mFlags & INCOGNITO) + ? HTTPBase::kFlagIncognito + : 0); mLock.unlock(); status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders); @@ -1701,7 +1703,8 @@ status_t AwesomePlayer::finishSetDataSource_l() { return UNKNOWN_ERROR; } - dataSource->getDrmInfo(&mDecryptHandle, &mDrmManagerClient); + dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient); + if (mDecryptHandle != NULL) { CHECK(mDrmManagerClient); if (RightsStatus::RIGHTS_VALID == mDecryptHandle->status) { diff --git a/media/libstagefright/DRMExtractor.cpp b/media/libstagefright/DRMExtractor.cpp index 2809df5..c4ed516 100644 --- a/media/libstagefright/DRMExtractor.cpp +++ b/media/libstagefright/DRMExtractor.cpp @@ -41,7 +41,7 @@ namespace android { class DRMSource : public MediaSource { public: DRMSource(const sp<MediaSource> &mediaSource, - DecryptHandle *decryptHandle, + const sp<DecryptHandle> &decryptHandle, DrmManagerClient *managerClient, int32_t trackId, DrmBuffer *ipmpBox); @@ -56,7 +56,7 @@ protected: private: sp<MediaSource> mOriginalMediaSource; - DecryptHandle* mDecryptHandle; + sp<DecryptHandle> mDecryptHandle; DrmManagerClient* mDrmManagerClient; size_t mTrackId; mutable Mutex mDRMLock; @@ -70,7 +70,7 @@ private: //////////////////////////////////////////////////////////////////////////////// DRMSource::DRMSource(const sp<MediaSource> &mediaSource, - DecryptHandle *decryptHandle, + const sp<DecryptHandle> &decryptHandle, DrmManagerClient *managerClient, int32_t trackId, DrmBuffer *ipmpBox) : mOriginalMediaSource(mediaSource), @@ -245,7 +245,7 @@ DRMExtractor::DRMExtractor(const sp<DataSource> &source, const char* mime) mOriginalExtractor->setDrmFlag(true); mOriginalExtractor->getMetaData()->setInt32(kKeyIsDRM, 1); - source->getDrmInfo(&mDecryptHandle, &mDrmManagerClient); + source->getDrmInfo(mDecryptHandle, &mDrmManagerClient); } DRMExtractor::~DRMExtractor() { @@ -281,7 +281,7 @@ sp<MetaData> DRMExtractor::getMetaData() { bool SniffDRM( const sp<DataSource> &source, String8 *mimeType, float *confidence, sp<AMessage> *) { - DecryptHandle *decryptHandle = source->DrmInitialization(); + sp<DecryptHandle> decryptHandle = source->DrmInitialization(); if (decryptHandle != NULL) { if (decryptHandle->decryptApiType == DecryptApiType::CONTAINER_BASED) { diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp index 3b38208..b5c51f4 100644 --- a/media/libstagefright/DataSource.cpp +++ b/media/libstagefright/DataSource.cpp @@ -21,7 +21,7 @@ #include "include/OggExtractor.h" #include "include/MPEG2TSExtractor.h" #include "include/NuCachedSource2.h" -#include "include/NuHTTPDataSource.h" +#include "include/HTTPBase.h" #include "include/DRMExtractor.h" #include "include/FLACExtractor.h" #include "include/AACExtractor.h" @@ -127,7 +127,7 @@ sp<DataSource> DataSource::CreateFromURI( source = new FileSource(uri + 7); } else if (!strncasecmp("http://", uri, 7) || !strncasecmp("https://", uri, 8)) { - sp<NuHTTPDataSource> httpSource = new NuHTTPDataSource; + sp<HTTPBase> httpSource = HTTPBase::Create(); if (httpSource->connect(uri, headers) != OK) { return NULL; } diff --git a/media/libstagefright/FileSource.cpp b/media/libstagefright/FileSource.cpp index 02a78c9..f2f3500 100644 --- a/media/libstagefright/FileSource.cpp +++ b/media/libstagefright/FileSource.cpp @@ -125,7 +125,7 @@ status_t FileSource::getSize(off64_t *size) { return OK; } -DecryptHandle* FileSource::DrmInitialization() { +sp<DecryptHandle> FileSource::DrmInitialization() { if (mDrmManagerClient == NULL) { mDrmManagerClient = new DrmManagerClient(); } @@ -147,8 +147,8 @@ DecryptHandle* FileSource::DrmInitialization() { return mDecryptHandle; } -void FileSource::getDrmInfo(DecryptHandle **handle, DrmManagerClient **client) { - *handle = mDecryptHandle; +void FileSource::getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client) { + handle = mDecryptHandle; *client = mDrmManagerClient; } diff --git a/media/libstagefright/HTTPBase.cpp b/media/libstagefright/HTTPBase.cpp new file mode 100644 index 0000000..58b17a7 --- /dev/null +++ b/media/libstagefright/HTTPBase.cpp @@ -0,0 +1,45 @@ +/* + * 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. + */ + +#include "include/HTTPBase.h" + +#if CHROMIUM_AVAILABLE +#include "include/ChromiumHTTPDataSource.h" +#endif + +#include "include/NuHTTPDataSource.h" + +#include <cutils/properties.h> + +namespace android { + +HTTPBase::HTTPBase() {} + +// static +sp<HTTPBase> HTTPBase::Create(uint32_t flags) { +#if CHROMIUM_AVAILABLE + char value[PROPERTY_VALUE_MAX]; + if (!property_get("media.stagefright.use-chromium", value, NULL) + || (strcasecmp("false", value) && strcmp("0", value))) { + return new ChromiumHTTPDataSource(flags); + } else +#endif + { + return new NuHTTPDataSource(flags); + } +} + +} // namespace android diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp index 7b96d01..1ca2d6d 100644 --- a/media/libstagefright/MPEG4Extractor.cpp +++ b/media/libstagefright/MPEG4Extractor.cpp @@ -262,7 +262,7 @@ static const char *FourCC2MIME(uint32_t fourcc) { MPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source) : mDataSource(source), - mHaveMetadata(false), + mInitCheck(NO_INIT), mHasVideo(false), mFirstTrack(NULL), mLastTrack(NULL), @@ -361,8 +361,8 @@ sp<MetaData> MPEG4Extractor::getTrackMetaData( } status_t MPEG4Extractor::readMetaData() { - if (mHaveMetadata) { - return OK; + if (mInitCheck != NO_INIT) { + return mInitCheck; } off64_t offset = 0; @@ -370,17 +370,20 @@ status_t MPEG4Extractor::readMetaData() { while ((err = parseChunk(&offset, 0)) == OK) { } - if (mHaveMetadata) { + if (mInitCheck == OK) { if (mHasVideo) { mFileMetaData->setCString(kKeyMIMEType, "video/mp4"); } else { mFileMetaData->setCString(kKeyMIMEType, "audio/mp4"); } - return OK; + mInitCheck = verifyIfStreamable(); + } else { + mInitCheck = err; } - return err; + CHECK_NE(err, (status_t)NO_INIT); + return mInitCheck; } void MPEG4Extractor::setDrmFlag(bool flag) { @@ -755,7 +758,7 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { return err; } } else if (chunk_type == FOURCC('m', 'o', 'o', 'v')) { - mHaveMetadata = true; + mInitCheck = OK; if (!mIsDrm) { return UNKNOWN_ERROR; // Return a dummy error. @@ -2077,6 +2080,101 @@ status_t MPEG4Source::read( } } +MPEG4Extractor::Track *MPEG4Extractor::findTrackByMimePrefix( + const char *mimePrefix) { + for (Track *track = mFirstTrack; track != NULL; track = track->next) { + const char *mime; + if (track->meta != NULL + && track->meta->findCString(kKeyMIMEType, &mime) + && !strncasecmp(mime, mimePrefix, strlen(mimePrefix))) { + return track; + } + } + + return NULL; +} + +status_t MPEG4Extractor::verifyIfStreamable() { + if (!(mDataSource->flags() & DataSource::kIsCachingDataSource)) { + return OK; + } + + Track *audio = findTrackByMimePrefix("audio/"); + Track *video = findTrackByMimePrefix("video/"); + + if (audio == NULL || video == NULL) { + return OK; + } + + sp<SampleTable> audioSamples = audio->sampleTable; + sp<SampleTable> videoSamples = video->sampleTable; + + off64_t maxOffsetDiff = 0; + int64_t maxOffsetTimeUs = -1; + + for (uint32_t i = 0; i < videoSamples->countSamples(); ++i) { + off64_t videoOffset; + uint32_t videoTime; + bool isSync; + CHECK_EQ((status_t)OK, videoSamples->getMetaDataForSample( + i, &videoOffset, NULL, &videoTime, &isSync)); + + int64_t videoTimeUs = (int64_t)(videoTime * 1E6 / video->timescale); + + uint32_t reqAudioTime = (videoTimeUs * audio->timescale) / 1000000; + uint32_t j; + if (audioSamples->findSampleAtTime( + reqAudioTime, &j, SampleTable::kFlagClosest) != OK) { + continue; + } + + off64_t audioOffset; + uint32_t audioTime; + CHECK_EQ((status_t)OK, audioSamples->getMetaDataForSample( + j, &audioOffset, NULL, &audioTime)); + + int64_t audioTimeUs = (int64_t)(audioTime * 1E6 / audio->timescale); + + off64_t offsetDiff = videoOffset - audioOffset; + if (offsetDiff < 0) { + offsetDiff = -offsetDiff; + } + +#if 0 + printf("%s%d/%d videoTime %.2f secs audioTime %.2f secs " + "videoOffset %lld audioOffset %lld offsetDiff %lld\n", + isSync ? "*" : " ", + i, + j, + videoTimeUs / 1E6, + audioTimeUs / 1E6, + videoOffset, + audioOffset, + offsetDiff); +#endif + + if (offsetDiff > maxOffsetDiff) { + maxOffsetDiff = offsetDiff; + maxOffsetTimeUs = videoTimeUs; + } + } + +#if 0 + printf("max offset diff: %lld at video time: %.2f secs\n", + maxOffsetDiff, maxOffsetTimeUs / 1E6); +#endif + + if (maxOffsetDiff < 1024 * 1024) { + return OK; + } + + LOGE("This content is not streamable, " + "max offset diff: %lld at video time: %.2f secs", + maxOffsetDiff, maxOffsetTimeUs / 1E6); + + return ERROR_UNSUPPORTED; +} + static bool LegacySniffMPEG4( const sp<DataSource> &source, String8 *mimeType, float *confidence) { uint8_t header[8]; diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp index c7b99b9..7c65612 100644 --- a/media/libstagefright/NuCachedSource2.cpp +++ b/media/libstagefright/NuCachedSource2.cpp @@ -477,11 +477,11 @@ void NuCachedSource2::resumeFetchingIfNecessary() { restartPrefetcherIfNecessary_l(true /* ignore low water threshold */); } -DecryptHandle* NuCachedSource2::DrmInitialization() { +sp<DecryptHandle> NuCachedSource2::DrmInitialization() { return mSource->DrmInitialization(); } -void NuCachedSource2::getDrmInfo(DecryptHandle **handle, DrmManagerClient **client) { +void NuCachedSource2::getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client) { mSource->getDrmInfo(handle, client); } diff --git a/media/libstagefright/NuHTTPDataSource.cpp b/media/libstagefright/NuHTTPDataSource.cpp index b24343f..73daf12 100644 --- a/media/libstagefright/NuHTTPDataSource.cpp +++ b/media/libstagefright/NuHTTPDataSource.cpp @@ -530,7 +530,7 @@ void NuHTTPDataSource::addBandwidthMeasurement_l( } } -DecryptHandle* NuHTTPDataSource::DrmInitialization() { +sp<DecryptHandle> NuHTTPDataSource::DrmInitialization() { if (mDrmManagerClient == NULL) { mDrmManagerClient = new DrmManagerClient(); } @@ -554,8 +554,8 @@ DecryptHandle* NuHTTPDataSource::DrmInitialization() { return mDecryptHandle; } -void NuHTTPDataSource::getDrmInfo(DecryptHandle **handle, DrmManagerClient **client) { - *handle = mDecryptHandle; +void NuHTTPDataSource::getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client) { + handle = mDecryptHandle; *client = mDrmManagerClient; } diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp index ea3b801..c371cd0 100644 --- a/media/libstagefright/StagefrightMetadataRetriever.cpp +++ b/media/libstagefright/StagefrightMetadataRetriever.cpp @@ -411,6 +411,12 @@ void StagefrightMetadataRetriever::parseMetaData() { mMetaData.add(METADATA_KEY_NUM_TRACKS, String8(tmp)); + bool hasAudio = false; + bool hasVideo = false; + int32_t videoWidth = -1; + int32_t videoHeight = -1; + int32_t audioBitrate = -1; + // The overall duration is the duration of the longest track. int64_t maxDurationUs = 0; for (size_t i = 0; i < numTracks; ++i) { @@ -422,12 +428,55 @@ void StagefrightMetadataRetriever::parseMetaData() { maxDurationUs = durationUs; } } + + const char *mime; + if (trackMeta->findCString(kKeyMIMEType, &mime)) { + if (!hasAudio && !strncasecmp("audio/", mime, 6)) { + hasAudio = true; + + if (!trackMeta->findInt32(kKeyBitRate, &audioBitrate)) { + audioBitrate = -1; + } + } else if (!hasVideo && !strncasecmp("video/", mime, 6)) { + hasVideo = true; + + CHECK(trackMeta->findInt32(kKeyWidth, &videoWidth)); + CHECK(trackMeta->findInt32(kKeyHeight, &videoHeight)); + } + } } // The duration value is a string representing the duration in ms. sprintf(tmp, "%lld", (maxDurationUs + 500) / 1000); mMetaData.add(METADATA_KEY_DURATION, String8(tmp)); + if (hasAudio) { + mMetaData.add(METADATA_KEY_HAS_AUDIO, String8("yes")); + } + + if (hasVideo) { + mMetaData.add(METADATA_KEY_HAS_VIDEO, String8("yes")); + + sprintf(tmp, "%d", videoWidth); + mMetaData.add(METADATA_KEY_VIDEO_WIDTH, String8(tmp)); + + sprintf(tmp, "%d", videoHeight); + mMetaData.add(METADATA_KEY_VIDEO_HEIGHT, String8(tmp)); + } + + if (numTracks == 1 && hasAudio && audioBitrate >= 0) { + sprintf(tmp, "%ld", audioBitrate); + mMetaData.add(METADATA_KEY_BITRATE, String8(tmp)); + } else { + off64_t sourceSize; + if (mSource->getSize(&sourceSize) == OK) { + int64_t avgBitRate = (int64_t)(sourceSize * 8E6 / maxDurationUs); + + sprintf(tmp, "%lld", avgBitRate); + mMetaData.add(METADATA_KEY_BITRATE, String8(tmp)); + } + } + if (numTracks == 1) { const char *fileMIME; CHECK(meta->findCString(kKeyMIMEType, &fileMIME)); diff --git a/media/libstagefright/chromium_http/Android.mk b/media/libstagefright/chromium_http/Android.mk new file mode 100644 index 0000000..80b2478 --- /dev/null +++ b/media/libstagefright/chromium_http/Android.mk @@ -0,0 +1,25 @@ +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + ChromiumHTTPDataSource.cpp \ + support.cpp \ + +LOCAL_C_INCLUDES:= \ + $(JNI_H_INCLUDE) \ + frameworks/base/media/libstagefright \ + $(TOP)/frameworks/base/include/media/stagefright/openmax \ + external/chromium \ + external/chromium/android + +LOCAL_CFLAGS += -Wno-multichar + +ifneq ($(TARGET_SIMULATOR),true) +LOCAL_SHARED_LIBRARIES += libstlport +include external/stlport/libstlport.mk +endif + +LOCAL_MODULE:= libstagefright_chromium_http + +include $(BUILD_STATIC_LIBRARY) diff --git a/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp b/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp new file mode 100644 index 0000000..949a5e4 --- /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; +} + +sp<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( + sp<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 + diff --git a/media/libstagefright/chromium_http/support.cpp b/media/libstagefright/chromium_http/support.cpp new file mode 100644 index 0000000..7ac56e8 --- /dev/null +++ b/media/libstagefright/chromium_http/support.cpp @@ -0,0 +1,457 @@ +/* + * 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 "ChromiumHTTPDataSourceSupport" +#include <utils/Log.h> + +#include <media/stagefright/foundation/AString.h> + +#include "support.h" + +#include "android/net/android_network_library_impl.h" +#include "base/thread.h" +#include "net/base/host_resolver.h" +#include "net/base/ssl_config_service.h" +#include "net/http/http_auth_handler_factory.h" +#include "net/http/http_cache.h" +#include "net/proxy/proxy_config_service_android.h" + +#include "include/ChromiumHTTPDataSource.h" + +#include <cutils/properties.h> +#include <media/stagefright/MediaErrors.h> + +namespace android { + +static Mutex gNetworkThreadLock; +static base::Thread *gNetworkThread = NULL; +static scoped_refptr<URLRequestContext> gReqContext; + +static void InitializeNetworkThreadIfNecessary() { + Mutex::Autolock autoLock(gNetworkThreadLock); + if (gNetworkThread == NULL) { + gNetworkThread = new base::Thread("network"); + base::Thread::Options options; + options.message_loop_type = MessageLoop::TYPE_IO; + CHECK(gNetworkThread->StartWithOptions(options)); + + gReqContext = new SfRequestContext; + + net::AndroidNetworkLibrary::RegisterSharedInstance( + new SfNetworkLibrary); + } +} + +static void MY_LOGI(const char *s) { + LOG_PRI(ANDROID_LOG_INFO, LOG_TAG, "%s", s); +} + +static void MY_LOGV(const char *s) { +#if !defined(LOG_NDEBUG) || LOG_NDEBUG == 0 + LOG_PRI(ANDROID_LOG_VERBOSE, LOG_TAG, "%s", s); +#endif +} + +SfNetLog::SfNetLog() + : mNextID(1) { +} + +void SfNetLog::AddEntry( + EventType type, + const base::TimeTicks &time, + const Source &source, + EventPhase phase, + EventParameters *params) { +#if 0 + MY_LOGI(StringPrintf( + "AddEntry time=%s type=%s source=%s phase=%s\n", + TickCountToString(time).c_str(), + EventTypeToString(type), + SourceTypeToString(source.type), + EventPhaseToString(phase)).c_str()); +#endif +} + +uint32 SfNetLog::NextID() { + return mNextID++; +} + +net::NetLog::LogLevel SfNetLog::GetLogLevel() const { + return LOG_ALL; +} + +//////////////////////////////////////////////////////////////////////////////// + +SfRequestContext::SfRequestContext() { + AString ua; + ua.append("stagefright/1.2 (Linux;Android "); + +#if (PROPERTY_VALUE_MAX < 8) +#error "PROPERTY_VALUE_MAX must be at least 8" +#endif + + char value[PROPERTY_VALUE_MAX]; + property_get("ro.build.version.release", value, "Unknown"); + ua.append(value); + ua.append(")"); + + mUserAgent = ua.c_str(); + + net_log_ = new SfNetLog; + + host_resolver_ = + net::CreateSystemHostResolver( + net::HostResolver::kDefaultParallelism, + NULL /* resolver_proc */, + net_log_); + + ssl_config_service_ = + net::SSLConfigService::CreateSystemSSLConfigService(); + + proxy_service_ = net::ProxyService::CreateWithoutProxyResolver( + new net::ProxyConfigServiceAndroid, net_log_); + + http_transaction_factory_ = new net::HttpCache( + host_resolver_, + dnsrr_resolver_, + dns_cert_checker_.get(), + proxy_service_.get(), + ssl_config_service_.get(), + net::HttpAuthHandlerFactory::CreateDefault(host_resolver_), + network_delegate_, + net_log_, + NULL); // backend_factory +} + +const std::string &SfRequestContext::GetUserAgent(const GURL &url) const { + return mUserAgent; +} + +//////////////////////////////////////////////////////////////////////////////// + +SfNetworkLibrary::SfNetworkLibrary() {} + +SfNetworkLibrary::VerifyResult SfNetworkLibrary::VerifyX509CertChain( + const std::vector<std::string>& cert_chain, + const std::string& hostname, + const std::string& auth_type) { + return VERIFY_OK; +} + +//////////////////////////////////////////////////////////////////////////////// + +SfDelegate::SfDelegate() + : mOwner(NULL), + mURLRequest(NULL), + mReadBuffer(new net::IOBufferWithSize(8192)), + mNumBytesRead(0), + mNumBytesTotal(0), + mDataDestination(NULL), + mAtEOS(false) { + InitializeNetworkThreadIfNecessary(); +} + +SfDelegate::~SfDelegate() { + CHECK(mURLRequest == NULL); +} + +void SfDelegate::setOwner(ChromiumHTTPDataSource *owner) { + mOwner = owner; +} + +void SfDelegate::OnReceivedRedirect( + URLRequest *request, const GURL &new_url, bool *defer_redirect) { + MY_LOGI("OnReceivedRedirect"); +} + +void SfDelegate::OnAuthRequired( + URLRequest *request, net::AuthChallengeInfo *auth_info) { + MY_LOGI("OnAuthRequired"); + + inherited::OnAuthRequired(request, auth_info); +} + +void SfDelegate::OnCertificateRequested( + URLRequest *request, net::SSLCertRequestInfo *cert_request_info) { + MY_LOGI("OnCertificateRequested"); + + inherited::OnCertificateRequested(request, cert_request_info); +} + +void SfDelegate::OnSSLCertificateError( + URLRequest *request, int cert_error, net::X509Certificate *cert) { + fprintf(stderr, "OnSSLCertificateError cert_error=%d\n", cert_error); + + inherited::OnSSLCertificateError(request, cert_error, cert); +} + +void SfDelegate::OnGetCookies(URLRequest *request, bool blocked_by_policy) { + MY_LOGI("OnGetCookies"); +} + +void SfDelegate::OnSetCookie( + URLRequest *request, + const std::string &cookie_line, + const net::CookieOptions &options, + bool blocked_by_policy) { + MY_LOGI("OnSetCookie"); +} + +void SfDelegate::OnResponseStarted(URLRequest *request) { + if (request->status().status() != URLRequestStatus::SUCCESS) { + MY_LOGI(StringPrintf( + "Request failed with status %d and os_error %d", + request->status().status(), + request->status().os_error()).c_str()); + + delete mURLRequest; + mURLRequest = NULL; + + mOwner->onConnectionFailed(ERROR_IO); + return; + } else if (mRangeRequested && request->GetResponseCode() != 206) { + MY_LOGI(StringPrintf( + "We requested a content range, but server didn't " + "support that. (responded with %d)", + request->GetResponseCode()).c_str()); + + delete mURLRequest; + mURLRequest = NULL; + + mOwner->onConnectionFailed(-EPIPE); + return; + } else if ((request->GetResponseCode() / 100) != 2) { + MY_LOGI(StringPrintf( + "Server responded with http status %d", + request->GetResponseCode()).c_str()); + + delete mURLRequest; + mURLRequest = NULL; + + mOwner->onConnectionFailed(ERROR_IO); + return; + } + + MY_LOGV("OnResponseStarted"); + + std::string headers; + request->GetAllResponseHeaders(&headers); + + MY_LOGV(StringPrintf("response headers: %s", headers.c_str()).c_str()); + + mOwner->onConnectionEstablished(request->GetExpectedContentSize()); +} + +void SfDelegate::OnReadCompleted(URLRequest *request, int bytes_read) { + if (bytes_read == -1) { + MY_LOGI(StringPrintf( + "OnReadCompleted, read failed, status %d", + request->status().status()).c_str()); + + mOwner->onReadCompleted(ERROR_IO); + return; + } + + MY_LOGV(StringPrintf("OnReadCompleted, read %d bytes", bytes_read).c_str()); + + if (bytes_read < 0) { + MY_LOGI(StringPrintf( + "Read failed w/ status %d\n", + request->status().status()).c_str()); + + mOwner->onReadCompleted(ERROR_IO); + return; + } else if (bytes_read == 0) { + mAtEOS = true; + mOwner->onReadCompleted(mNumBytesRead); + return; + } + + CHECK_GT(bytes_read, 0); + CHECK_LE(mNumBytesRead + bytes_read, mNumBytesTotal); + + memcpy((uint8_t *)mDataDestination + mNumBytesRead, + mReadBuffer->data(), + bytes_read); + + mNumBytesRead += bytes_read; + + readMore(request); +} + +void SfDelegate::readMore(URLRequest *request) { + while (mNumBytesRead < mNumBytesTotal) { + size_t copy = mNumBytesTotal - mNumBytesRead; + if (copy > mReadBuffer->size()) { + copy = mReadBuffer->size(); + } + + int n; + if (request->Read(mReadBuffer, copy, &n)) { + MY_LOGV(StringPrintf("Read %d bytes directly.", n).c_str()); + + CHECK_LE((size_t)n, copy); + + memcpy((uint8_t *)mDataDestination + mNumBytesRead, + mReadBuffer->data(), + n); + + mNumBytesRead += n; + + if (n == 0) { + mAtEOS = true; + break; + } + } else { + MY_LOGV("readMore pending read"); + + if (request->status().status() != URLRequestStatus::IO_PENDING) { + MY_LOGI(StringPrintf( + "Direct read failed w/ status %d\n", + request->status().status()).c_str()); + + mOwner->onReadCompleted(ERROR_IO); + return; + } + + return; + } + } + + mOwner->onReadCompleted(mNumBytesRead); +} + +void SfDelegate::initiateConnection( + const char *uri, + const KeyedVector<String8, String8> *headers, + off64_t offset) { + GURL url(uri); + + MessageLoop *loop = gNetworkThread->message_loop(); + loop->PostTask( + FROM_HERE, + NewRunnableFunction( + &SfDelegate::OnInitiateConnectionWrapper, + this, + url, + headers, + offset)); + +} + +// static +void SfDelegate::OnInitiateConnectionWrapper( + SfDelegate *me, GURL url, + const KeyedVector<String8, String8> *headers, + off64_t offset) { + me->onInitiateConnection(url, headers, offset); +} + +void SfDelegate::onInitiateConnection( + const GURL &url, + const KeyedVector<String8, String8> *extra, + off64_t offset) { + CHECK(mURLRequest == NULL); + + mURLRequest = new URLRequest(url, this); + mAtEOS = false; + + mRangeRequested = false; + + if (offset != 0 || extra != NULL) { + net::HttpRequestHeaders headers = + mURLRequest->extra_request_headers(); + + if (offset != 0) { + headers.AddHeaderFromString( + StringPrintf("Range: bytes=%lld-", offset).c_str()); + + mRangeRequested = true; + } + + if (extra != NULL) { + for (size_t i = 0; i < extra->size(); ++i) { + AString s; + s.append(extra->keyAt(i).string()); + s.append(": "); + s.append(extra->valueAt(i).string()); + + headers.AddHeaderFromString(s.c_str()); + } + } + + mURLRequest->SetExtraRequestHeaders(headers); + } + + mURLRequest->set_context(gReqContext); + + mURLRequest->Start(); +} + +void SfDelegate::initiateDisconnect() { + MessageLoop *loop = gNetworkThread->message_loop(); + loop->PostTask( + FROM_HERE, + NewRunnableFunction( + &SfDelegate::OnInitiateDisconnectWrapper, this)); +} + +// static +void SfDelegate::OnInitiateDisconnectWrapper(SfDelegate *me) { + me->onInitiateDisconnect(); +} + +void SfDelegate::onInitiateDisconnect() { + mURLRequest->Cancel(); + + delete mURLRequest; + mURLRequest = NULL; + + mOwner->onDisconnectComplete(); +} + +void SfDelegate::initiateRead(void *data, size_t size) { + MessageLoop *loop = gNetworkThread->message_loop(); + loop->PostTask( + FROM_HERE, + NewRunnableFunction( + &SfDelegate::OnInitiateReadWrapper, this, data, size)); +} + +// static +void SfDelegate::OnInitiateReadWrapper( + SfDelegate *me, void *data, size_t size) { + me->onInitiateRead(data, size); +} + +void SfDelegate::onInitiateRead(void *data, size_t size) { + CHECK(mURLRequest != NULL); + + mNumBytesRead = 0; + mNumBytesTotal = size; + mDataDestination = data; + + if (mAtEOS) { + mOwner->onReadCompleted(0); + return; + } + + readMore(mURLRequest); +} + +} // namespace android + diff --git a/media/libstagefright/chromium_http/support.h b/media/libstagefright/chromium_http/support.h new file mode 100644 index 0000000..634ac93 --- /dev/null +++ b/media/libstagefright/chromium_http/support.h @@ -0,0 +1,159 @@ +/* + * 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. + */ + +#ifndef SUPPORT_H_ + +#define SUPPORT_H_ + +#include <assert.h> + +#include "net/base/net_log.h" +#include "net/url_request/url_request.h" +#include "net/url_request/url_request_context.h" +#include "net/base/android_network_library.h" +#include "net/base/io_buffer.h" + +#include <utils/KeyedVector.h> +#include <utils/String8.h> + +namespace android { + +struct SfNetLog : public net::NetLog { + SfNetLog(); + + virtual void AddEntry( + EventType type, + const base::TimeTicks &time, + const Source &source, + EventPhase phase, + EventParameters *params); + + virtual uint32 NextID(); + virtual LogLevel GetLogLevel() const; + +private: + uint32 mNextID; + + DISALLOW_EVIL_CONSTRUCTORS(SfNetLog); +}; + +struct SfRequestContext : public URLRequestContext { + SfRequestContext(); + + virtual const std::string &GetUserAgent(const GURL &url) const; + +private: + std::string mUserAgent; + + DISALLOW_EVIL_CONSTRUCTORS(SfRequestContext); +}; + +// This is required for https support, we don't really verify certificates, +// we accept anything... +struct SfNetworkLibrary : public net::AndroidNetworkLibrary { + SfNetworkLibrary(); + + virtual VerifyResult VerifyX509CertChain( + const std::vector<std::string>& cert_chain, + const std::string& hostname, + const std::string& auth_type); + +private: + DISALLOW_EVIL_CONSTRUCTORS(SfNetworkLibrary); +}; + +struct ChromiumHTTPDataSource; + +struct SfDelegate : public URLRequest::Delegate { + SfDelegate(); + virtual ~SfDelegate(); + + void initiateConnection( + const char *uri, + const KeyedVector<String8, String8> *headers, + off64_t offset); + + void initiateDisconnect(); + void initiateRead(void *data, size_t size); + + void setOwner(ChromiumHTTPDataSource *mOwner); + + virtual void OnReceivedRedirect( + URLRequest *request, const GURL &new_url, bool *defer_redirect); + + virtual void OnAuthRequired( + URLRequest *request, net::AuthChallengeInfo *auth_info); + + virtual void OnCertificateRequested( + URLRequest *request, net::SSLCertRequestInfo *cert_request_info); + + virtual void OnSSLCertificateError( + URLRequest *request, int cert_error, net::X509Certificate *cert); + + virtual void OnGetCookies(URLRequest *request, bool blocked_by_policy); + + virtual void OnSetCookie( + URLRequest *request, + const std::string &cookie_line, + const net::CookieOptions &options, + bool blocked_by_policy); + + virtual void OnResponseStarted(URLRequest *request); + + virtual void OnReadCompleted(URLRequest *request, int bytes_read); + +private: + typedef Delegate inherited; + + ChromiumHTTPDataSource *mOwner; + + URLRequest *mURLRequest; + scoped_refptr<net::IOBufferWithSize> mReadBuffer; + + size_t mNumBytesRead; + size_t mNumBytesTotal; + void *mDataDestination; + + bool mRangeRequested; + bool mAtEOS; + + void readMore(URLRequest *request); + + static void OnInitiateConnectionWrapper( + SfDelegate *me, + GURL url, + const KeyedVector<String8, String8> *headers, + off64_t offset); + + static void OnInitiateDisconnectWrapper(SfDelegate *me); + + static void OnInitiateReadWrapper( + SfDelegate *me, void *data, size_t size); + + void onInitiateConnection( + const GURL &url, + const KeyedVector<String8, String8> *headers, + off64_t offset); + + void onInitiateDisconnect(); + void onInitiateRead(void *data, size_t size); + + DISALLOW_EVIL_CONSTRUCTORS(SfDelegate); +}; + +} // namespace android + +#endif // SUPPORT_H_ diff --git a/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp b/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp index 59dd740..0ba42ff 100644 --- a/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp +++ b/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp @@ -14,6 +14,9 @@ * limitations under the License. */ +//#define LOG_NDEBUG 0 +#define LOG_TAG "MP3Decoder" + #include "MP3Decoder.h" #include "include/pvmp3decoder_api.h" @@ -175,7 +178,12 @@ status_t MP3Decoder::read( != NO_DECODING_ERROR) { LOGV("mp3 decoder returned error %d", decoderErr); - if (decoderErr != NO_ENOUGH_MAIN_DATA_ERROR) { + if (decoderErr != NO_ENOUGH_MAIN_DATA_ERROR || + mConfig->outputFrameSize == 0) { + + if (mConfig->outputFrameSize == 0) { + LOGE("Output frame size is 0"); + } buffer->release(); buffer = NULL; diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp index f0cd6a0..8e1bdf3 100644 --- a/media/libstagefright/httplive/LiveSession.cpp +++ b/media/libstagefright/httplive/LiveSession.cpp @@ -23,7 +23,7 @@ #include "LiveDataSource.h" #include "include/M3UParser.h" -#include "include/NuHTTPDataSource.h" +#include "include/HTTPBase.h" #include <cutils/properties.h> #include <media/stagefright/foundation/hexdump.h> @@ -45,9 +45,9 @@ LiveSession::LiveSession(uint32_t flags) : mFlags(flags), mDataSource(new LiveDataSource), mHTTPDataSource( - new NuHTTPDataSource( + HTTPBase::Create( (mFlags & kFlagIncognito) - ? NuHTTPDataSource::kFlagIncognito + ? HTTPBase::kFlagIncognito : 0)), mPrevBandwidthIndex(-1), mLastPlaylistFetchTimeUs(-1), @@ -625,7 +625,12 @@ status_t LiveSession::decryptBuffer( } else { key = new ABuffer(16); - sp<NuHTTPDataSource> keySource = new NuHTTPDataSource; + sp<HTTPBase> keySource = + HTTPBase::Create( + (mFlags & kFlagIncognito) + ? HTTPBase::kFlagIncognito + : 0); + status_t err = keySource->connect(keyURI.c_str()); if (err == OK) { diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h index 4e6f75c..b26f202 100644 --- a/media/libstagefright/include/AwesomePlayer.h +++ b/media/libstagefright/include/AwesomePlayer.h @@ -18,7 +18,7 @@ #define AWESOME_PLAYER_H_ -#include "NuHTTPDataSource.h" +#include "HTTPBase.h" #include "TimedEventQueue.h" #include <media/MediaPlayerInterface.h> @@ -209,7 +209,7 @@ private: MediaBuffer *mVideoBuffer; - sp<NuHTTPDataSource> mConnectingDataSource; + sp<HTTPBase> mConnectingDataSource; sp<NuCachedSource2> mCachedSource; sp<ALooper> mLooper; @@ -217,7 +217,7 @@ private: sp<ARTSPController> mConnectingRTSPController; DrmManagerClient *mDrmManagerClient; - DecryptHandle *mDecryptHandle; + sp<DecryptHandle> mDecryptHandle; status_t setDataSource_l( const char *uri, diff --git a/media/libstagefright/include/ChromiumHTTPDataSource.h b/media/libstagefright/include/ChromiumHTTPDataSource.h new file mode 100644 index 0000000..af49059 --- /dev/null +++ b/media/libstagefright/include/ChromiumHTTPDataSource.h @@ -0,0 +1,127 @@ +/* + * 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. + */ + +#ifndef CHROME_HTTP_DATA_SOURCE_H_ + +#define CHROME_HTTP_DATA_SOURCE_H_ + +#include <media/stagefright/foundation/AString.h> +#include <utils/threads.h> + +#include "HTTPBase.h" + +namespace android { + +struct SfDelegate; + +struct ChromiumHTTPDataSource : public HTTPBase { + ChromiumHTTPDataSource(uint32_t flags = 0); + + virtual status_t connect( + const char *uri, + const KeyedVector<String8, String8> *headers = NULL, + off64_t offset = 0); + + virtual void disconnect(); + + virtual status_t initCheck() const; + + virtual ssize_t readAt(off64_t offset, void *data, size_t size); + virtual status_t getSize(off64_t *size); + virtual uint32_t flags(); + + virtual bool estimateBandwidth(int32_t *bandwidth_bps); + + virtual sp<DecryptHandle> DrmInitialization(); + + virtual void getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client); + + virtual String8 getUri(); + +protected: + virtual ~ChromiumHTTPDataSource(); + +private: + friend struct SfDelegate; + + enum State { + DISCONNECTED, + CONNECTING, + CONNECTED, + READING, + DISCONNECTING + }; + + struct BandwidthEntry { + int64_t mDelayUs; + size_t mNumBytes; + }; + + const uint32_t mFlags; + + mutable Mutex mLock; + Condition mCondition; + + State mState; + + SfDelegate *mDelegate; + + AString mURI; + KeyedVector<String8, String8> mHeaders; + + off64_t mCurrentOffset; + + // Any connection error or the result of a read operation + // (for the lattter this is the number of bytes read, if successful). + ssize_t mIOResult; + + int64_t mContentSize; + + List<BandwidthEntry> mBandwidthHistory; + size_t mNumBandwidthHistoryItems; + int64_t mTotalTransferTimeUs; + size_t mTotalTransferBytes; + + sp<DecryptHandle> mDecryptHandle; + DrmManagerClient *mDrmManagerClient; + + void disconnect_l(); + + status_t connect_l( + const char *uri, + const KeyedVector<String8, String8> *headers, + off64_t offset); + + static void InitiateRead( + ChromiumHTTPDataSource *me, void *data, size_t size); + + void initiateRead(void *data, size_t size); + + void onConnectionEstablished(int64_t contentSize); + void onConnectionFailed(status_t err); + void onReadCompleted(ssize_t size); + void onDisconnectComplete(); + + void addBandwidthMeasurement_l(size_t numBytes, int64_t delayUs); + + void clearDRMState_l(); + + DISALLOW_EVIL_CONSTRUCTORS(ChromiumHTTPDataSource); +}; + +} // namespace android + +#endif // CHROME_HTTP_DATA_SOURCE_H_ diff --git a/media/libstagefright/include/DRMExtractor.h b/media/libstagefright/include/DRMExtractor.h index 9881cc1..b4e4afb 100644 --- a/media/libstagefright/include/DRMExtractor.h +++ b/media/libstagefright/include/DRMExtractor.h @@ -45,7 +45,7 @@ private: sp<DataSource> mDataSource; sp<MediaExtractor> mOriginalExtractor; - DecryptHandle* mDecryptHandle; + sp<DecryptHandle> mDecryptHandle; DrmManagerClient* mDrmManagerClient; DRMExtractor(const DRMExtractor &); diff --git a/media/libstagefright/include/HTTPBase.h b/media/libstagefright/include/HTTPBase.h new file mode 100644 index 0000000..6cec390 --- /dev/null +++ b/media/libstagefright/include/HTTPBase.h @@ -0,0 +1,53 @@ +/* + * 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. + */ + +#ifndef HTTP_BASE_H_ + +#define HTTP_BASE_H_ + +#include <media/stagefright/foundation/ABase.h> +#include <media/stagefright/DataSource.h> + +namespace android { + +struct HTTPBase : public DataSource { + enum Flags { + // Don't log any URLs. + kFlagIncognito = 1 + }; + + HTTPBase(); + + virtual status_t connect( + const char *uri, + const KeyedVector<String8, String8> *headers = NULL, + off64_t offset = 0) = 0; + + virtual void disconnect() = 0; + + // Returns true if bandwidth could successfully be estimated, + // false otherwise. + virtual bool estimateBandwidth(int32_t *bandwidth_bps) = 0; + + static sp<HTTPBase> Create(uint32_t flags = 0); + +private: + DISALLOW_EVIL_CONSTRUCTORS(HTTPBase); +}; + +} // namespace android + +#endif // HTTP_BASE_H_ diff --git a/media/libstagefright/include/LiveSession.h b/media/libstagefright/include/LiveSession.h index 3fe5d4e..2b5ea0e 100644 --- a/media/libstagefright/include/LiveSession.h +++ b/media/libstagefright/include/LiveSession.h @@ -26,7 +26,7 @@ struct ABuffer; struct DataSource; struct LiveDataSource; struct M3UParser; -struct NuHTTPDataSource; +struct HTTPBase; struct LiveSession : public AHandler { enum Flags { @@ -75,7 +75,7 @@ private: sp<LiveDataSource> mDataSource; - sp<NuHTTPDataSource> mHTTPDataSource; + sp<HTTPBase> mHTTPDataSource; AString mMasterURL; Vector<BandwidthItem> mBandwidthItems; diff --git a/media/libstagefright/include/MPEG4Extractor.h b/media/libstagefright/include/MPEG4Extractor.h index 04e8a6a..d9ef208 100644 --- a/media/libstagefright/include/MPEG4Extractor.h +++ b/media/libstagefright/include/MPEG4Extractor.h @@ -57,7 +57,7 @@ private: }; sp<DataSource> mDataSource; - bool mHaveMetadata; + status_t mInitCheck; bool mHasVideo; Track *mFirstTrack, *mLastTrack; @@ -90,6 +90,10 @@ private: status_t parseTrackHeader(off64_t data_offset, off64_t data_size); + Track *findTrackByMimePrefix(const char *mimePrefix); + + status_t verifyIfStreamable(); + MPEG4Extractor(const MPEG4Extractor &); MPEG4Extractor &operator=(const MPEG4Extractor &); }; diff --git a/media/libstagefright/include/NuCachedSource2.h b/media/libstagefright/include/NuCachedSource2.h index 022804c..02d5817 100644 --- a/media/libstagefright/include/NuCachedSource2.h +++ b/media/libstagefright/include/NuCachedSource2.h @@ -37,8 +37,8 @@ struct NuCachedSource2 : public DataSource { virtual status_t getSize(off64_t *size); virtual uint32_t flags(); - virtual DecryptHandle* DrmInitialization(); - virtual void getDrmInfo(DecryptHandle **handle, DrmManagerClient **client); + virtual sp<DecryptHandle> DrmInitialization(); + virtual void getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client); virtual String8 getUri(); //////////////////////////////////////////////////////////////////////////// diff --git a/media/libstagefright/include/NuHTTPDataSource.h b/media/libstagefright/include/NuHTTPDataSource.h index 2569568..7dd5d59 100644 --- a/media/libstagefright/include/NuHTTPDataSource.h +++ b/media/libstagefright/include/NuHTTPDataSource.h @@ -18,28 +18,24 @@ #define NU_HTTP_DATA_SOURCE_H_ -#include <media/stagefright/DataSource.h> #include <utils/List.h> #include <utils/String8.h> #include <utils/threads.h> #include "HTTPStream.h" +#include "include/HTTPBase.h" namespace android { -struct NuHTTPDataSource : public DataSource { - enum Flags { - // Don't log any URLs. - kFlagIncognito = 1 - }; +struct NuHTTPDataSource : public HTTPBase { NuHTTPDataSource(uint32_t flags = 0); - status_t connect( + virtual status_t connect( const char *uri, const KeyedVector<String8, String8> *headers = NULL, off64_t offset = 0); - void disconnect(); + virtual void disconnect(); virtual status_t initCheck() const; @@ -49,10 +45,10 @@ struct NuHTTPDataSource : public DataSource { // Returns true if bandwidth could successfully be estimated, // false otherwise. - bool estimateBandwidth(int32_t *bandwidth_bps); + virtual bool estimateBandwidth(int32_t *bandwidth_bps); - virtual DecryptHandle* DrmInitialization(); - virtual void getDrmInfo(DecryptHandle **handle, DrmManagerClient **client); + virtual sp<DecryptHandle> DrmInitialization(); + virtual void getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client); virtual String8 getUri(); protected: @@ -98,7 +94,7 @@ private: int64_t mTotalTransferTimeUs; size_t mTotalTransferBytes; - DecryptHandle *mDecryptHandle; + sp<DecryptHandle> mDecryptHandle; DrmManagerClient *mDrmManagerClient; status_t connect( |