/* * Copyright (C) 2009 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 "OMXClient" #include #include #undef NDEBUG #include #include #include #include #include namespace android { OMXClient::OMXClient() { } OMXClient::~OMXClient() { disconnect(); } status_t OMXClient::connect() { Mutex::Autolock autoLock(mLock); sp sm = defaultServiceManager(); sp binder = sm->getService(String16("media.player")); sp service = interface_cast(binder); assert(service.get() != NULL); mOMX = service->createOMX(); assert(mOMX.get() != NULL); mReflector = new OMXClientReflector(this); return OK; } void OMXClient::disconnect() { Mutex::Autolock autoLock(mLock); if (mReflector.get() != NULL) { return; } assert(mObservers.isEmpty()); mReflector->reset(); mReflector.clear(); } status_t OMXClient::registerObserver( IOMX::node_id node, OMXObserver *observer) { Mutex::Autolock autoLock(&mLock); ssize_t index = mObservers.indexOfKey(node); if (index >= 0) { return UNKNOWN_ERROR; } mObservers.add(node, observer); observer->start(); mOMX->observe_node(node, mReflector); return OK; } void OMXClient::unregisterObserver(IOMX::node_id node) { Mutex::Autolock autoLock(mLock); ssize_t index = mObservers.indexOfKey(node); assert(index >= 0); if (index < 0) { return; } OMXObserver *observer = mObservers.valueAt(index); observer->stop(); mObservers.removeItemsAt(index); } bool OMXClient::onOMXMessage(const omx_message &msg) { bool done = false; switch (msg.type) { case omx_message::EVENT: { LOGV("OnEvent node:%p event:%d data1:%ld data2:%ld", msg.u.event_data.node, msg.u.event_data.event, msg.u.event_data.data1, msg.u.event_data.data2); break; } case omx_message::FILL_BUFFER_DONE: { LOGV("FillBufferDone %p", msg.u.extended_buffer_data.buffer); break; } case omx_message::EMPTY_BUFFER_DONE: { LOGV("EmptyBufferDone %p", msg.u.buffer_data.buffer); break; } default: LOGE("received unknown omx_message type %d", msg.type); break; } Mutex::Autolock autoLock(mLock); ssize_t index = mObservers.indexOfKey(msg.node); if (index >= 0) { mObservers.editValueAt(index)->postMessage(msg); } return done; } //////////////////////////////////////////////////////////////////////////////// OMXObserver::OMXObserver() { } OMXObserver::~OMXObserver() { } void OMXObserver::start() { pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); int err = pthread_create(&mThread, &attr, ThreadWrapper, this); assert(err == 0); pthread_attr_destroy(&attr); } void OMXObserver::stop() { omx_message msg; msg.type = omx_message::QUIT_OBSERVER; postMessage(msg); void *dummy; pthread_join(mThread, &dummy); } void OMXObserver::postMessage(const omx_message &msg) { Mutex::Autolock autoLock(mLock); mQueue.push_back(msg); mQueueNotEmpty.signal(); } // static void *OMXObserver::ThreadWrapper(void *me) { static_cast(me)->threadEntry(); return NULL; } void OMXObserver::threadEntry() { for (;;) { omx_message msg; { Mutex::Autolock autoLock(mLock); while (mQueue.empty()) { mQueueNotEmpty.wait(mLock); } msg = *mQueue.begin(); mQueue.erase(mQueue.begin()); } if (msg.type == omx_message::QUIT_OBSERVER) { break; } onOMXMessage(msg); } } //////////////////////////////////////////////////////////////////////////////// OMXClientReflector::OMXClientReflector(OMXClient *client) : mClient(client) { } void OMXClientReflector::on_message(const omx_message &msg) { if (mClient != NULL) { mClient->onOMXMessage(msg); } } void OMXClientReflector::reset() { mClient = NULL; } } // namespace android