OMXClient.cpp revision 0c89199745bc1bf05b997fc7c342017807676b6f
1/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "OMXClient"
19#include <utils/Log.h>
20
21#include <sys/socket.h>
22
23#include <binder/IServiceManager.h>
24#include <media/IMediaPlayerService.h>
25#include <media/IOMX.h>
26#include <media/stagefright/MediaDebug.h>
27#include <media/stagefright/OMXClient.h>
28
29namespace android {
30
31OMXClient::OMXClient() {
32}
33
34OMXClient::~OMXClient() {
35    disconnect();
36}
37
38status_t OMXClient::connect() {
39    Mutex::Autolock autoLock(mLock);
40
41    sp<IServiceManager> sm = defaultServiceManager();
42    sp<IBinder> binder = sm->getService(String16("media.player"));
43    sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
44
45    CHECK(service.get() != NULL);
46
47    mOMX = service->createOMX();
48    CHECK(mOMX.get() != NULL);
49
50    mReflector = new OMXClientReflector(this);
51
52    return OK;
53}
54
55void OMXClient::disconnect() {
56    Mutex::Autolock autoLock(mLock);
57
58    if (mReflector.get() != NULL) {
59        return;
60    }
61
62    CHECK(mObservers.isEmpty());
63
64    mReflector->reset();
65    mReflector.clear();
66}
67
68status_t OMXClient::registerObserver(
69        IOMX::node_id node, OMXObserver *observer) {
70    Mutex::Autolock autoLock(&mLock);
71
72    ssize_t index = mObservers.indexOfKey(node);
73    if (index >= 0) {
74        return UNKNOWN_ERROR;
75    }
76
77    mObservers.add(node, observer);
78    observer->start();
79
80    mOMX->observe_node(node, mReflector);
81
82    return OK;
83}
84
85void OMXClient::unregisterObserver(IOMX::node_id node) {
86    Mutex::Autolock autoLock(mLock);
87
88    ssize_t index = mObservers.indexOfKey(node);
89    CHECK(index >= 0);
90
91    if (index < 0) {
92        return;
93    }
94
95    OMXObserver *observer = mObservers.valueAt(index);
96    observer->stop();
97    mObservers.removeItemsAt(index);
98}
99
100bool OMXClient::onOMXMessage(const omx_message &msg) {
101    bool done = false;
102
103    switch (msg.type) {
104        case omx_message::EVENT:
105        {
106            LOGV("OnEvent node:%p event:%d data1:%ld data2:%ld",
107                 msg.u.event_data.node,
108                 msg.u.event_data.event,
109                 msg.u.event_data.data1,
110                 msg.u.event_data.data2);
111
112            break;
113        }
114
115        case omx_message::FILL_BUFFER_DONE:
116        {
117            LOGV("FillBufferDone %p", msg.u.extended_buffer_data.buffer);
118            break;
119        }
120
121        case omx_message::EMPTY_BUFFER_DONE:
122        {
123            LOGV("EmptyBufferDone %p", msg.u.buffer_data.buffer);
124            break;
125        }
126
127        default:
128            LOGE("received unknown omx_message type %d", msg.type);
129            break;
130    }
131
132    Mutex::Autolock autoLock(mLock);
133    ssize_t index = mObservers.indexOfKey(msg.node);
134
135    if (index >= 0) {
136        mObservers.editValueAt(index)->postMessage(msg);
137    }
138
139    return done;
140}
141
142////////////////////////////////////////////////////////////////////////////////
143
144OMXObserver::OMXObserver() {
145}
146
147OMXObserver::~OMXObserver() {
148}
149
150void OMXObserver::start() {
151    pthread_attr_t attr;
152    pthread_attr_init(&attr);
153    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
154
155    int err = pthread_create(&mThread, &attr, ThreadWrapper, this);
156    CHECK_EQ(err, 0);
157
158    pthread_attr_destroy(&attr);
159}
160
161void OMXObserver::stop() {
162    omx_message msg;
163    msg.type = omx_message::QUIT_OBSERVER;
164    postMessage(msg);
165
166    void *dummy;
167    pthread_join(mThread, &dummy);
168}
169
170void OMXObserver::postMessage(const omx_message &msg) {
171    Mutex::Autolock autoLock(mLock);
172    mQueue.push_back(msg);
173    mQueueNotEmpty.signal();
174}
175
176// static
177void *OMXObserver::ThreadWrapper(void *me) {
178    static_cast<OMXObserver *>(me)->threadEntry();
179
180    return NULL;
181}
182
183void OMXObserver::threadEntry() {
184    for (;;) {
185        omx_message msg;
186
187        {
188            Mutex::Autolock autoLock(mLock);
189            while (mQueue.empty()) {
190                mQueueNotEmpty.wait(mLock);
191            }
192
193            msg = *mQueue.begin();
194            mQueue.erase(mQueue.begin());
195        }
196
197        if (msg.type == omx_message::QUIT_OBSERVER) {
198            break;
199        }
200
201        onOMXMessage(msg);
202    }
203}
204
205////////////////////////////////////////////////////////////////////////////////
206
207OMXClientReflector::OMXClientReflector(OMXClient *client)
208    : mClient(client) {
209}
210
211void OMXClientReflector::on_message(const omx_message &msg) {
212    if (mClient != NULL) {
213        mClient->onOMXMessage(msg);
214    }
215}
216
217void OMXClientReflector::reset() {
218    mClient = NULL;
219}
220
221}  // namespace android
222