OMXNodeInstance.cpp revision 570a3cb7582daa030cb38eedc5eb6a06f86ecc7f
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#include "OMXMaster.h"
23
24#include <OMX_Component.h>
25
26#include <binder/IMemory.h>
27#include <media/stagefright/MediaDebug.h>
28
29namespace android {
30
31struct BufferMeta {
32    BufferMeta(const sp<IMemory> &mem, bool is_backup = false)
33        : mMem(mem),
34          mIsBackup(is_backup) {
35    }
36
37    BufferMeta(size_t size)
38        : mSize(size),
39          mIsBackup(false) {
40    }
41
42    void CopyFromOMX(const OMX_BUFFERHEADERTYPE *header) {
43        if (!mIsBackup) {
44            return;
45        }
46
47        memcpy((OMX_U8 *)mMem->pointer() + header->nOffset,
48               header->pBuffer + header->nOffset,
49               header->nFilledLen);
50    }
51
52    void CopyToOMX(const OMX_BUFFERHEADERTYPE *header) {
53        if (!mIsBackup) {
54            return;
55        }
56
57        memcpy(header->pBuffer + header->nOffset,
58               (const OMX_U8 *)mMem->pointer() + header->nOffset,
59               header->nFilledLen);
60    }
61
62private:
63    sp<IMemory> mMem;
64    size_t mSize;
65    bool mIsBackup;
66
67    BufferMeta(const BufferMeta &);
68    BufferMeta &operator=(const BufferMeta &);
69};
70
71// static
72OMX_CALLBACKTYPE OMXNodeInstance::kCallbacks = {
73    &OnEvent, &OnEmptyBufferDone, &OnFillBufferDone
74};
75
76OMXNodeInstance::OMXNodeInstance(
77        OMX *owner, const sp<IOMXObserver> &observer)
78    : mOwner(owner),
79      mNodeID(NULL),
80      mHandle(NULL),
81      mObserver(observer),
82      mDying(false) {
83}
84
85OMXNodeInstance::~OMXNodeInstance() {
86    CHECK_EQ(mHandle, NULL);
87}
88
89void OMXNodeInstance::setHandle(OMX::node_id node_id, OMX_HANDLETYPE handle) {
90    CHECK_EQ(mHandle, NULL);
91    mNodeID = node_id;
92    mHandle = handle;
93}
94
95OMX *OMXNodeInstance::owner() {
96    return mOwner;
97}
98
99sp<IOMXObserver> OMXNodeInstance::observer() {
100    return mObserver;
101}
102
103OMX::node_id OMXNodeInstance::nodeID() {
104    return mNodeID;
105}
106
107static status_t StatusFromOMXError(OMX_ERRORTYPE err) {
108    return (err == OMX_ErrorNone) ? OK : UNKNOWN_ERROR;
109}
110
111status_t OMXNodeInstance::freeNode(OMXMaster *master) {
112    // Transition the node from its current state all the way down
113    // to "Loaded".
114    // This ensures that all active buffers are properly freed even
115    // for components that don't do this themselves on a call to
116    // "FreeHandle".
117
118    // The code below may trigger some more events to be dispatched
119    // by the OMX component - we want to ignore them as our client
120    // does not expect them.
121    mDying = true;
122
123    OMX_STATETYPE state;
124    CHECK_EQ(OMX_GetState(mHandle, &state), OMX_ErrorNone);
125    switch (state) {
126        case OMX_StateExecuting:
127        {
128            LOGV("forcing Executing->Idle");
129            sendCommand(OMX_CommandStateSet, OMX_StateIdle);
130            OMX_ERRORTYPE err;
131            while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone
132                   && state != OMX_StateIdle) {
133                usleep(100000);
134            }
135            CHECK_EQ(err, OMX_ErrorNone);
136
137            // fall through
138        }
139
140        case OMX_StateIdle:
141        {
142            LOGV("forcing Idle->Loaded");
143            sendCommand(OMX_CommandStateSet, OMX_StateLoaded);
144
145            freeActiveBuffers();
146
147            OMX_ERRORTYPE err;
148            while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone
149                   && state != OMX_StateLoaded) {
150                LOGV("waiting for Loaded state...");
151                usleep(100000);
152            }
153            CHECK_EQ(err, OMX_ErrorNone);
154
155            // fall through
156        }
157
158        case OMX_StateLoaded:
159        case OMX_StateInvalid:
160            break;
161
162        default:
163            CHECK(!"should not be here, unknown state.");
164            break;
165    }
166
167    OMX_ERRORTYPE err = master->destroyComponentInstance(
168            static_cast<OMX_COMPONENTTYPE *>(mHandle));
169
170    mHandle = NULL;
171
172    if (err != OMX_ErrorNone) {
173        LOGE("FreeHandle FAILED with error 0x%08x.", err);
174    }
175
176    mOwner->invalidateNodeID(mNodeID);
177    mNodeID = NULL;
178
179    LOGV("OMXNodeInstance going away.");
180    delete this;
181
182    return StatusFromOMXError(err);
183}
184
185status_t OMXNodeInstance::sendCommand(
186        OMX_COMMANDTYPE cmd, OMX_S32 param) {
187    Mutex::Autolock autoLock(mLock);
188
189    OMX_ERRORTYPE err = OMX_SendCommand(mHandle, cmd, param, NULL);
190    return StatusFromOMXError(err);
191}
192
193status_t OMXNodeInstance::getParameter(
194        OMX_INDEXTYPE index, void *params, size_t size) {
195    Mutex::Autolock autoLock(mLock);
196
197    OMX_ERRORTYPE err = OMX_GetParameter(mHandle, index, params);
198    return StatusFromOMXError(err);
199}
200
201status_t OMXNodeInstance::setParameter(
202        OMX_INDEXTYPE index, const void *params, size_t size) {
203    Mutex::Autolock autoLock(mLock);
204
205    OMX_ERRORTYPE err = OMX_SetParameter(
206            mHandle, index, const_cast<void *>(params));
207
208    return StatusFromOMXError(err);
209}
210
211status_t OMXNodeInstance::getConfig(
212        OMX_INDEXTYPE index, void *params, size_t size) {
213    Mutex::Autolock autoLock(mLock);
214
215    OMX_ERRORTYPE err = OMX_GetConfig(mHandle, index, params);
216    return StatusFromOMXError(err);
217}
218
219status_t OMXNodeInstance::setConfig(
220        OMX_INDEXTYPE index, const void *params, size_t size) {
221    Mutex::Autolock autoLock(mLock);
222
223    OMX_ERRORTYPE err = OMX_SetConfig(
224            mHandle, index, const_cast<void *>(params));
225
226    return StatusFromOMXError(err);
227}
228
229status_t OMXNodeInstance::useBuffer(
230        OMX_U32 portIndex, const sp<IMemory> &params,
231        OMX::buffer_id *buffer) {
232    Mutex::Autolock autoLock(mLock);
233
234    BufferMeta *buffer_meta = new BufferMeta(params);
235
236    OMX_BUFFERHEADERTYPE *header;
237
238    OMX_ERRORTYPE err = OMX_UseBuffer(
239            mHandle, &header, portIndex, buffer_meta,
240            params->size(), static_cast<OMX_U8 *>(params->pointer()));
241
242    if (err != OMX_ErrorNone) {
243        LOGE("OMX_UseBuffer failed with error %d (0x%08x)", err, err);
244
245        delete buffer_meta;
246        buffer_meta = NULL;
247
248        *buffer = 0;
249
250        return UNKNOWN_ERROR;
251    }
252
253    *buffer = header;
254
255    addActiveBuffer(portIndex, *buffer);
256
257    return OK;
258}
259
260status_t OMXNodeInstance::allocateBuffer(
261        OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer,
262        void **buffer_data) {
263    Mutex::Autolock autoLock(mLock);
264
265    BufferMeta *buffer_meta = new BufferMeta(size);
266
267    OMX_BUFFERHEADERTYPE *header;
268
269    OMX_ERRORTYPE err = OMX_AllocateBuffer(
270            mHandle, &header, portIndex, buffer_meta, size);
271
272    if (err != OMX_ErrorNone) {
273        LOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err);
274
275        delete buffer_meta;
276        buffer_meta = NULL;
277
278        *buffer = 0;
279
280        return UNKNOWN_ERROR;
281    }
282
283    *buffer = header;
284    *buffer_data = header->pBuffer;
285
286    addActiveBuffer(portIndex, *buffer);
287
288    return OK;
289}
290
291status_t OMXNodeInstance::allocateBufferWithBackup(
292        OMX_U32 portIndex, const sp<IMemory> &params,
293        OMX::buffer_id *buffer) {
294    Mutex::Autolock autoLock(mLock);
295
296    BufferMeta *buffer_meta = new BufferMeta(params, true);
297
298    OMX_BUFFERHEADERTYPE *header;
299
300    OMX_ERRORTYPE err = OMX_AllocateBuffer(
301            mHandle, &header, portIndex, buffer_meta, params->size());
302
303    if (err != OMX_ErrorNone) {
304        LOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err);
305
306        delete buffer_meta;
307        buffer_meta = NULL;
308
309        *buffer = 0;
310
311        return UNKNOWN_ERROR;
312    }
313
314    *buffer = header;
315
316    addActiveBuffer(portIndex, *buffer);
317
318    return OK;
319}
320
321status_t OMXNodeInstance::freeBuffer(
322        OMX_U32 portIndex, OMX::buffer_id buffer) {
323    Mutex::Autolock autoLock(mLock);
324
325    removeActiveBuffer(portIndex, buffer);
326
327    OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
328    BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate);
329
330    OMX_ERRORTYPE err = OMX_FreeBuffer(mHandle, portIndex, header);
331
332    delete buffer_meta;
333    buffer_meta = NULL;
334
335    return StatusFromOMXError(err);
336}
337
338status_t OMXNodeInstance::fillBuffer(OMX::buffer_id buffer) {
339    Mutex::Autolock autoLock(mLock);
340
341    OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
342    header->nFilledLen = 0;
343    header->nOffset = 0;
344    header->nFlags = 0;
345
346    OMX_ERRORTYPE err = OMX_FillThisBuffer(mHandle, header);
347
348    return StatusFromOMXError(err);
349}
350
351status_t OMXNodeInstance::emptyBuffer(
352        OMX::buffer_id buffer,
353        OMX_U32 rangeOffset, OMX_U32 rangeLength,
354        OMX_U32 flags, OMX_TICKS timestamp) {
355    Mutex::Autolock autoLock(mLock);
356
357    OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
358    header->nFilledLen = rangeLength;
359    header->nOffset = rangeOffset;
360    header->nFlags = flags;
361    header->nTimeStamp = timestamp;
362
363    BufferMeta *buffer_meta =
364        static_cast<BufferMeta *>(header->pAppPrivate);
365    buffer_meta->CopyToOMX(header);
366
367    OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header);
368
369    return StatusFromOMXError(err);
370}
371
372status_t OMXNodeInstance::getExtensionIndex(
373        const char *parameterName, OMX_INDEXTYPE *index) {
374    Mutex::Autolock autoLock(mLock);
375
376    OMX_ERRORTYPE err = OMX_GetExtensionIndex(
377            mHandle, const_cast<char *>(parameterName), index);
378
379    return StatusFromOMXError(err);
380}
381
382void OMXNodeInstance::onMessage(const omx_message &msg) {
383    if (msg.type == omx_message::FILL_BUFFER_DONE) {
384        OMX_BUFFERHEADERTYPE *buffer =
385            static_cast<OMX_BUFFERHEADERTYPE *>(
386                    msg.u.extended_buffer_data.buffer);
387
388        BufferMeta *buffer_meta =
389            static_cast<BufferMeta *>(buffer->pAppPrivate);
390
391        buffer_meta->CopyFromOMX(buffer);
392    }
393
394    mObserver->onMessage(msg);
395}
396
397void OMXNodeInstance::onObserverDied(OMXMaster *master) {
398    LOGE("!!! Observer died. Quickly, do something, ... anything...");
399
400    // Try to force shutdown of the node and hope for the best.
401    freeNode(master);
402}
403
404void OMXNodeInstance::onGetHandleFailed() {
405    delete this;
406}
407
408// static
409OMX_ERRORTYPE OMXNodeInstance::OnEvent(
410        OMX_IN OMX_HANDLETYPE hComponent,
411        OMX_IN OMX_PTR pAppData,
412        OMX_IN OMX_EVENTTYPE eEvent,
413        OMX_IN OMX_U32 nData1,
414        OMX_IN OMX_U32 nData2,
415        OMX_IN OMX_PTR pEventData) {
416    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
417    if (instance->mDying) {
418        return OMX_ErrorNone;
419    }
420    return instance->owner()->OnEvent(
421            instance->nodeID(), eEvent, nData1, nData2, pEventData);
422}
423
424// static
425OMX_ERRORTYPE OMXNodeInstance::OnEmptyBufferDone(
426        OMX_IN OMX_HANDLETYPE hComponent,
427        OMX_IN OMX_PTR pAppData,
428        OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
429    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
430    if (instance->mDying) {
431        return OMX_ErrorNone;
432    }
433    return instance->owner()->OnEmptyBufferDone(instance->nodeID(), pBuffer);
434}
435
436// static
437OMX_ERRORTYPE OMXNodeInstance::OnFillBufferDone(
438        OMX_IN OMX_HANDLETYPE hComponent,
439        OMX_IN OMX_PTR pAppData,
440        OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
441    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
442    if (instance->mDying) {
443        return OMX_ErrorNone;
444    }
445    return instance->owner()->OnFillBufferDone(instance->nodeID(), pBuffer);
446}
447
448void OMXNodeInstance::addActiveBuffer(OMX_U32 portIndex, OMX::buffer_id id) {
449    ActiveBuffer active;
450    active.mPortIndex = portIndex;
451    active.mID = id;
452    mActiveBuffers.push(active);
453}
454
455void OMXNodeInstance::removeActiveBuffer(
456        OMX_U32 portIndex, OMX::buffer_id id) {
457    bool found = false;
458    for (size_t i = 0; i < mActiveBuffers.size(); ++i) {
459        if (mActiveBuffers[i].mPortIndex == portIndex
460            && mActiveBuffers[i].mID == id) {
461            found = true;
462            mActiveBuffers.removeItemsAt(i);
463            break;
464        }
465    }
466
467    if (!found) {
468        LOGW("Attempt to remove an active buffer we know nothing about...");
469    }
470}
471
472void OMXNodeInstance::freeActiveBuffers() {
473    // Make sure to count down here, as freeBuffer will in turn remove
474    // the active buffer from the vector...
475    for (size_t i = mActiveBuffers.size(); i--;) {
476        freeBuffer(mActiveBuffers[i].mPortIndex, mActiveBuffers[i].mID);
477    }
478}
479
480}  // namespace android
481
482