OMXNodeInstance.cpp revision 47bed1a7755ed58fa5d4c0d35b20468deb83bd60
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 "OMXNodeInstance"
19#include <utils/Log.h>
20
21#include "../include/OMXNodeInstance.h"
22
23#include "pv_omxcore.h"
24
25#include <binder/IMemory.h>
26#include <media/stagefright/MediaDebug.h>
27
28namespace android {
29
30struct BufferMeta {
31    BufferMeta(const sp<IMemory> &mem, bool is_backup = false)
32        : mMem(mem),
33          mIsBackup(is_backup) {
34    }
35
36    BufferMeta(size_t size)
37        : mSize(size),
38          mIsBackup(false) {
39    }
40
41    void CopyFromOMX(const OMX_BUFFERHEADERTYPE *header) {
42        if (!mIsBackup) {
43            return;
44        }
45
46        memcpy((OMX_U8 *)mMem->pointer() + header->nOffset,
47               header->pBuffer + header->nOffset,
48               header->nFilledLen);
49    }
50
51    void CopyToOMX(const OMX_BUFFERHEADERTYPE *header) {
52        if (!mIsBackup) {
53            return;
54        }
55
56        memcpy(header->pBuffer + header->nOffset,
57               (const OMX_U8 *)mMem->pointer() + header->nOffset,
58               header->nFilledLen);
59    }
60
61private:
62    sp<IMemory> mMem;
63    size_t mSize;
64    bool mIsBackup;
65
66    BufferMeta(const BufferMeta &);
67    BufferMeta &operator=(const BufferMeta &);
68};
69
70// static
71OMX_CALLBACKTYPE OMXNodeInstance::kCallbacks = {
72    &OnEvent, &OnEmptyBufferDone, &OnFillBufferDone
73};
74
75OMXNodeInstance::OMXNodeInstance(
76        OMX *owner, const sp<IOMXObserver> &observer)
77    : mOwner(owner),
78      mNodeID(NULL),
79      mHandle(NULL),
80      mObserver(observer) {
81}
82
83OMXNodeInstance::~OMXNodeInstance() {
84    CHECK_EQ(mHandle, NULL);
85}
86
87void OMXNodeInstance::setHandle(OMX::node_id node_id, OMX_HANDLETYPE handle) {
88    CHECK_EQ(mHandle, NULL);
89    mNodeID = node_id;
90    mHandle = handle;
91}
92
93OMX *OMXNodeInstance::owner() {
94    return mOwner;
95}
96
97sp<IOMXObserver> OMXNodeInstance::observer() {
98    return mObserver;
99}
100
101OMX::node_id OMXNodeInstance::nodeID() {
102    return mNodeID;
103}
104
105static status_t StatusFromOMXError(OMX_ERRORTYPE err) {
106    return (err == OMX_ErrorNone) ? OK : UNKNOWN_ERROR;
107}
108
109status_t OMXNodeInstance::freeNode() {
110    OMX_ERRORTYPE err = OMX_MasterFreeHandle(mHandle);
111    mHandle = NULL;
112
113    if (err != OMX_ErrorNone) {
114        LOGE("FreeHandle FAILED with error 0x%08x.", err);
115    }
116
117    mOwner->invalidateNodeID(mNodeID);
118    mNodeID = NULL;
119
120    LOGV("OMXNodeInstance going away.");
121    delete this;
122
123    return StatusFromOMXError(err);
124}
125
126status_t OMXNodeInstance::sendCommand(
127        OMX_COMMANDTYPE cmd, OMX_S32 param) {
128    Mutex::Autolock autoLock(mLock);
129
130    OMX_ERRORTYPE err = OMX_SendCommand(mHandle, cmd, param, NULL);
131    return StatusFromOMXError(err);
132}
133
134status_t OMXNodeInstance::getParameter(
135        OMX_INDEXTYPE index, void *params, size_t size) {
136    Mutex::Autolock autoLock(mLock);
137
138    OMX_ERRORTYPE err = OMX_GetParameter(mHandle, index, params);
139    return StatusFromOMXError(err);
140}
141
142status_t OMXNodeInstance::setParameter(
143        OMX_INDEXTYPE index, const void *params, size_t size) {
144    Mutex::Autolock autoLock(mLock);
145
146    OMX_ERRORTYPE err = OMX_SetParameter(
147            mHandle, index, const_cast<void *>(params));
148
149    return StatusFromOMXError(err);
150}
151
152status_t OMXNodeInstance::getConfig(
153        OMX_INDEXTYPE index, void *params, size_t size) {
154    Mutex::Autolock autoLock(mLock);
155
156    OMX_ERRORTYPE err = OMX_GetConfig(mHandle, index, params);
157    return StatusFromOMXError(err);
158}
159
160status_t OMXNodeInstance::setConfig(
161        OMX_INDEXTYPE index, const void *params, size_t size) {
162    Mutex::Autolock autoLock(mLock);
163
164    OMX_ERRORTYPE err = OMX_SetConfig(
165            mHandle, index, const_cast<void *>(params));
166
167    return StatusFromOMXError(err);
168}
169
170status_t OMXNodeInstance::useBuffer(
171        OMX_U32 portIndex, const sp<IMemory> &params,
172        OMX::buffer_id *buffer) {
173    Mutex::Autolock autoLock(mLock);
174
175    BufferMeta *buffer_meta = new BufferMeta(params);
176
177    OMX_BUFFERHEADERTYPE *header;
178
179    OMX_ERRORTYPE err = OMX_UseBuffer(
180            mHandle, &header, portIndex, buffer_meta,
181            params->size(), static_cast<OMX_U8 *>(params->pointer()));
182
183    if (err != OMX_ErrorNone) {
184        LOGE("OMX_UseBuffer failed with error %d (0x%08x)", err, err);
185
186        delete buffer_meta;
187        buffer_meta = NULL;
188
189        *buffer = 0;
190
191        return UNKNOWN_ERROR;
192    }
193
194    *buffer = header;
195
196    return OK;
197}
198
199status_t OMXNodeInstance::allocateBuffer(
200        OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer) {
201    Mutex::Autolock autoLock(mLock);
202
203    BufferMeta *buffer_meta = new BufferMeta(size);
204
205    OMX_BUFFERHEADERTYPE *header;
206
207    OMX_ERRORTYPE err = OMX_AllocateBuffer(
208            mHandle, &header, portIndex, buffer_meta, size);
209
210    if (err != OMX_ErrorNone) {
211        LOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err);
212
213        delete buffer_meta;
214        buffer_meta = NULL;
215
216        *buffer = 0;
217
218        return UNKNOWN_ERROR;
219    }
220
221    *buffer = header;
222
223    return OK;
224}
225
226status_t OMXNodeInstance::allocateBufferWithBackup(
227        OMX_U32 portIndex, const sp<IMemory> &params,
228        OMX::buffer_id *buffer) {
229    Mutex::Autolock autoLock(mLock);
230
231    BufferMeta *buffer_meta = new BufferMeta(params, true);
232
233    OMX_BUFFERHEADERTYPE *header;
234
235    OMX_ERRORTYPE err = OMX_AllocateBuffer(
236            mHandle, &header, portIndex, buffer_meta, params->size());
237
238    if (err != OMX_ErrorNone) {
239        LOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err);
240
241        delete buffer_meta;
242        buffer_meta = NULL;
243
244        *buffer = 0;
245
246        return UNKNOWN_ERROR;
247    }
248
249    *buffer = header;
250
251    return OK;
252}
253
254status_t OMXNodeInstance::freeBuffer(
255        OMX_U32 portIndex, OMX::buffer_id buffer) {
256    Mutex::Autolock autoLock(mLock);
257
258    OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
259    BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate);
260
261    OMX_ERRORTYPE err = OMX_FreeBuffer(mHandle, portIndex, header);
262
263    delete buffer_meta;
264    buffer_meta = NULL;
265
266    return StatusFromOMXError(err);
267}
268
269status_t OMXNodeInstance::fillBuffer(OMX::buffer_id buffer) {
270    Mutex::Autolock autoLock(mLock);
271
272    OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
273    header->nFilledLen = 0;
274    header->nOffset = 0;
275    header->nFlags = 0;
276
277    OMX_ERRORTYPE err = OMX_FillThisBuffer(mHandle, header);
278
279    return StatusFromOMXError(err);
280}
281
282status_t OMXNodeInstance::emptyBuffer(
283        OMX::buffer_id buffer,
284        OMX_U32 rangeOffset, OMX_U32 rangeLength,
285        OMX_U32 flags, OMX_TICKS timestamp) {
286    Mutex::Autolock autoLock(mLock);
287
288    OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
289    header->nFilledLen = rangeLength;
290    header->nOffset = rangeOffset;
291    header->nFlags = flags;
292    header->nTimeStamp = timestamp;
293
294    BufferMeta *buffer_meta =
295        static_cast<BufferMeta *>(header->pAppPrivate);
296    buffer_meta->CopyToOMX(header);
297
298    OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header);
299
300    return StatusFromOMXError(err);
301}
302
303status_t OMXNodeInstance::getExtensionIndex(
304        const char *parameterName, OMX_INDEXTYPE *index) {
305    Mutex::Autolock autoLock(mLock);
306
307    OMX_ERRORTYPE err = OMX_GetExtensionIndex(
308            mHandle, const_cast<char *>(parameterName), index);
309
310    return StatusFromOMXError(err);
311}
312
313void OMXNodeInstance::onMessage(const omx_message &msg) {
314    if (msg.type == omx_message::FILL_BUFFER_DONE) {
315        OMX_BUFFERHEADERTYPE *buffer =
316            static_cast<OMX_BUFFERHEADERTYPE *>(
317                    msg.u.extended_buffer_data.buffer);
318
319        BufferMeta *buffer_meta =
320            static_cast<BufferMeta *>(buffer->pAppPrivate);
321
322        buffer_meta->CopyFromOMX(buffer);
323    }
324
325    mObserver->onMessage(msg);
326}
327
328void OMXNodeInstance::onObserverDied() {
329    LOGE("!!! Observer died. Quickly, do something, ... anything...");
330
331    // Try to force shutdown of the node and hope for the best.
332    freeNode();
333}
334
335void OMXNodeInstance::onGetHandleFailed() {
336    delete this;
337}
338
339// static
340OMX_ERRORTYPE OMXNodeInstance::OnEvent(
341        OMX_IN OMX_HANDLETYPE hComponent,
342        OMX_IN OMX_PTR pAppData,
343        OMX_IN OMX_EVENTTYPE eEvent,
344        OMX_IN OMX_U32 nData1,
345        OMX_IN OMX_U32 nData2,
346        OMX_IN OMX_PTR pEventData) {
347    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
348    return instance->owner()->OnEvent(
349            instance->nodeID(), eEvent, nData1, nData2, pEventData);
350}
351
352// static
353OMX_ERRORTYPE OMXNodeInstance::OnEmptyBufferDone(
354        OMX_IN OMX_HANDLETYPE hComponent,
355        OMX_IN OMX_PTR pAppData,
356        OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
357    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
358    return instance->owner()->OnEmptyBufferDone(instance->nodeID(), pBuffer);
359}
360
361// static
362OMX_ERRORTYPE OMXNodeInstance::OnFillBufferDone(
363        OMX_IN OMX_HANDLETYPE hComponent,
364        OMX_IN OMX_PTR pAppData,
365        OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
366    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
367    return instance->owner()->OnFillBufferDone(instance->nodeID(), pBuffer);
368}
369
370}  // namespace android
371
372