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