blob: 5423ffae0c102b9fd499e037838e97eefc3ad515 [file] [log] [blame]
/*
* 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 <utils/Log.h>
#include <sys/socket.h>
#undef NDEBUG
#include <assert.h>
#include <binder/IServiceManager.h>
#include <media/IMediaPlayerService.h>
#include <media/IOMX.h>
#include <media/stagefright/OMXClient.h>
namespace android {
OMXClient::OMXClient() {
}
OMXClient::~OMXClient() {
disconnect();
}
status_t OMXClient::connect() {
Mutex::Autolock autoLock(mLock);
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder = sm->getService(String16("media.player"));
sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(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<OMXObserver *>(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