michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim:set ts=2 sw=2 sts=2 et cindent: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: //#define LOG_NDEBUG 0 michael@0: #define LOG_TAG "OMXCodecProxy" michael@0: michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: michael@0: #include "nsDebug.h" michael@0: michael@0: #include "IMediaResourceManagerService.h" michael@0: michael@0: #include "OMXCodecProxy.h" michael@0: michael@0: namespace android { michael@0: michael@0: // static michael@0: sp OMXCodecProxy::Create( michael@0: const sp &omx, michael@0: const sp &meta, bool createEncoder, michael@0: const sp &source, michael@0: const char *matchComponentName, michael@0: uint32_t flags, michael@0: const sp &nativeWindow) michael@0: { michael@0: sp proxy; michael@0: michael@0: const char *mime; michael@0: if (!meta->findCString(kKeyMIMEType, &mime)) { michael@0: return nullptr; michael@0: } michael@0: michael@0: if (!strncasecmp(mime, "video/", 6)) { michael@0: proxy = new OMXCodecProxy(omx, meta, createEncoder, source, matchComponentName, flags, nativeWindow); michael@0: } michael@0: return proxy; michael@0: } michael@0: michael@0: michael@0: OMXCodecProxy::OMXCodecProxy( michael@0: const sp &omx, michael@0: const sp &meta, michael@0: bool createEncoder, michael@0: const sp &source, michael@0: const char *matchComponentName, michael@0: uint32_t flags, michael@0: const sp &nativeWindow) michael@0: : mOMX(omx), michael@0: mSrcMeta(meta), michael@0: mIsEncoder(createEncoder), michael@0: mSource(source), michael@0: mComponentName(nullptr), michael@0: mFlags(flags), michael@0: mNativeWindow(nativeWindow), michael@0: mState(MediaResourceManagerClient::CLIENT_STATE_WAIT_FOR_RESOURCE) michael@0: { michael@0: } michael@0: michael@0: OMXCodecProxy::~OMXCodecProxy() michael@0: { michael@0: mState = MediaResourceManagerClient::CLIENT_STATE_SHUTDOWN; michael@0: michael@0: if (mOMXCodec.get()) { michael@0: wp tmp = mOMXCodec; michael@0: mOMXCodec.clear(); michael@0: while (tmp.promote() != nullptr) { michael@0: // this value come from stagefrigh's AwesomePlayer. michael@0: usleep(1000); michael@0: } michael@0: } michael@0: // Complete all pending Binder ipc transactions michael@0: IPCThreadState::self()->flushCommands(); michael@0: michael@0: if (mManagerService.get() && mClient.get()) { michael@0: mManagerService->cancelClient(mClient); michael@0: } michael@0: michael@0: mSource.clear(); michael@0: free(mComponentName); michael@0: mComponentName = nullptr; michael@0: } michael@0: michael@0: MediaResourceManagerClient::State OMXCodecProxy::getState() michael@0: { michael@0: Mutex::Autolock autoLock(mLock); michael@0: return mState; michael@0: } michael@0: michael@0: void OMXCodecProxy::setEventListener(const wp& listener) michael@0: { michael@0: Mutex::Autolock autoLock(mLock); michael@0: mEventListener = listener; michael@0: } michael@0: michael@0: void OMXCodecProxy::notifyStatusChangedLocked() michael@0: { michael@0: if (mEventListener != nullptr) { michael@0: sp listener = mEventListener.promote(); michael@0: if (listener != nullptr) { michael@0: listener->statusChanged(); michael@0: } michael@0: } michael@0: } michael@0: michael@0: void OMXCodecProxy::requestResource() michael@0: { michael@0: Mutex::Autolock autoLock(mLock); michael@0: michael@0: if (mClient.get()) { michael@0: return; michael@0: } michael@0: sp listener = this; michael@0: mClient = new MediaResourceManagerClient(listener); michael@0: michael@0: mManagerService = mClient->getMediaResourceManagerService(); michael@0: if (!mManagerService.get()) { michael@0: mClient = nullptr; michael@0: return; michael@0: } michael@0: michael@0: mManagerService->requestMediaResource(mClient, MediaResourceManagerClient::HW_VIDEO_DECODER); michael@0: } michael@0: michael@0: bool OMXCodecProxy::IsWaitingResources() michael@0: { michael@0: Mutex::Autolock autoLock(mLock); michael@0: return mState == MediaResourceManagerClient::CLIENT_STATE_WAIT_FOR_RESOURCE; michael@0: } michael@0: michael@0: // called on Binder ipc thread michael@0: void OMXCodecProxy::statusChanged(int event) michael@0: { michael@0: Mutex::Autolock autoLock(mLock); michael@0: michael@0: if (mState != MediaResourceManagerClient::CLIENT_STATE_WAIT_FOR_RESOURCE) { michael@0: return; michael@0: } michael@0: michael@0: mState = (MediaResourceManagerClient::State) event; michael@0: if (mState != MediaResourceManagerClient::CLIENT_STATE_RESOURCE_ASSIGNED) { michael@0: return; michael@0: } michael@0: michael@0: const char *mime; michael@0: if (!mSrcMeta->findCString(kKeyMIMEType, &mime)) { michael@0: mState = MediaResourceManagerClient::CLIENT_STATE_SHUTDOWN; michael@0: notifyStatusChangedLocked(); michael@0: return; michael@0: } michael@0: michael@0: if (!strncasecmp(mime, "video/", 6)) { michael@0: sp codec; michael@0: mOMXCodec = OMXCodec::Create(mOMX, mSrcMeta, mIsEncoder, mSource, mComponentName, mFlags, mNativeWindow); michael@0: if (mOMXCodec == nullptr) { michael@0: mState = MediaResourceManagerClient::CLIENT_STATE_SHUTDOWN; michael@0: notifyStatusChangedLocked(); michael@0: return; michael@0: } michael@0: // Check if this video is sized such that we're comfortable michael@0: // possibly using an OMX decoder. michael@0: int32_t maxWidth, maxHeight; michael@0: char propValue[PROPERTY_VALUE_MAX]; michael@0: property_get("ro.moz.omx.hw.max_width", propValue, "-1"); michael@0: maxWidth = atoi(propValue); michael@0: property_get("ro.moz.omx.hw.max_height", propValue, "-1"); michael@0: maxHeight = atoi(propValue); michael@0: michael@0: int32_t width = -1, height = -1; michael@0: if (maxWidth > 0 && maxHeight > 0 && michael@0: !(mOMXCodec->getFormat()->findInt32(kKeyWidth, &width) && michael@0: mOMXCodec->getFormat()->findInt32(kKeyHeight, &height) && michael@0: width * height <= maxWidth * maxHeight)) { michael@0: printf_stderr("Failed to get video size, or it was too large for HW decoder ( but )", michael@0: width, height, maxWidth, maxHeight); michael@0: mOMXCodec.clear(); michael@0: mState = MediaResourceManagerClient::CLIENT_STATE_SHUTDOWN; michael@0: notifyStatusChangedLocked(); michael@0: return; michael@0: } michael@0: michael@0: if (mOMXCodec->start() != OK) { michael@0: NS_WARNING("Couldn't start OMX video source"); michael@0: mOMXCodec.clear(); michael@0: mState = MediaResourceManagerClient::CLIENT_STATE_SHUTDOWN; michael@0: notifyStatusChangedLocked(); michael@0: return; michael@0: } michael@0: } michael@0: notifyStatusChangedLocked(); michael@0: } michael@0: michael@0: status_t OMXCodecProxy::start(MetaData *params) michael@0: { michael@0: Mutex::Autolock autoLock(mLock); michael@0: michael@0: if (mState != MediaResourceManagerClient::CLIENT_STATE_RESOURCE_ASSIGNED) { michael@0: return NO_INIT; michael@0: } michael@0: CHECK(mOMXCodec.get() != nullptr); michael@0: return mOMXCodec->start(); michael@0: } michael@0: michael@0: status_t OMXCodecProxy::stop() michael@0: { michael@0: Mutex::Autolock autoLock(mLock); michael@0: michael@0: if (mState != MediaResourceManagerClient::CLIENT_STATE_RESOURCE_ASSIGNED) { michael@0: return NO_INIT; michael@0: } michael@0: CHECK(mOMXCodec.get() != nullptr); michael@0: return mOMXCodec->stop(); michael@0: } michael@0: michael@0: sp OMXCodecProxy::getFormat() michael@0: { michael@0: Mutex::Autolock autoLock(mLock); michael@0: michael@0: if (mState != MediaResourceManagerClient::CLIENT_STATE_RESOURCE_ASSIGNED) { michael@0: sp meta = new MetaData; michael@0: return meta; michael@0: } michael@0: CHECK(mOMXCodec.get() != nullptr); michael@0: return mOMXCodec->getFormat(); michael@0: } michael@0: michael@0: status_t OMXCodecProxy::read(MediaBuffer **buffer, const ReadOptions *options) michael@0: { michael@0: Mutex::Autolock autoLock(mLock); michael@0: michael@0: if (mState != MediaResourceManagerClient::CLIENT_STATE_RESOURCE_ASSIGNED) { michael@0: return NO_INIT; michael@0: } michael@0: CHECK(mOMXCodec.get() != nullptr); michael@0: return mOMXCodec->read(buffer, options); michael@0: } michael@0: michael@0: status_t OMXCodecProxy::pause() michael@0: { michael@0: Mutex::Autolock autoLock(mLock); michael@0: michael@0: if (mState != MediaResourceManagerClient::CLIENT_STATE_RESOURCE_ASSIGNED) { michael@0: return NO_INIT; michael@0: } michael@0: CHECK(mOMXCodec.get() != nullptr); michael@0: return mOMXCodec->pause(); michael@0: } michael@0: michael@0: } // namespace android