OMXNodeInstance.cpp revision 318ad9c1d9d6515026dfc2c021359d27decaa7a1
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    Mutex::Autolock autoLock(mLock);
111
112    OMX_ERRORTYPE err = OMX_MasterFreeHandle(mHandle);
113    mHandle = NULL;
114
115    if (err != OMX_ErrorNone) {
116        LOGE("FreeHandle FAILED with error 0x%08x.", err);
117    }
118
119    mOwner->invalidateNodeID(mNodeID);
120    mNodeID = NULL;
121
122    LOGI("OMXNodeInstance going away.");
123    delete this;
124
125    return StatusFromOMXError(err);
126}
127
128status_t OMXNodeInstance::sendCommand(
129        OMX_COMMANDTYPE cmd, OMX_S32 param) {
130    Mutex::Autolock autoLock(mLock);
131
132    OMX_ERRORTYPE err = OMX_SendCommand(mHandle, cmd, param, NULL);
133    return StatusFromOMXError(err);
134}
135
136status_t OMXNodeInstance::getParameter(
137        OMX_INDEXTYPE index, void *params, size_t size) {
138    Mutex::Autolock autoLock(mLock);
139
140    OMX_ERRORTYPE err = OMX_GetParameter(mHandle, index, params);
141    return StatusFromOMXError(err);
142}
143
144status_t OMXNodeInstance::setParameter(
145        OMX_INDEXTYPE index, const void *params, size_t size) {
146    Mutex::Autolock autoLock(mLock);
147
148    OMX_ERRORTYPE err = OMX_SetParameter(
149            mHandle, index, const_cast<void *>(params));
150
151    return StatusFromOMXError(err);
152}
153
154status_t OMXNodeInstance::getConfig(
155        OMX_INDEXTYPE index, void *params, size_t size) {
156    Mutex::Autolock autoLock(mLock);
157
158    OMX_ERRORTYPE err = OMX_GetConfig(mHandle, index, params);
159    return StatusFromOMXError(err);
160}
161
162status_t OMXNodeInstance::setConfig(
163        OMX_INDEXTYPE index, const void *params, size_t size) {
164    Mutex::Autolock autoLock(mLock);
165
166    OMX_ERRORTYPE err = OMX_SetConfig(
167            mHandle, index, const_cast<void *>(params));
168
169    return StatusFromOMXError(err);
170}
171
172status_t OMXNodeInstance::useBuffer(
173        OMX_U32 portIndex, const sp<IMemory> &params,
174        OMX::buffer_id *buffer) {
175    Mutex::Autolock autoLock(mLock);
176
177    BufferMeta *buffer_meta = new BufferMeta(params);
178
179    OMX_BUFFERHEADERTYPE *header;
180
181    OMX_ERRORTYPE err = OMX_UseBuffer(
182            mHandle, &header, portIndex, buffer_meta,
183            params->size(), static_cast<OMX_U8 *>(params->pointer()));
184
185    if (err != OMX_ErrorNone) {
186        LOGE("OMX_UseBuffer failed with error %d (0x%08x)", err, err);
187
188        delete buffer_meta;
189        buffer_meta = NULL;
190
191        *buffer = 0;
192
193        return UNKNOWN_ERROR;
194    }
195
196    *buffer = header;
197
198    return OK;
199}
200
201status_t OMXNodeInstance::allocateBuffer(
202        OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer) {
203    Mutex::Autolock autoLock(mLock);
204
205    BufferMeta *buffer_meta = new BufferMeta(size);
206
207    OMX_BUFFERHEADERTYPE *header;
208
209    OMX_ERRORTYPE err = OMX_AllocateBuffer(
210            mHandle, &header, portIndex, buffer_meta, size);
211
212    if (err != OMX_ErrorNone) {
213        LOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err);
214
215        delete buffer_meta;
216        buffer_meta = NULL;
217
218        *buffer = 0;
219
220        return UNKNOWN_ERROR;
221    }
222
223    *buffer = header;
224
225    return OK;
226}
227
228status_t OMXNodeInstance::allocateBufferWithBackup(
229        OMX_U32 portIndex, const sp<IMemory> &params,
230        OMX::buffer_id *buffer) {
231    Mutex::Autolock autoLock(mLock);
232
233    BufferMeta *buffer_meta = new BufferMeta(params, true);
234
235    OMX_BUFFERHEADERTYPE *header;
236
237    OMX_ERRORTYPE err = OMX_AllocateBuffer(
238            mHandle, &header, portIndex, buffer_meta, params->size());
239
240    if (err != OMX_ErrorNone) {
241        LOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err);
242
243        delete buffer_meta;
244        buffer_meta = NULL;
245
246        *buffer = 0;
247
248        return UNKNOWN_ERROR;
249    }
250
251    *buffer = header;
252
253    return OK;
254}
255
256status_t OMXNodeInstance::freeBuffer(
257        OMX_U32 portIndex, OMX::buffer_id buffer) {
258    Mutex::Autolock autoLock(mLock);
259
260    OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
261    BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate);
262
263    OMX_ERRORTYPE err = OMX_FreeBuffer(mHandle, portIndex, header);
264
265    delete buffer_meta;
266    buffer_meta = NULL;
267
268    return StatusFromOMXError(err);
269}
270
271status_t OMXNodeInstance::fillBuffer(OMX::buffer_id buffer) {
272    Mutex::Autolock autoLock(mLock);
273
274    OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
275    header->nFilledLen = 0;
276    header->nOffset = 0;
277    header->nFlags = 0;
278
279    OMX_ERRORTYPE err = OMX_FillThisBuffer(mHandle, header);
280
281    return StatusFromOMXError(err);
282}
283
284status_t OMXNodeInstance::emptyBuffer(
285        OMX::buffer_id buffer,
286        OMX_U32 rangeOffset, OMX_U32 rangeLength,
287        OMX_U32 flags, OMX_TICKS timestamp) {
288    Mutex::Autolock autoLock(mLock);
289
290    OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
291    header->nFilledLen = rangeLength;
292    header->nOffset = rangeOffset;
293    header->nFlags = flags;
294    header->nTimeStamp = timestamp;
295
296    BufferMeta *buffer_meta =
297        static_cast<BufferMeta *>(header->pAppPrivate);
298    buffer_meta->CopyToOMX(header);
299
300    OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header);
301
302    return StatusFromOMXError(err);
303}
304
305status_t OMXNodeInstance::getExtensionIndex(
306        const char *parameterName, OMX_INDEXTYPE *index) {
307    Mutex::Autolock autoLock(mLock);
308
309    OMX_ERRORTYPE err = OMX_GetExtensionIndex(
310            mHandle, const_cast<char *>(parameterName), index);
311
312    return StatusFromOMXError(err);
313}
314
315void OMXNodeInstance::onMessage(const omx_message &msg) {
316    if (msg.type == omx_message::FILL_BUFFER_DONE) {
317        OMX_BUFFERHEADERTYPE *buffer =
318            static_cast<OMX_BUFFERHEADERTYPE *>(
319                    msg.u.extended_buffer_data.buffer);
320
321        BufferMeta *buffer_meta =
322            static_cast<BufferMeta *>(buffer->pAppPrivate);
323
324        buffer_meta->CopyFromOMX(buffer);
325    }
326
327    mObserver->onMessage(msg);
328}
329
330void OMXNodeInstance::onObserverDied() {
331    LOGE("!!! Observer died. Quickly, do something, ... anything...");
332
333    // Try to force shutdown of the node and hope for the best.
334    freeNode();
335}
336
337void OMXNodeInstance::onGetHandleFailed() {
338    delete this;
339}
340
341// static
342OMX_ERRORTYPE OMXNodeInstance::OnEvent(
343        OMX_IN OMX_HANDLETYPE hComponent,
344        OMX_IN OMX_PTR pAppData,
345        OMX_IN OMX_EVENTTYPE eEvent,
346        OMX_IN OMX_U32 nData1,
347        OMX_IN OMX_U32 nData2,
348        OMX_IN OMX_PTR pEventData) {
349    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
350    return instance->owner()->OnEvent(
351            instance->nodeID(), eEvent, nData1, nData2, pEventData);
352}
353
354// static
355OMX_ERRORTYPE OMXNodeInstance::OnEmptyBufferDone(
356        OMX_IN OMX_HANDLETYPE hComponent,
357        OMX_IN OMX_PTR pAppData,
358        OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
359    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
360    return instance->owner()->OnEmptyBufferDone(instance->nodeID(), pBuffer);
361}
362
363// static
364OMX_ERRORTYPE OMXNodeInstance::OnFillBufferDone(
365        OMX_IN OMX_HANDLETYPE hComponent,
366        OMX_IN OMX_PTR pAppData,
367        OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
368    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
369    return instance->owner()->OnFillBufferDone(instance->nodeID(), pBuffer);
370}
371
372}  // namespace android
373
374