OMXClient.cpp revision 408b8e1073385d0d09bb96b9952f84731a0b4aeb
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#undef NDEBUG
24#include <assert.h>
25
26#include <binder/IServiceManager.h>
27#include <media/IMediaPlayerService.h>
28#include <media/IOMX.h>
29#include <media/stagefright/OMXClient.h>
30
31namespace android {
32
33OMXClient::OMXClient() {
34}
35
36OMXClient::~OMXClient() {
37    disconnect();
38}
39
40status_t OMXClient::connect() {
41    Mutex::Autolock autoLock(mLock);
42
43    sp<IServiceManager> sm = defaultServiceManager();
44    sp<IBinder> binder = sm->getService(String16("media.player"));
45    sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
46
47    assert(service.get() != NULL);
48
49    mOMX = service->createOMX();
50    assert(mOMX.get() != NULL);
51
52    mReflector = new OMXClientReflector(this);
53
54    return OK;
55}
56
57void OMXClient::disconnect() {
58    Mutex::Autolock autoLock(mLock);
59
60    if (mReflector.get() != NULL) {
61        return;
62    }
63
64    assert(mObservers.isEmpty());
65
66    mReflector->reset();
67    mReflector.clear();
68}
69
70status_t OMXClient::registerObserver(
71        IOMX::node_id node, OMXObserver *observer) {
72    Mutex::Autolock autoLock(&mLock);
73
74    ssize_t index = mObservers.indexOfKey(node);
75    if (index >= 0) {
76        return UNKNOWN_ERROR;
77    }
78
79    mObservers.add(node, observer);
80    observer->start();
81
82    mOMX->observe_node(node, mReflector);
83
84    return OK;
85}
86
87void OMXClient::unregisterObserver(IOMX::node_id node) {
88    Mutex::Autolock autoLock(mLock);
89
90    ssize_t index = mObservers.indexOfKey(node);
91    assert(index >= 0);
92
93    if (index < 0) {
94        return;
95    }
96
97    OMXObserver *observer = mObservers.valueAt(index);
98    observer->stop();
99    mObservers.removeItemsAt(index);
100}
101
102bool OMXClient::onOMXMessage(const omx_message &msg) {
103    bool done = false;
104
105    switch (msg.type) {
106        case omx_message::EVENT:
107        {
108            LOGV("OnEvent node:%p event:%d data1:%ld data2:%ld",
109                 msg.u.event_data.node,
110                 msg.u.event_data.event,
111                 msg.u.event_data.data1,
112                 msg.u.event_data.data2);
113
114            break;
115        }
116
117        case omx_message::FILL_BUFFER_DONE:
118        {
119            LOGV("FillBufferDone %p", msg.u.extended_buffer_data.buffer);
120            break;
121        }
122
123        case omx_message::EMPTY_BUFFER_DONE:
124        {
125            LOGV("EmptyBufferDone %p", msg.u.buffer_data.buffer);
126            break;
127        }
128
129        default:
130            LOGE("received unknown omx_message type %d", msg.type);
131            break;
132    }
133
134    Mutex::Autolock autoLock(mLock);
135    ssize_t index = mObservers.indexOfKey(msg.u.buffer_data.node);
136
137    if (index >= 0) {
138        mObservers.editValueAt(index)->postMessage(msg);
139    }
140
141    return done;
142}
143
144////////////////////////////////////////////////////////////////////////////////
145
146OMXObserver::OMXObserver() {
147}
148
149OMXObserver::~OMXObserver() {
150}
151
152void OMXObserver::start() {
153    pthread_attr_t attr;
154    pthread_attr_init(&attr);
155    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
156
157    int err = pthread_create(&mThread, &attr, ThreadWrapper, this);
158    assert(err == 0);
159
160    pthread_attr_destroy(&attr);
161}
162
163void OMXObserver::stop() {
164    omx_message msg;
165    msg.type = omx_message::QUIT_OBSERVER;
166    postMessage(msg);
167
168    void *dummy;
169    pthread_join(mThread, &dummy);
170}
171
172void OMXObserver::postMessage(const omx_message &msg) {
173    Mutex::Autolock autoLock(mLock);
174    mQueue.push_back(msg);
175    mQueueNotEmpty.signal();
176}
177
178// static
179void *OMXObserver::ThreadWrapper(void *me) {
180    static_cast<OMXObserver *>(me)->threadEntry();
181
182    return NULL;
183}
184
185void OMXObserver::threadEntry() {
186    for (;;) {
187        omx_message msg;
188
189        {
190            Mutex::Autolock autoLock(mLock);
191            while (mQueue.empty()) {
192                mQueueNotEmpty.wait(mLock);
193            }
194
195            msg = *mQueue.begin();
196            mQueue.erase(mQueue.begin());
197        }
198
199        if (msg.type == omx_message::QUIT_OBSERVER) {
200            break;
201        }
202
203        onOMXMessage(msg);
204    }
205}
206
207////////////////////////////////////////////////////////////////////////////////
208
209OMXClientReflector::OMXClientReflector(OMXClient *client)
210    : mClient(client) {
211}
212
213void OMXClientReflector::on_message(const omx_message &msg) {
214    if (mClient != NULL) {
215        mClient->onOMXMessage(msg);
216    }
217}
218
219void OMXClientReflector::reset() {
220    mClient = NULL;
221}
222
223}  // namespace android
224