ACodec.cpp revision 8b71241ce7353731ab75322c46e090ee35014a33
1/*
2 * Copyright (C) 2010 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 "ACodec"
19
20#include <media/stagefright/ACodec.h>
21
22#include <binder/MemoryDealer.h>
23
24#include <media/stagefright/foundation/hexdump.h>
25#include <media/stagefright/foundation/ABuffer.h>
26#include <media/stagefright/foundation/ADebug.h>
27#include <media/stagefright/foundation/AMessage.h>
28
29#include <media/stagefright/MediaCodecList.h>
30#include <media/stagefright/MediaDefs.h>
31#include <media/stagefright/NativeWindowWrapper.h>
32#include <media/stagefright/OMXClient.h>
33#include <media/stagefright/OMXCodec.h>
34
35#include <OMX_Component.h>
36
37namespace android {
38
39template<class T>
40static void InitOMXParams(T *params) {
41    params->nSize = sizeof(T);
42    params->nVersion.s.nVersionMajor = 1;
43    params->nVersion.s.nVersionMinor = 0;
44    params->nVersion.s.nRevision = 0;
45    params->nVersion.s.nStep = 0;
46}
47
48struct CodecObserver : public BnOMXObserver {
49    CodecObserver() {}
50
51    void setNotificationMessage(const sp<AMessage> &msg) {
52        mNotify = msg;
53    }
54
55    // from IOMXObserver
56    virtual void onMessage(const omx_message &omx_msg) {
57        sp<AMessage> msg = mNotify->dup();
58
59        msg->setInt32("type", omx_msg.type);
60        msg->setPointer("node", omx_msg.node);
61
62        switch (omx_msg.type) {
63            case omx_message::EVENT:
64            {
65                msg->setInt32("event", omx_msg.u.event_data.event);
66                msg->setInt32("data1", omx_msg.u.event_data.data1);
67                msg->setInt32("data2", omx_msg.u.event_data.data2);
68                break;
69            }
70
71            case omx_message::EMPTY_BUFFER_DONE:
72            {
73                msg->setPointer("buffer", omx_msg.u.buffer_data.buffer);
74                break;
75            }
76
77            case omx_message::FILL_BUFFER_DONE:
78            {
79                msg->setPointer(
80                        "buffer", omx_msg.u.extended_buffer_data.buffer);
81                msg->setInt32(
82                        "range_offset",
83                        omx_msg.u.extended_buffer_data.range_offset);
84                msg->setInt32(
85                        "range_length",
86                        omx_msg.u.extended_buffer_data.range_length);
87                msg->setInt32(
88                        "flags",
89                        omx_msg.u.extended_buffer_data.flags);
90                msg->setInt64(
91                        "timestamp",
92                        omx_msg.u.extended_buffer_data.timestamp);
93                msg->setPointer(
94                        "platform_private",
95                        omx_msg.u.extended_buffer_data.platform_private);
96                msg->setPointer(
97                        "data_ptr",
98                        omx_msg.u.extended_buffer_data.data_ptr);
99                break;
100            }
101
102            default:
103                TRESPASS();
104                break;
105        }
106
107        msg->post();
108    }
109
110protected:
111    virtual ~CodecObserver() {}
112
113private:
114    sp<AMessage> mNotify;
115
116    DISALLOW_EVIL_CONSTRUCTORS(CodecObserver);
117};
118
119////////////////////////////////////////////////////////////////////////////////
120
121struct ACodec::BaseState : public AState {
122    BaseState(ACodec *codec, const sp<AState> &parentState = NULL);
123
124protected:
125    enum PortMode {
126        KEEP_BUFFERS,
127        RESUBMIT_BUFFERS,
128        FREE_BUFFERS,
129    };
130
131    ACodec *mCodec;
132
133    virtual PortMode getPortMode(OMX_U32 portIndex);
134
135    virtual bool onMessageReceived(const sp<AMessage> &msg);
136
137    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
138
139    virtual void onOutputBufferDrained(const sp<AMessage> &msg);
140    virtual void onInputBufferFilled(const sp<AMessage> &msg);
141
142    void postFillThisBuffer(BufferInfo *info);
143
144private:
145    bool onOMXMessage(const sp<AMessage> &msg);
146
147    bool onOMXEmptyBufferDone(IOMX::buffer_id bufferID);
148
149    bool onOMXFillBufferDone(
150            IOMX::buffer_id bufferID,
151            size_t rangeOffset, size_t rangeLength,
152            OMX_U32 flags,
153            int64_t timeUs,
154            void *platformPrivate,
155            void *dataPtr);
156
157    void getMoreInputDataIfPossible();
158
159    DISALLOW_EVIL_CONSTRUCTORS(BaseState);
160};
161
162////////////////////////////////////////////////////////////////////////////////
163
164struct ACodec::UninitializedState : public ACodec::BaseState {
165    UninitializedState(ACodec *codec);
166
167protected:
168    virtual bool onMessageReceived(const sp<AMessage> &msg);
169    virtual void stateEntered();
170
171private:
172    void onSetup(const sp<AMessage> &msg);
173    bool onAllocateComponent(const sp<AMessage> &msg);
174
175    DISALLOW_EVIL_CONSTRUCTORS(UninitializedState);
176};
177
178////////////////////////////////////////////////////////////////////////////////
179
180struct ACodec::LoadedState : public ACodec::BaseState {
181    LoadedState(ACodec *codec);
182
183protected:
184    virtual bool onMessageReceived(const sp<AMessage> &msg);
185    virtual void stateEntered();
186
187private:
188    friend struct ACodec::UninitializedState;
189
190    bool onConfigureComponent(const sp<AMessage> &msg);
191    void onStart();
192    void onShutdown(bool keepComponentAllocated);
193
194    DISALLOW_EVIL_CONSTRUCTORS(LoadedState);
195};
196
197////////////////////////////////////////////////////////////////////////////////
198
199struct ACodec::LoadedToIdleState : public ACodec::BaseState {
200    LoadedToIdleState(ACodec *codec);
201
202protected:
203    virtual bool onMessageReceived(const sp<AMessage> &msg);
204    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
205    virtual void stateEntered();
206
207private:
208    status_t allocateBuffers();
209
210    DISALLOW_EVIL_CONSTRUCTORS(LoadedToIdleState);
211};
212
213////////////////////////////////////////////////////////////////////////////////
214
215struct ACodec::IdleToExecutingState : public ACodec::BaseState {
216    IdleToExecutingState(ACodec *codec);
217
218protected:
219    virtual bool onMessageReceived(const sp<AMessage> &msg);
220    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
221    virtual void stateEntered();
222
223private:
224    DISALLOW_EVIL_CONSTRUCTORS(IdleToExecutingState);
225};
226
227////////////////////////////////////////////////////////////////////////////////
228
229struct ACodec::ExecutingState : public ACodec::BaseState {
230    ExecutingState(ACodec *codec);
231
232    void submitOutputBuffers();
233
234    // Submit output buffers to the decoder, submit input buffers to client
235    // to fill with data.
236    void resume();
237
238    // Returns true iff input and output buffers are in play.
239    bool active() const { return mActive; }
240
241protected:
242    virtual PortMode getPortMode(OMX_U32 portIndex);
243    virtual bool onMessageReceived(const sp<AMessage> &msg);
244    virtual void stateEntered();
245
246    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
247
248private:
249    bool mActive;
250
251    DISALLOW_EVIL_CONSTRUCTORS(ExecutingState);
252};
253
254////////////////////////////////////////////////////////////////////////////////
255
256struct ACodec::OutputPortSettingsChangedState : public ACodec::BaseState {
257    OutputPortSettingsChangedState(ACodec *codec);
258
259protected:
260    virtual PortMode getPortMode(OMX_U32 portIndex);
261    virtual bool onMessageReceived(const sp<AMessage> &msg);
262    virtual void stateEntered();
263
264    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
265
266private:
267    DISALLOW_EVIL_CONSTRUCTORS(OutputPortSettingsChangedState);
268};
269
270////////////////////////////////////////////////////////////////////////////////
271
272struct ACodec::ExecutingToIdleState : public ACodec::BaseState {
273    ExecutingToIdleState(ACodec *codec);
274
275protected:
276    virtual bool onMessageReceived(const sp<AMessage> &msg);
277    virtual void stateEntered();
278
279    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
280
281    virtual void onOutputBufferDrained(const sp<AMessage> &msg);
282    virtual void onInputBufferFilled(const sp<AMessage> &msg);
283
284private:
285    void changeStateIfWeOwnAllBuffers();
286
287    bool mComponentNowIdle;
288
289    DISALLOW_EVIL_CONSTRUCTORS(ExecutingToIdleState);
290};
291
292////////////////////////////////////////////////////////////////////////////////
293
294struct ACodec::IdleToLoadedState : public ACodec::BaseState {
295    IdleToLoadedState(ACodec *codec);
296
297protected:
298    virtual bool onMessageReceived(const sp<AMessage> &msg);
299    virtual void stateEntered();
300
301    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
302
303private:
304    DISALLOW_EVIL_CONSTRUCTORS(IdleToLoadedState);
305};
306
307////////////////////////////////////////////////////////////////////////////////
308
309struct ACodec::FlushingState : public ACodec::BaseState {
310    FlushingState(ACodec *codec);
311
312protected:
313    virtual bool onMessageReceived(const sp<AMessage> &msg);
314    virtual void stateEntered();
315
316    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
317
318    virtual void onOutputBufferDrained(const sp<AMessage> &msg);
319    virtual void onInputBufferFilled(const sp<AMessage> &msg);
320
321private:
322    bool mFlushComplete[2];
323
324    void changeStateIfWeOwnAllBuffers();
325
326    DISALLOW_EVIL_CONSTRUCTORS(FlushingState);
327};
328
329////////////////////////////////////////////////////////////////////////////////
330
331ACodec::ACodec()
332    : mQuirks(0),
333      mNode(NULL),
334      mSentFormat(false),
335      mIsEncoder(false),
336      mShutdownInProgress(false) {
337    mUninitializedState = new UninitializedState(this);
338    mLoadedState = new LoadedState(this);
339    mLoadedToIdleState = new LoadedToIdleState(this);
340    mIdleToExecutingState = new IdleToExecutingState(this);
341    mExecutingState = new ExecutingState(this);
342
343    mOutputPortSettingsChangedState =
344        new OutputPortSettingsChangedState(this);
345
346    mExecutingToIdleState = new ExecutingToIdleState(this);
347    mIdleToLoadedState = new IdleToLoadedState(this);
348    mFlushingState = new FlushingState(this);
349
350    mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false;
351    mInputEOSResult = OK;
352
353    changeState(mUninitializedState);
354}
355
356ACodec::~ACodec() {
357}
358
359void ACodec::setNotificationMessage(const sp<AMessage> &msg) {
360    mNotify = msg;
361}
362
363void ACodec::initiateSetup(const sp<AMessage> &msg) {
364    msg->setWhat(kWhatSetup);
365    msg->setTarget(id());
366    msg->post();
367}
368
369void ACodec::initiateAllocateComponent(const sp<AMessage> &msg) {
370    msg->setWhat(kWhatAllocateComponent);
371    msg->setTarget(id());
372    msg->post();
373}
374
375void ACodec::initiateConfigureComponent(const sp<AMessage> &msg) {
376    msg->setWhat(kWhatConfigureComponent);
377    msg->setTarget(id());
378    msg->post();
379}
380
381void ACodec::initiateStart() {
382    (new AMessage(kWhatStart, id()))->post();
383}
384
385void ACodec::signalFlush() {
386    ALOGV("[%s] signalFlush", mComponentName.c_str());
387    (new AMessage(kWhatFlush, id()))->post();
388}
389
390void ACodec::signalResume() {
391    (new AMessage(kWhatResume, id()))->post();
392}
393
394void ACodec::initiateShutdown(bool keepComponentAllocated) {
395    sp<AMessage> msg = new AMessage(kWhatShutdown, id());
396    msg->setInt32("keepComponentAllocated", keepComponentAllocated);
397    msg->post();
398}
399
400status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) {
401    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
402
403    CHECK(mDealer[portIndex] == NULL);
404    CHECK(mBuffers[portIndex].isEmpty());
405
406    status_t err;
407    if (mNativeWindow != NULL && portIndex == kPortIndexOutput) {
408        err = allocateOutputBuffersFromNativeWindow();
409    } else {
410        OMX_PARAM_PORTDEFINITIONTYPE def;
411        InitOMXParams(&def);
412        def.nPortIndex = portIndex;
413
414        err = mOMX->getParameter(
415                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
416
417        if (err == OK) {
418            ALOGV("[%s] Allocating %lu buffers of size %lu on %s port",
419                    mComponentName.c_str(),
420                    def.nBufferCountActual, def.nBufferSize,
421                    portIndex == kPortIndexInput ? "input" : "output");
422
423            size_t totalSize = def.nBufferCountActual * def.nBufferSize;
424            mDealer[portIndex] = new MemoryDealer(totalSize, "ACodec");
425
426            for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
427                sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
428                CHECK(mem.get() != NULL);
429
430                BufferInfo info;
431                info.mStatus = BufferInfo::OWNED_BY_US;
432
433                uint32_t requiresAllocateBufferBit =
434                    (portIndex == kPortIndexInput)
435                        ? OMXCodec::kRequiresAllocateBufferOnInputPorts
436                        : OMXCodec::kRequiresAllocateBufferOnOutputPorts;
437
438                if (portIndex == kPortIndexInput && (mFlags & kFlagIsSecure)) {
439                    mem.clear();
440
441                    void *ptr;
442                    err = mOMX->allocateBuffer(
443                            mNode, portIndex, def.nBufferSize, &info.mBufferID,
444                            &ptr);
445
446                    info.mData = new ABuffer(ptr, def.nBufferSize);
447                } else if (mQuirks & requiresAllocateBufferBit) {
448                    err = mOMX->allocateBufferWithBackup(
449                            mNode, portIndex, mem, &info.mBufferID);
450                } else {
451                    err = mOMX->useBuffer(mNode, portIndex, mem, &info.mBufferID);
452                }
453
454                if (mem != NULL) {
455                    info.mData = new ABuffer(mem->pointer(), def.nBufferSize);
456                }
457
458                mBuffers[portIndex].push(info);
459            }
460        }
461    }
462
463    if (err != OK) {
464        return err;
465    }
466
467    sp<AMessage> notify = mNotify->dup();
468    notify->setInt32("what", ACodec::kWhatBuffersAllocated);
469
470    notify->setInt32("portIndex", portIndex);
471    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
472        AString name = StringPrintf("buffer-id_%d", i);
473        notify->setPointer(name.c_str(), mBuffers[portIndex][i].mBufferID);
474
475        name = StringPrintf("data_%d", i);
476        notify->setBuffer(name.c_str(), mBuffers[portIndex][i].mData);
477    }
478
479    notify->post();
480
481    return OK;
482}
483
484status_t ACodec::allocateOutputBuffersFromNativeWindow() {
485    OMX_PARAM_PORTDEFINITIONTYPE def;
486    InitOMXParams(&def);
487    def.nPortIndex = kPortIndexOutput;
488
489    status_t err = mOMX->getParameter(
490            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
491
492    if (err != OK) {
493        return err;
494    }
495
496    err = native_window_set_scaling_mode(mNativeWindow.get(),
497            NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
498
499    if (err != OK) {
500        return err;
501    }
502
503    err = native_window_set_buffers_geometry(
504            mNativeWindow.get(),
505            def.format.video.nFrameWidth,
506            def.format.video.nFrameHeight,
507            def.format.video.eColorFormat);
508
509    if (err != 0) {
510        ALOGE("native_window_set_buffers_geometry failed: %s (%d)",
511                strerror(-err), -err);
512        return err;
513    }
514
515    // Set up the native window.
516    OMX_U32 usage = 0;
517    err = mOMX->getGraphicBufferUsage(mNode, kPortIndexOutput, &usage);
518    if (err != 0) {
519        ALOGW("querying usage flags from OMX IL component failed: %d", err);
520        // XXX: Currently this error is logged, but not fatal.
521        usage = 0;
522    }
523
524    err = native_window_set_usage(
525            mNativeWindow.get(),
526            usage | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP);
527
528    if (err != 0) {
529        ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err);
530        return err;
531    }
532
533    int minUndequeuedBufs = 0;
534    err = mNativeWindow->query(
535            mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
536            &minUndequeuedBufs);
537
538    if (err != 0) {
539        ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)",
540                strerror(-err), -err);
541        return err;
542    }
543
544    // XXX: Is this the right logic to use?  It's not clear to me what the OMX
545    // buffer counts refer to - how do they account for the renderer holding on
546    // to buffers?
547    if (def.nBufferCountActual < def.nBufferCountMin + minUndequeuedBufs) {
548        OMX_U32 newBufferCount = def.nBufferCountMin + minUndequeuedBufs;
549        def.nBufferCountActual = newBufferCount;
550        err = mOMX->setParameter(
551                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
552
553        if (err != OK) {
554            ALOGE("[%s] setting nBufferCountActual to %lu failed: %d",
555                    mComponentName.c_str(), newBufferCount, err);
556            return err;
557        }
558    }
559
560    err = native_window_set_buffer_count(
561            mNativeWindow.get(), def.nBufferCountActual);
562
563    if (err != 0) {
564        ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err),
565                -err);
566        return err;
567    }
568
569    ALOGV("[%s] Allocating %lu buffers from a native window of size %lu on "
570         "output port",
571         mComponentName.c_str(), def.nBufferCountActual, def.nBufferSize);
572
573    // Dequeue buffers and send them to OMX
574    for (OMX_U32 i = 0; i < def.nBufferCountActual; i++) {
575        ANativeWindowBuffer *buf;
576        err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf);
577        if (err != 0) {
578            ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
579            break;
580        }
581
582        sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false));
583        BufferInfo info;
584        info.mStatus = BufferInfo::OWNED_BY_US;
585        info.mData = new ABuffer(0);
586        info.mGraphicBuffer = graphicBuffer;
587        mBuffers[kPortIndexOutput].push(info);
588
589        IOMX::buffer_id bufferId;
590        err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer,
591                &bufferId);
592        if (err != 0) {
593            ALOGE("registering GraphicBuffer %lu with OMX IL component failed: "
594                 "%d", i, err);
595            break;
596        }
597
598        mBuffers[kPortIndexOutput].editItemAt(i).mBufferID = bufferId;
599
600        ALOGV("[%s] Registered graphic buffer with ID %p (pointer = %p)",
601             mComponentName.c_str(),
602             bufferId, graphicBuffer.get());
603    }
604
605    OMX_U32 cancelStart;
606    OMX_U32 cancelEnd;
607
608    if (err != 0) {
609        // If an error occurred while dequeuing we need to cancel any buffers
610        // that were dequeued.
611        cancelStart = 0;
612        cancelEnd = mBuffers[kPortIndexOutput].size();
613    } else {
614        // Return the last two buffers to the native window.
615        cancelStart = def.nBufferCountActual - minUndequeuedBufs;
616        cancelEnd = def.nBufferCountActual;
617    }
618
619    for (OMX_U32 i = cancelStart; i < cancelEnd; i++) {
620        BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
621        cancelBufferToNativeWindow(info);
622    }
623
624    return err;
625}
626
627status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) {
628    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
629
630    ALOGV("[%s] Calling cancelBuffer on buffer %p",
631         mComponentName.c_str(), info->mBufferID);
632
633    int err = mNativeWindow->cancelBuffer(
634        mNativeWindow.get(), info->mGraphicBuffer.get());
635
636    CHECK_EQ(err, 0);
637
638    info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
639
640    return OK;
641}
642
643ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() {
644    ANativeWindowBuffer *buf;
645    if (mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf) != 0) {
646        ALOGE("dequeueBuffer failed.");
647        return NULL;
648    }
649
650    for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
651        BufferInfo *info =
652            &mBuffers[kPortIndexOutput].editItemAt(i);
653
654        if (info->mGraphicBuffer->handle == buf->handle) {
655            CHECK_EQ((int)info->mStatus,
656                     (int)BufferInfo::OWNED_BY_NATIVE_WINDOW);
657
658            info->mStatus = BufferInfo::OWNED_BY_US;
659
660            return info;
661        }
662    }
663
664    TRESPASS();
665
666    return NULL;
667}
668
669status_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) {
670    for (size_t i = mBuffers[portIndex].size(); i-- > 0;) {
671        CHECK_EQ((status_t)OK, freeBuffer(portIndex, i));
672    }
673
674    mDealer[portIndex].clear();
675
676    return OK;
677}
678
679status_t ACodec::freeOutputBuffersNotOwnedByComponent() {
680    for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
681        BufferInfo *info =
682            &mBuffers[kPortIndexOutput].editItemAt(i);
683
684        if (info->mStatus !=
685                BufferInfo::OWNED_BY_COMPONENT) {
686            // We shouldn't have sent out any buffers to the client at this
687            // point.
688            CHECK_NE((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
689
690            CHECK_EQ((status_t)OK, freeBuffer(kPortIndexOutput, i));
691        }
692    }
693
694    return OK;
695}
696
697status_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) {
698    BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
699
700    CHECK(info->mStatus == BufferInfo::OWNED_BY_US
701            || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
702
703    if (portIndex == kPortIndexOutput && mNativeWindow != NULL
704            && info->mStatus == BufferInfo::OWNED_BY_US) {
705        CHECK_EQ((status_t)OK, cancelBufferToNativeWindow(info));
706    }
707
708    CHECK_EQ(mOMX->freeBuffer(
709                mNode, portIndex, info->mBufferID),
710             (status_t)OK);
711
712    mBuffers[portIndex].removeAt(i);
713
714    return OK;
715}
716
717ACodec::BufferInfo *ACodec::findBufferByID(
718        uint32_t portIndex, IOMX::buffer_id bufferID,
719        ssize_t *index) {
720    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
721        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
722
723        if (info->mBufferID == bufferID) {
724            if (index != NULL) {
725                *index = i;
726            }
727            return info;
728        }
729    }
730
731    TRESPASS();
732
733    return NULL;
734}
735
736status_t ACodec::setComponentRole(
737        bool isEncoder, const char *mime) {
738    struct MimeToRole {
739        const char *mime;
740        const char *decoderRole;
741        const char *encoderRole;
742    };
743
744    static const MimeToRole kMimeToRole[] = {
745        { MEDIA_MIMETYPE_AUDIO_MPEG,
746            "audio_decoder.mp3", "audio_encoder.mp3" },
747        { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I,
748            "audio_decoder.mp1", "audio_encoder.mp1" },
749        { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II,
750            "audio_decoder.mp2", "audio_encoder.mp2" },
751        { MEDIA_MIMETYPE_AUDIO_AMR_NB,
752            "audio_decoder.amrnb", "audio_encoder.amrnb" },
753        { MEDIA_MIMETYPE_AUDIO_AMR_WB,
754            "audio_decoder.amrwb", "audio_encoder.amrwb" },
755        { MEDIA_MIMETYPE_AUDIO_AAC,
756            "audio_decoder.aac", "audio_encoder.aac" },
757        { MEDIA_MIMETYPE_AUDIO_VORBIS,
758            "audio_decoder.vorbis", "audio_encoder.vorbis" },
759        { MEDIA_MIMETYPE_AUDIO_G711_MLAW,
760            "audio_decoder.g711mlaw", "audio_encoder.g711mlaw" },
761        { MEDIA_MIMETYPE_AUDIO_G711_ALAW,
762            "audio_decoder.g711alaw", "audio_encoder.g711alaw" },
763        { MEDIA_MIMETYPE_VIDEO_AVC,
764            "video_decoder.avc", "video_encoder.avc" },
765        { MEDIA_MIMETYPE_VIDEO_MPEG4,
766            "video_decoder.mpeg4", "video_encoder.mpeg4" },
767        { MEDIA_MIMETYPE_VIDEO_H263,
768            "video_decoder.h263", "video_encoder.h263" },
769        { MEDIA_MIMETYPE_VIDEO_VPX,
770            "video_decoder.vpx", "video_encoder.vpx" },
771        { MEDIA_MIMETYPE_AUDIO_RAW,
772            "audio_decoder.raw", "audio_encoder.raw" },
773    };
774
775    static const size_t kNumMimeToRole =
776        sizeof(kMimeToRole) / sizeof(kMimeToRole[0]);
777
778    size_t i;
779    for (i = 0; i < kNumMimeToRole; ++i) {
780        if (!strcasecmp(mime, kMimeToRole[i].mime)) {
781            break;
782        }
783    }
784
785    if (i == kNumMimeToRole) {
786        return ERROR_UNSUPPORTED;
787    }
788
789    const char *role =
790        isEncoder ? kMimeToRole[i].encoderRole
791                  : kMimeToRole[i].decoderRole;
792
793    if (role != NULL) {
794        OMX_PARAM_COMPONENTROLETYPE roleParams;
795        InitOMXParams(&roleParams);
796
797        strncpy((char *)roleParams.cRole,
798                role, OMX_MAX_STRINGNAME_SIZE - 1);
799
800        roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
801
802        status_t err = mOMX->setParameter(
803                mNode, OMX_IndexParamStandardComponentRole,
804                &roleParams, sizeof(roleParams));
805
806        if (err != OK) {
807            ALOGW("[%s] Failed to set standard component role '%s'.",
808                 mComponentName.c_str(), role);
809
810            return err;
811        }
812    }
813
814    return OK;
815}
816
817status_t ACodec::configureCodec(
818        const char *mime, const sp<AMessage> &msg) {
819    int32_t encoder;
820    if (!msg->findInt32("encoder", &encoder)) {
821        encoder = false;
822    }
823
824    mIsEncoder = encoder;
825
826    status_t err = setComponentRole(encoder /* isEncoder */, mime);
827
828    if (err != OK) {
829        return err;
830    }
831
832    int32_t bitRate = 0;
833    if (encoder && !msg->findInt32("bitrate", &bitRate)) {
834        return INVALID_OPERATION;
835    }
836
837    if (!strncasecmp(mime, "video/", 6)) {
838        if (encoder) {
839            err = setupVideoEncoder(mime, msg);
840        } else {
841            int32_t width, height;
842            if (!msg->findInt32("width", &width)
843                    || !msg->findInt32("height", &height)) {
844                err = INVALID_OPERATION;
845            } else {
846                err = setupVideoDecoder(mime, width, height);
847            }
848        }
849    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
850        int32_t numChannels, sampleRate;
851        if (!msg->findInt32("channel-count", &numChannels)
852                || !msg->findInt32("sample-rate", &sampleRate)) {
853            err = INVALID_OPERATION;
854        } else {
855            int32_t isADTS, aacProfile;
856            if (!msg->findInt32("is-adts", &isADTS)) {
857                isADTS = 0;
858            }
859            if (!msg->findInt32("aac-profile", &aacProfile)) {
860                aacProfile = OMX_AUDIO_AACObjectNull;
861            }
862
863            err = setupAACCodec(
864                    encoder, numChannels, sampleRate, bitRate, aacProfile, isADTS != 0);
865        }
866    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) {
867        err = setupAMRCodec(encoder, false /* isWAMR */, bitRate);
868    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
869        err = setupAMRCodec(encoder, true /* isWAMR */, bitRate);
870    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW)
871            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) {
872        // These are PCM-like formats with a fixed sample rate but
873        // a variable number of channels.
874
875        int32_t numChannels;
876        if (!msg->findInt32("channel-count", &numChannels)) {
877            err = INVALID_OPERATION;
878        } else {
879            err = setupG711Codec(encoder, numChannels);
880        }
881    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
882        int32_t numChannels, sampleRate;
883        if (encoder
884                || !msg->findInt32("channel-count", &numChannels)
885                || !msg->findInt32("sample-rate", &sampleRate)) {
886            err = INVALID_OPERATION;
887        } else {
888            err = setupRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
889        }
890    }
891
892    if (!msg->findInt32("encoder-delay", &mEncoderDelay)) {
893        mEncoderDelay = 0;
894    }
895    if (!msg->findInt32("encoder-padding", &mEncoderPadding)) {
896        mEncoderPadding = 0;
897    }
898
899    int32_t maxInputSize;
900    if (msg->findInt32("max-input-size", &maxInputSize)) {
901        err = setMinBufferSize(kPortIndexInput, (size_t)maxInputSize);
902    } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) {
903        err = setMinBufferSize(kPortIndexInput, 8192);  // XXX
904    }
905
906    return err;
907}
908
909status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) {
910    OMX_PARAM_PORTDEFINITIONTYPE def;
911    InitOMXParams(&def);
912    def.nPortIndex = portIndex;
913
914    status_t err = mOMX->getParameter(
915            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
916
917    if (err != OK) {
918        return err;
919    }
920
921    if (def.nBufferSize >= size) {
922        return OK;
923    }
924
925    def.nBufferSize = size;
926
927    err = mOMX->setParameter(
928            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
929
930    if (err != OK) {
931        return err;
932    }
933
934    err = mOMX->getParameter(
935            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
936
937    if (err != OK) {
938        return err;
939    }
940
941    CHECK(def.nBufferSize >= size);
942
943    return OK;
944}
945
946status_t ACodec::selectAudioPortFormat(
947        OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat) {
948    OMX_AUDIO_PARAM_PORTFORMATTYPE format;
949    InitOMXParams(&format);
950
951    format.nPortIndex = portIndex;
952    for (OMX_U32 index = 0;; ++index) {
953        format.nIndex = index;
954
955        status_t err = mOMX->getParameter(
956                mNode, OMX_IndexParamAudioPortFormat,
957                &format, sizeof(format));
958
959        if (err != OK) {
960            return err;
961        }
962
963        if (format.eEncoding == desiredFormat) {
964            break;
965        }
966    }
967
968    return mOMX->setParameter(
969            mNode, OMX_IndexParamAudioPortFormat, &format, sizeof(format));
970}
971
972status_t ACodec::setupAACCodec(
973        bool encoder, int32_t numChannels, int32_t sampleRate,
974        int32_t bitRate, int32_t aacProfile, bool isADTS) {
975    if (encoder && isADTS) {
976        return -EINVAL;
977    }
978
979    status_t err = setupRawAudioFormat(
980            encoder ? kPortIndexInput : kPortIndexOutput,
981            sampleRate,
982            numChannels);
983
984    if (err != OK) {
985        return err;
986    }
987
988    if (encoder) {
989        err = selectAudioPortFormat(kPortIndexOutput, OMX_AUDIO_CodingAAC);
990
991        if (err != OK) {
992            return err;
993        }
994
995        OMX_PARAM_PORTDEFINITIONTYPE def;
996        InitOMXParams(&def);
997        def.nPortIndex = kPortIndexOutput;
998
999        err = mOMX->getParameter(
1000                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1001
1002        if (err != OK) {
1003            return err;
1004        }
1005
1006        def.format.audio.bFlagErrorConcealment = OMX_TRUE;
1007        def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
1008
1009        err = mOMX->setParameter(
1010                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1011
1012        if (err != OK) {
1013            return err;
1014        }
1015
1016        OMX_AUDIO_PARAM_AACPROFILETYPE profile;
1017        InitOMXParams(&profile);
1018        profile.nPortIndex = kPortIndexOutput;
1019
1020        err = mOMX->getParameter(
1021                mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1022
1023        if (err != OK) {
1024            return err;
1025        }
1026
1027        profile.nChannels = numChannels;
1028
1029        profile.eChannelMode =
1030            (numChannels == 1)
1031                ? OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo;
1032
1033        profile.nSampleRate = sampleRate;
1034        profile.nBitRate = bitRate;
1035        profile.nAudioBandWidth = 0;
1036        profile.nFrameLength = 0;
1037        profile.nAACtools = OMX_AUDIO_AACToolAll;
1038        profile.nAACERtools = OMX_AUDIO_AACERNone;
1039        profile.eAACProfile = (OMX_AUDIO_AACPROFILETYPE) aacProfile;
1040        profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
1041
1042        err = mOMX->setParameter(
1043                mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1044
1045        if (err != OK) {
1046            return err;
1047        }
1048
1049        return err;
1050    }
1051
1052    OMX_AUDIO_PARAM_AACPROFILETYPE profile;
1053    InitOMXParams(&profile);
1054    profile.nPortIndex = kPortIndexInput;
1055
1056    err = mOMX->getParameter(
1057            mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1058
1059    if (err != OK) {
1060        return err;
1061    }
1062
1063    profile.nChannels = numChannels;
1064    profile.nSampleRate = sampleRate;
1065
1066    profile.eAACStreamFormat =
1067        isADTS
1068            ? OMX_AUDIO_AACStreamFormatMP4ADTS
1069            : OMX_AUDIO_AACStreamFormatMP4FF;
1070
1071    return mOMX->setParameter(
1072            mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1073}
1074
1075static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate(
1076        bool isAMRWB, int32_t bps) {
1077    if (isAMRWB) {
1078        if (bps <= 6600) {
1079            return OMX_AUDIO_AMRBandModeWB0;
1080        } else if (bps <= 8850) {
1081            return OMX_AUDIO_AMRBandModeWB1;
1082        } else if (bps <= 12650) {
1083            return OMX_AUDIO_AMRBandModeWB2;
1084        } else if (bps <= 14250) {
1085            return OMX_AUDIO_AMRBandModeWB3;
1086        } else if (bps <= 15850) {
1087            return OMX_AUDIO_AMRBandModeWB4;
1088        } else if (bps <= 18250) {
1089            return OMX_AUDIO_AMRBandModeWB5;
1090        } else if (bps <= 19850) {
1091            return OMX_AUDIO_AMRBandModeWB6;
1092        } else if (bps <= 23050) {
1093            return OMX_AUDIO_AMRBandModeWB7;
1094        }
1095
1096        // 23850 bps
1097        return OMX_AUDIO_AMRBandModeWB8;
1098    } else {  // AMRNB
1099        if (bps <= 4750) {
1100            return OMX_AUDIO_AMRBandModeNB0;
1101        } else if (bps <= 5150) {
1102            return OMX_AUDIO_AMRBandModeNB1;
1103        } else if (bps <= 5900) {
1104            return OMX_AUDIO_AMRBandModeNB2;
1105        } else if (bps <= 6700) {
1106            return OMX_AUDIO_AMRBandModeNB3;
1107        } else if (bps <= 7400) {
1108            return OMX_AUDIO_AMRBandModeNB4;
1109        } else if (bps <= 7950) {
1110            return OMX_AUDIO_AMRBandModeNB5;
1111        } else if (bps <= 10200) {
1112            return OMX_AUDIO_AMRBandModeNB6;
1113        }
1114
1115        // 12200 bps
1116        return OMX_AUDIO_AMRBandModeNB7;
1117    }
1118}
1119
1120status_t ACodec::setupAMRCodec(bool encoder, bool isWAMR, int32_t bitrate) {
1121    OMX_AUDIO_PARAM_AMRTYPE def;
1122    InitOMXParams(&def);
1123    def.nPortIndex = encoder ? kPortIndexOutput : kPortIndexInput;
1124
1125    status_t err =
1126        mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
1127
1128    if (err != OK) {
1129        return err;
1130    }
1131
1132    def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
1133    def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitrate);
1134
1135    err = mOMX->setParameter(
1136            mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
1137
1138    if (err != OK) {
1139        return err;
1140    }
1141
1142    return setupRawAudioFormat(
1143            encoder ? kPortIndexInput : kPortIndexOutput,
1144            isWAMR ? 16000 : 8000 /* sampleRate */,
1145            1 /* numChannels */);
1146}
1147
1148status_t ACodec::setupG711Codec(bool encoder, int32_t numChannels) {
1149    CHECK(!encoder);  // XXX TODO
1150
1151    return setupRawAudioFormat(
1152            kPortIndexInput, 8000 /* sampleRate */, numChannels);
1153}
1154
1155status_t ACodec::setupRawAudioFormat(
1156        OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) {
1157    OMX_PARAM_PORTDEFINITIONTYPE def;
1158    InitOMXParams(&def);
1159    def.nPortIndex = portIndex;
1160
1161    status_t err = mOMX->getParameter(
1162            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1163
1164    if (err != OK) {
1165        return err;
1166    }
1167
1168    def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
1169
1170    err = mOMX->setParameter(
1171            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1172
1173    if (err != OK) {
1174        return err;
1175    }
1176
1177    OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
1178    InitOMXParams(&pcmParams);
1179    pcmParams.nPortIndex = portIndex;
1180
1181    err = mOMX->getParameter(
1182            mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
1183
1184    if (err != OK) {
1185        return err;
1186    }
1187
1188    pcmParams.nChannels = numChannels;
1189    pcmParams.eNumData = OMX_NumericalDataSigned;
1190    pcmParams.bInterleaved = OMX_TRUE;
1191    pcmParams.nBitPerSample = 16;
1192    pcmParams.nSamplingRate = sampleRate;
1193    pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
1194
1195    if (getOMXChannelMapping(numChannels, pcmParams.eChannelMapping) != OK) {
1196        return OMX_ErrorNone;
1197    }
1198
1199    return mOMX->setParameter(
1200            mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
1201}
1202
1203status_t ACodec::setVideoPortFormatType(
1204        OMX_U32 portIndex,
1205        OMX_VIDEO_CODINGTYPE compressionFormat,
1206        OMX_COLOR_FORMATTYPE colorFormat) {
1207    OMX_VIDEO_PARAM_PORTFORMATTYPE format;
1208    InitOMXParams(&format);
1209    format.nPortIndex = portIndex;
1210    format.nIndex = 0;
1211    bool found = false;
1212
1213    OMX_U32 index = 0;
1214    for (;;) {
1215        format.nIndex = index;
1216        status_t err = mOMX->getParameter(
1217                mNode, OMX_IndexParamVideoPortFormat,
1218                &format, sizeof(format));
1219
1220        if (err != OK) {
1221            return err;
1222        }
1223
1224        // The following assertion is violated by TI's video decoder.
1225        // CHECK_EQ(format.nIndex, index);
1226
1227        if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) {
1228            if (portIndex == kPortIndexInput
1229                    && colorFormat == format.eColorFormat) {
1230                // eCompressionFormat does not seem right.
1231                found = true;
1232                break;
1233            }
1234            if (portIndex == kPortIndexOutput
1235                    && compressionFormat == format.eCompressionFormat) {
1236                // eColorFormat does not seem right.
1237                found = true;
1238                break;
1239            }
1240        }
1241
1242        if (format.eCompressionFormat == compressionFormat
1243            && format.eColorFormat == colorFormat) {
1244            found = true;
1245            break;
1246        }
1247
1248        ++index;
1249    }
1250
1251    if (!found) {
1252        return UNKNOWN_ERROR;
1253    }
1254
1255    status_t err = mOMX->setParameter(
1256            mNode, OMX_IndexParamVideoPortFormat,
1257            &format, sizeof(format));
1258
1259    return err;
1260}
1261
1262status_t ACodec::setSupportedOutputFormat() {
1263    OMX_VIDEO_PARAM_PORTFORMATTYPE format;
1264    InitOMXParams(&format);
1265    format.nPortIndex = kPortIndexOutput;
1266    format.nIndex = 0;
1267
1268    status_t err = mOMX->getParameter(
1269            mNode, OMX_IndexParamVideoPortFormat,
1270            &format, sizeof(format));
1271    CHECK_EQ(err, (status_t)OK);
1272    CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused);
1273
1274    CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar
1275           || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
1276           || format.eColorFormat == OMX_COLOR_FormatCbYCrY
1277           || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar
1278           || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar);
1279
1280    return mOMX->setParameter(
1281            mNode, OMX_IndexParamVideoPortFormat,
1282            &format, sizeof(format));
1283}
1284
1285static status_t GetVideoCodingTypeFromMime(
1286        const char *mime, OMX_VIDEO_CODINGTYPE *codingType) {
1287    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
1288        *codingType = OMX_VIDEO_CodingAVC;
1289    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
1290        *codingType = OMX_VIDEO_CodingMPEG4;
1291    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
1292        *codingType = OMX_VIDEO_CodingH263;
1293    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG2, mime)) {
1294        *codingType = OMX_VIDEO_CodingMPEG2;
1295    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_VPX, mime)) {
1296        *codingType = OMX_VIDEO_CodingVPX;
1297    } else {
1298        *codingType = OMX_VIDEO_CodingUnused;
1299        return ERROR_UNSUPPORTED;
1300    }
1301
1302    return OK;
1303}
1304
1305status_t ACodec::setupVideoDecoder(
1306        const char *mime, int32_t width, int32_t height) {
1307    OMX_VIDEO_CODINGTYPE compressionFormat;
1308    status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
1309
1310    if (err != OK) {
1311        return err;
1312    }
1313
1314    err = setVideoPortFormatType(
1315            kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
1316
1317    if (err != OK) {
1318        return err;
1319    }
1320
1321    err = setSupportedOutputFormat();
1322
1323    if (err != OK) {
1324        return err;
1325    }
1326
1327    err = setVideoFormatOnPort(
1328            kPortIndexInput, width, height, compressionFormat);
1329
1330    if (err != OK) {
1331        return err;
1332    }
1333
1334    err = setVideoFormatOnPort(
1335            kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused);
1336
1337    if (err != OK) {
1338        return err;
1339    }
1340
1341    return OK;
1342}
1343
1344status_t ACodec::setupVideoEncoder(const char *mime, const sp<AMessage> &msg) {
1345    int32_t tmp;
1346    if (!msg->findInt32("color-format", &tmp)) {
1347        return INVALID_OPERATION;
1348    }
1349
1350    OMX_COLOR_FORMATTYPE colorFormat =
1351        static_cast<OMX_COLOR_FORMATTYPE>(tmp);
1352
1353    status_t err = setVideoPortFormatType(
1354            kPortIndexInput, OMX_VIDEO_CodingUnused, colorFormat);
1355
1356    if (err != OK) {
1357        ALOGE("[%s] does not support color format %d",
1358              mComponentName.c_str(), colorFormat);
1359
1360        return err;
1361    }
1362
1363    /* Input port configuration */
1364
1365    OMX_PARAM_PORTDEFINITIONTYPE def;
1366    InitOMXParams(&def);
1367
1368    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
1369
1370    def.nPortIndex = kPortIndexInput;
1371
1372    err = mOMX->getParameter(
1373            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1374
1375    if (err != OK) {
1376        return err;
1377    }
1378
1379    int32_t width, height, bitrate;
1380    if (!msg->findInt32("width", &width)
1381            || !msg->findInt32("height", &height)
1382            || !msg->findInt32("bitrate", &bitrate)) {
1383        return INVALID_OPERATION;
1384    }
1385
1386    video_def->nFrameWidth = width;
1387    video_def->nFrameHeight = height;
1388
1389    int32_t stride;
1390    if (!msg->findInt32("stride", &stride)) {
1391        stride = width;
1392    }
1393
1394    video_def->nStride = stride;
1395
1396    int32_t sliceHeight;
1397    if (!msg->findInt32("slice-height", &sliceHeight)) {
1398        sliceHeight = height;
1399    }
1400
1401    video_def->nSliceHeight = sliceHeight;
1402
1403    def.nBufferSize = (video_def->nStride * video_def->nSliceHeight * 3) / 2;
1404
1405    float frameRate;
1406    if (!msg->findFloat("frame-rate", &frameRate)) {
1407        int32_t tmp;
1408        if (!msg->findInt32("frame-rate", &tmp)) {
1409            return INVALID_OPERATION;
1410        }
1411        frameRate = (float)tmp;
1412    }
1413
1414    video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f);
1415    video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
1416    video_def->eColorFormat = colorFormat;
1417
1418    err = mOMX->setParameter(
1419            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1420
1421    if (err != OK) {
1422        ALOGE("[%s] failed to set input port definition parameters.",
1423              mComponentName.c_str());
1424
1425        return err;
1426    }
1427
1428    /* Output port configuration */
1429
1430    OMX_VIDEO_CODINGTYPE compressionFormat;
1431    err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
1432
1433    if (err != OK) {
1434        return err;
1435    }
1436
1437    err = setVideoPortFormatType(
1438            kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused);
1439
1440    if (err != OK) {
1441        ALOGE("[%s] does not support compression format %d",
1442             mComponentName.c_str(), compressionFormat);
1443
1444        return err;
1445    }
1446
1447    def.nPortIndex = kPortIndexOutput;
1448
1449    err = mOMX->getParameter(
1450            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1451
1452    if (err != OK) {
1453        return err;
1454    }
1455
1456    video_def->nFrameWidth = width;
1457    video_def->nFrameHeight = height;
1458    video_def->xFramerate = 0;
1459    video_def->nBitrate = bitrate;
1460    video_def->eCompressionFormat = compressionFormat;
1461    video_def->eColorFormat = OMX_COLOR_FormatUnused;
1462
1463    err = mOMX->setParameter(
1464            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1465
1466    if (err != OK) {
1467        ALOGE("[%s] failed to set output port definition parameters.",
1468              mComponentName.c_str());
1469
1470        return err;
1471    }
1472
1473    switch (compressionFormat) {
1474        case OMX_VIDEO_CodingMPEG4:
1475            err = setupMPEG4EncoderParameters(msg);
1476            break;
1477
1478        case OMX_VIDEO_CodingH263:
1479            err = setupH263EncoderParameters(msg);
1480            break;
1481
1482        case OMX_VIDEO_CodingAVC:
1483            err = setupAVCEncoderParameters(msg);
1484            break;
1485
1486        default:
1487            break;
1488    }
1489
1490    ALOGI("setupVideoEncoder succeeded");
1491
1492    return err;
1493}
1494
1495static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) {
1496    if (iFramesInterval < 0) {
1497        return 0xFFFFFFFF;
1498    } else if (iFramesInterval == 0) {
1499        return 0;
1500    }
1501    OMX_U32 ret = frameRate * iFramesInterval;
1502    CHECK(ret > 1);
1503    return ret;
1504}
1505
1506status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) {
1507    int32_t bitrate, iFrameInterval;
1508    if (!msg->findInt32("bitrate", &bitrate)
1509            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
1510        return INVALID_OPERATION;
1511    }
1512
1513    float frameRate;
1514    if (!msg->findFloat("frame-rate", &frameRate)) {
1515        int32_t tmp;
1516        if (!msg->findInt32("frame-rate", &tmp)) {
1517            return INVALID_OPERATION;
1518        }
1519        frameRate = (float)tmp;
1520    }
1521
1522    OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type;
1523    InitOMXParams(&mpeg4type);
1524    mpeg4type.nPortIndex = kPortIndexOutput;
1525
1526    status_t err = mOMX->getParameter(
1527            mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
1528
1529    if (err != OK) {
1530        return err;
1531    }
1532
1533    mpeg4type.nSliceHeaderSpacing = 0;
1534    mpeg4type.bSVH = OMX_FALSE;
1535    mpeg4type.bGov = OMX_FALSE;
1536
1537    mpeg4type.nAllowedPictureTypes =
1538        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
1539
1540    mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
1541    if (mpeg4type.nPFrames == 0) {
1542        mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
1543    }
1544    mpeg4type.nBFrames = 0;
1545    mpeg4type.nIDCVLCThreshold = 0;
1546    mpeg4type.bACPred = OMX_TRUE;
1547    mpeg4type.nMaxPacketSize = 256;
1548    mpeg4type.nTimeIncRes = 1000;
1549    mpeg4type.nHeaderExtension = 0;
1550    mpeg4type.bReversibleVLC = OMX_FALSE;
1551
1552    int32_t profile;
1553    if (msg->findInt32("profile", &profile)) {
1554        int32_t level;
1555        if (!msg->findInt32("level", &level)) {
1556            return INVALID_OPERATION;
1557        }
1558
1559        err = verifySupportForProfileAndLevel(profile, level);
1560
1561        if (err != OK) {
1562            return err;
1563        }
1564
1565        mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile);
1566        mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level);
1567    }
1568
1569    err = mOMX->setParameter(
1570            mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
1571
1572    if (err != OK) {
1573        return err;
1574    }
1575
1576    err = configureBitrate(bitrate);
1577
1578    if (err != OK) {
1579        return err;
1580    }
1581
1582    return setupErrorCorrectionParameters();
1583}
1584
1585status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) {
1586    int32_t bitrate, iFrameInterval;
1587    if (!msg->findInt32("bitrate", &bitrate)
1588            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
1589        return INVALID_OPERATION;
1590    }
1591
1592    float frameRate;
1593    if (!msg->findFloat("frame-rate", &frameRate)) {
1594        int32_t tmp;
1595        if (!msg->findInt32("frame-rate", &tmp)) {
1596            return INVALID_OPERATION;
1597        }
1598        frameRate = (float)tmp;
1599    }
1600
1601    OMX_VIDEO_PARAM_H263TYPE h263type;
1602    InitOMXParams(&h263type);
1603    h263type.nPortIndex = kPortIndexOutput;
1604
1605    status_t err = mOMX->getParameter(
1606            mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
1607
1608    if (err != OK) {
1609        return err;
1610    }
1611
1612    h263type.nAllowedPictureTypes =
1613        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
1614
1615    h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
1616    if (h263type.nPFrames == 0) {
1617        h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
1618    }
1619    h263type.nBFrames = 0;
1620
1621    int32_t profile;
1622    if (msg->findInt32("profile", &profile)) {
1623        int32_t level;
1624        if (!msg->findInt32("level", &level)) {
1625            return INVALID_OPERATION;
1626        }
1627
1628        err = verifySupportForProfileAndLevel(profile, level);
1629
1630        if (err != OK) {
1631            return err;
1632        }
1633
1634        h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile);
1635        h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level);
1636    }
1637
1638    h263type.bPLUSPTYPEAllowed = OMX_FALSE;
1639    h263type.bForceRoundingTypeToZero = OMX_FALSE;
1640    h263type.nPictureHeaderRepetition = 0;
1641    h263type.nGOBHeaderInterval = 0;
1642
1643    err = mOMX->setParameter(
1644            mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
1645
1646    if (err != OK) {
1647        return err;
1648    }
1649
1650    err = configureBitrate(bitrate);
1651
1652    if (err != OK) {
1653        return err;
1654    }
1655
1656    return setupErrorCorrectionParameters();
1657}
1658
1659status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) {
1660    int32_t bitrate, iFrameInterval;
1661    if (!msg->findInt32("bitrate", &bitrate)
1662            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
1663        return INVALID_OPERATION;
1664    }
1665
1666    float frameRate;
1667    if (!msg->findFloat("frame-rate", &frameRate)) {
1668        int32_t tmp;
1669        if (!msg->findInt32("frame-rate", &tmp)) {
1670            return INVALID_OPERATION;
1671        }
1672        frameRate = (float)tmp;
1673    }
1674
1675    OMX_VIDEO_PARAM_AVCTYPE h264type;
1676    InitOMXParams(&h264type);
1677    h264type.nPortIndex = kPortIndexOutput;
1678
1679    status_t err = mOMX->getParameter(
1680            mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
1681
1682    if (err != OK) {
1683        return err;
1684    }
1685
1686    h264type.nAllowedPictureTypes =
1687        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
1688
1689    int32_t profile;
1690    if (msg->findInt32("profile", &profile)) {
1691        int32_t level;
1692        if (!msg->findInt32("level", &level)) {
1693            return INVALID_OPERATION;
1694        }
1695
1696        err = verifySupportForProfileAndLevel(profile, level);
1697
1698        if (err != OK) {
1699            return err;
1700        }
1701
1702        h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile);
1703        h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level);
1704    }
1705
1706    // XXX
1707    if (!strncmp(mComponentName.c_str(), "OMX.TI.DUCATI1", 14)) {
1708        h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
1709    }
1710
1711    if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
1712        h264type.nSliceHeaderSpacing = 0;
1713        h264type.bUseHadamard = OMX_TRUE;
1714        h264type.nRefFrames = 1;
1715        h264type.nBFrames = 0;
1716        h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
1717        if (h264type.nPFrames == 0) {
1718            h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
1719        }
1720        h264type.nRefIdx10ActiveMinus1 = 0;
1721        h264type.nRefIdx11ActiveMinus1 = 0;
1722        h264type.bEntropyCodingCABAC = OMX_FALSE;
1723        h264type.bWeightedPPrediction = OMX_FALSE;
1724        h264type.bconstIpred = OMX_FALSE;
1725        h264type.bDirect8x8Inference = OMX_FALSE;
1726        h264type.bDirectSpatialTemporal = OMX_FALSE;
1727        h264type.nCabacInitIdc = 0;
1728    }
1729
1730    if (h264type.nBFrames != 0) {
1731        h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
1732    }
1733
1734    h264type.bEnableUEP = OMX_FALSE;
1735    h264type.bEnableFMO = OMX_FALSE;
1736    h264type.bEnableASO = OMX_FALSE;
1737    h264type.bEnableRS = OMX_FALSE;
1738    h264type.bFrameMBsOnly = OMX_TRUE;
1739    h264type.bMBAFF = OMX_FALSE;
1740    h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
1741
1742    if (!strcasecmp("OMX.Nvidia.h264.encoder", mComponentName.c_str())) {
1743        h264type.eLevel = OMX_VIDEO_AVCLevelMax;
1744    }
1745
1746    err = mOMX->setParameter(
1747            mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
1748
1749    if (err != OK) {
1750        return err;
1751    }
1752
1753    return configureBitrate(bitrate);
1754}
1755
1756status_t ACodec::verifySupportForProfileAndLevel(
1757        int32_t profile, int32_t level) {
1758    OMX_VIDEO_PARAM_PROFILELEVELTYPE params;
1759    InitOMXParams(&params);
1760    params.nPortIndex = kPortIndexOutput;
1761
1762    for (params.nProfileIndex = 0;; ++params.nProfileIndex) {
1763        status_t err = mOMX->getParameter(
1764                mNode,
1765                OMX_IndexParamVideoProfileLevelQuerySupported,
1766                &params,
1767                sizeof(params));
1768
1769        if (err != OK) {
1770            return err;
1771        }
1772
1773        int32_t supportedProfile = static_cast<int32_t>(params.eProfile);
1774        int32_t supportedLevel = static_cast<int32_t>(params.eLevel);
1775
1776        if (profile == supportedProfile && level <= supportedLevel) {
1777            return OK;
1778        }
1779    }
1780}
1781
1782status_t ACodec::configureBitrate(int32_t bitrate) {
1783    OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
1784    InitOMXParams(&bitrateType);
1785    bitrateType.nPortIndex = kPortIndexOutput;
1786
1787    status_t err = mOMX->getParameter(
1788            mNode, OMX_IndexParamVideoBitrate,
1789            &bitrateType, sizeof(bitrateType));
1790
1791    if (err != OK) {
1792        return err;
1793    }
1794
1795    bitrateType.eControlRate = OMX_Video_ControlRateVariable;
1796    bitrateType.nTargetBitrate = bitrate;
1797
1798    return mOMX->setParameter(
1799            mNode, OMX_IndexParamVideoBitrate,
1800            &bitrateType, sizeof(bitrateType));
1801}
1802
1803status_t ACodec::setupErrorCorrectionParameters() {
1804    OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
1805    InitOMXParams(&errorCorrectionType);
1806    errorCorrectionType.nPortIndex = kPortIndexOutput;
1807
1808    status_t err = mOMX->getParameter(
1809            mNode, OMX_IndexParamVideoErrorCorrection,
1810            &errorCorrectionType, sizeof(errorCorrectionType));
1811
1812    if (err != OK) {
1813        return OK;  // Optional feature. Ignore this failure
1814    }
1815
1816    errorCorrectionType.bEnableHEC = OMX_FALSE;
1817    errorCorrectionType.bEnableResync = OMX_TRUE;
1818    errorCorrectionType.nResynchMarkerSpacing = 256;
1819    errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
1820    errorCorrectionType.bEnableRVLC = OMX_FALSE;
1821
1822    return mOMX->setParameter(
1823            mNode, OMX_IndexParamVideoErrorCorrection,
1824            &errorCorrectionType, sizeof(errorCorrectionType));
1825}
1826
1827status_t ACodec::setVideoFormatOnPort(
1828        OMX_U32 portIndex,
1829        int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat) {
1830    OMX_PARAM_PORTDEFINITIONTYPE def;
1831    InitOMXParams(&def);
1832    def.nPortIndex = portIndex;
1833
1834    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
1835
1836    status_t err = mOMX->getParameter(
1837            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1838
1839    CHECK_EQ(err, (status_t)OK);
1840
1841    if (portIndex == kPortIndexInput) {
1842        // XXX Need a (much) better heuristic to compute input buffer sizes.
1843        const size_t X = 64 * 1024;
1844        if (def.nBufferSize < X) {
1845            def.nBufferSize = X;
1846        }
1847    }
1848
1849    CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
1850
1851    video_def->nFrameWidth = width;
1852    video_def->nFrameHeight = height;
1853
1854    if (portIndex == kPortIndexInput) {
1855        video_def->eCompressionFormat = compressionFormat;
1856        video_def->eColorFormat = OMX_COLOR_FormatUnused;
1857    }
1858
1859    err = mOMX->setParameter(
1860            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1861
1862    return err;
1863}
1864
1865status_t ACodec::initNativeWindow() {
1866    if (mNativeWindow != NULL) {
1867        return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE);
1868    }
1869
1870    mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE);
1871    return OK;
1872}
1873
1874size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const {
1875    size_t n = 0;
1876
1877    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
1878        const BufferInfo &info = mBuffers[portIndex].itemAt(i);
1879
1880        if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) {
1881            ++n;
1882        }
1883    }
1884
1885    return n;
1886}
1887
1888bool ACodec::allYourBuffersAreBelongToUs(
1889        OMX_U32 portIndex) {
1890    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
1891        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
1892
1893        if (info->mStatus != BufferInfo::OWNED_BY_US
1894                && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
1895            ALOGV("[%s] Buffer %p on port %ld still has status %d",
1896                    mComponentName.c_str(),
1897                    info->mBufferID, portIndex, info->mStatus);
1898            return false;
1899        }
1900    }
1901
1902    return true;
1903}
1904
1905bool ACodec::allYourBuffersAreBelongToUs() {
1906    return allYourBuffersAreBelongToUs(kPortIndexInput)
1907        && allYourBuffersAreBelongToUs(kPortIndexOutput);
1908}
1909
1910void ACodec::deferMessage(const sp<AMessage> &msg) {
1911    bool wasEmptyBefore = mDeferredQueue.empty();
1912    mDeferredQueue.push_back(msg);
1913}
1914
1915void ACodec::processDeferredMessages() {
1916    List<sp<AMessage> > queue = mDeferredQueue;
1917    mDeferredQueue.clear();
1918
1919    List<sp<AMessage> >::iterator it = queue.begin();
1920    while (it != queue.end()) {
1921        onMessageReceived(*it++);
1922    }
1923}
1924
1925void ACodec::sendFormatChange() {
1926    sp<AMessage> notify = mNotify->dup();
1927    notify->setInt32("what", kWhatOutputFormatChanged);
1928
1929    OMX_PARAM_PORTDEFINITIONTYPE def;
1930    InitOMXParams(&def);
1931    def.nPortIndex = kPortIndexOutput;
1932
1933    CHECK_EQ(mOMX->getParameter(
1934                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)),
1935             (status_t)OK);
1936
1937    CHECK_EQ((int)def.eDir, (int)OMX_DirOutput);
1938
1939    switch (def.eDomain) {
1940        case OMX_PortDomainVideo:
1941        {
1942            OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
1943
1944            notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW);
1945            notify->setInt32("width", videoDef->nFrameWidth);
1946            notify->setInt32("height", videoDef->nFrameHeight);
1947            notify->setInt32("stride", videoDef->nStride);
1948            notify->setInt32("slice-height", videoDef->nSliceHeight);
1949            notify->setInt32("color-format", videoDef->eColorFormat);
1950
1951            OMX_CONFIG_RECTTYPE rect;
1952            InitOMXParams(&rect);
1953            rect.nPortIndex = kPortIndexOutput;
1954
1955            if (mOMX->getConfig(
1956                        mNode, OMX_IndexConfigCommonOutputCrop,
1957                        &rect, sizeof(rect)) != OK) {
1958                rect.nLeft = 0;
1959                rect.nTop = 0;
1960                rect.nWidth = videoDef->nFrameWidth;
1961                rect.nHeight = videoDef->nFrameHeight;
1962            }
1963
1964            CHECK_GE(rect.nLeft, 0);
1965            CHECK_GE(rect.nTop, 0);
1966            CHECK_GE(rect.nWidth, 0u);
1967            CHECK_GE(rect.nHeight, 0u);
1968            CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth);
1969            CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight);
1970
1971            notify->setRect(
1972                    "crop",
1973                    rect.nLeft,
1974                    rect.nTop,
1975                    rect.nLeft + rect.nWidth - 1,
1976                    rect.nTop + rect.nHeight - 1);
1977
1978            if (mNativeWindow != NULL) {
1979                android_native_rect_t crop;
1980                crop.left = rect.nLeft;
1981                crop.top = rect.nTop;
1982                crop.right = rect.nLeft + rect.nWidth;
1983                crop.bottom = rect.nTop + rect.nHeight;
1984
1985                CHECK_EQ(0, native_window_set_crop(
1986                            mNativeWindow.get(), &crop));
1987            }
1988            break;
1989        }
1990
1991        case OMX_PortDomainAudio:
1992        {
1993            OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
1994            CHECK_EQ((int)audioDef->eEncoding, (int)OMX_AUDIO_CodingPCM);
1995
1996            OMX_AUDIO_PARAM_PCMMODETYPE params;
1997            InitOMXParams(&params);
1998            params.nPortIndex = kPortIndexOutput;
1999
2000            CHECK_EQ(mOMX->getParameter(
2001                        mNode, OMX_IndexParamAudioPcm,
2002                        &params, sizeof(params)),
2003                     (status_t)OK);
2004
2005            CHECK(params.nChannels == 1 || params.bInterleaved);
2006            CHECK_EQ(params.nBitPerSample, 16u);
2007            CHECK_EQ((int)params.eNumData, (int)OMX_NumericalDataSigned);
2008            CHECK_EQ((int)params.ePCMMode, (int)OMX_AUDIO_PCMModeLinear);
2009
2010            notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
2011            notify->setInt32("channel-count", params.nChannels);
2012            notify->setInt32("sample-rate", params.nSamplingRate);
2013            if (mEncoderDelay + mEncoderPadding) {
2014                size_t frameSize = params.nChannels * sizeof(int16_t);
2015                if (mSkipCutBuffer != NULL) {
2016                    size_t prevbufsize = mSkipCutBuffer->size();
2017                    if (prevbufsize != 0) {
2018                        ALOGW("Replacing SkipCutBuffer holding %d bytes", prevbufsize);
2019                    }
2020                }
2021                mSkipCutBuffer = new SkipCutBuffer(mEncoderDelay * frameSize,
2022                                                   mEncoderPadding * frameSize);
2023            }
2024            break;
2025        }
2026
2027        default:
2028            TRESPASS();
2029    }
2030
2031    notify->post();
2032
2033    mSentFormat = true;
2034}
2035
2036void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) {
2037    sp<AMessage> notify = mNotify->dup();
2038    notify->setInt32("what", ACodec::kWhatError);
2039    notify->setInt32("omx-error", error);
2040    notify->setInt32("err", internalError);
2041    notify->post();
2042}
2043
2044////////////////////////////////////////////////////////////////////////////////
2045
2046ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
2047    : AState(parentState),
2048      mCodec(codec) {
2049}
2050
2051ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(OMX_U32 portIndex) {
2052    return KEEP_BUFFERS;
2053}
2054
2055bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) {
2056    switch (msg->what()) {
2057        case kWhatInputBufferFilled:
2058        {
2059            onInputBufferFilled(msg);
2060            break;
2061        }
2062
2063        case kWhatOutputBufferDrained:
2064        {
2065            onOutputBufferDrained(msg);
2066            break;
2067        }
2068
2069        case ACodec::kWhatOMXMessage:
2070        {
2071            return onOMXMessage(msg);
2072        }
2073
2074        default:
2075            return false;
2076    }
2077
2078    return true;
2079}
2080
2081bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) {
2082    int32_t type;
2083    CHECK(msg->findInt32("type", &type));
2084
2085    IOMX::node_id nodeID;
2086    CHECK(msg->findPointer("node", &nodeID));
2087    CHECK_EQ(nodeID, mCodec->mNode);
2088
2089    switch (type) {
2090        case omx_message::EVENT:
2091        {
2092            int32_t event, data1, data2;
2093            CHECK(msg->findInt32("event", &event));
2094            CHECK(msg->findInt32("data1", &data1));
2095            CHECK(msg->findInt32("data2", &data2));
2096
2097            if (event == OMX_EventCmdComplete
2098                    && data1 == OMX_CommandFlush
2099                    && data2 == (int32_t)OMX_ALL) {
2100                // Use of this notification is not consistent across
2101                // implementations. We'll drop this notification and rely
2102                // on flush-complete notifications on the individual port
2103                // indices instead.
2104
2105                return true;
2106            }
2107
2108            return onOMXEvent(
2109                    static_cast<OMX_EVENTTYPE>(event),
2110                    static_cast<OMX_U32>(data1),
2111                    static_cast<OMX_U32>(data2));
2112        }
2113
2114        case omx_message::EMPTY_BUFFER_DONE:
2115        {
2116            IOMX::buffer_id bufferID;
2117            CHECK(msg->findPointer("buffer", &bufferID));
2118
2119            return onOMXEmptyBufferDone(bufferID);
2120        }
2121
2122        case omx_message::FILL_BUFFER_DONE:
2123        {
2124            IOMX::buffer_id bufferID;
2125            CHECK(msg->findPointer("buffer", &bufferID));
2126
2127            int32_t rangeOffset, rangeLength, flags;
2128            int64_t timeUs;
2129            void *platformPrivate;
2130            void *dataPtr;
2131
2132            CHECK(msg->findInt32("range_offset", &rangeOffset));
2133            CHECK(msg->findInt32("range_length", &rangeLength));
2134            CHECK(msg->findInt32("flags", &flags));
2135            CHECK(msg->findInt64("timestamp", &timeUs));
2136            CHECK(msg->findPointer("platform_private", &platformPrivate));
2137            CHECK(msg->findPointer("data_ptr", &dataPtr));
2138
2139            return onOMXFillBufferDone(
2140                    bufferID,
2141                    (size_t)rangeOffset, (size_t)rangeLength,
2142                    (OMX_U32)flags,
2143                    timeUs,
2144                    platformPrivate,
2145                    dataPtr);
2146        }
2147
2148        default:
2149            TRESPASS();
2150            break;
2151    }
2152}
2153
2154bool ACodec::BaseState::onOMXEvent(
2155        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2156    if (event != OMX_EventError) {
2157        ALOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)",
2158             mCodec->mComponentName.c_str(), event, data1, data2);
2159
2160        return false;
2161    }
2162
2163    ALOGE("[%s] ERROR(0x%08lx)", mCodec->mComponentName.c_str(), data1);
2164
2165    mCodec->signalError((OMX_ERRORTYPE)data1);
2166
2167    return true;
2168}
2169
2170bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) {
2171    ALOGV("[%s] onOMXEmptyBufferDone %p",
2172         mCodec->mComponentName.c_str(), bufferID);
2173
2174    BufferInfo *info =
2175        mCodec->findBufferByID(kPortIndexInput, bufferID);
2176
2177    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
2178    info->mStatus = BufferInfo::OWNED_BY_US;
2179
2180    PortMode mode = getPortMode(kPortIndexInput);
2181
2182    switch (mode) {
2183        case KEEP_BUFFERS:
2184            break;
2185
2186        case RESUBMIT_BUFFERS:
2187            postFillThisBuffer(info);
2188            break;
2189
2190        default:
2191        {
2192            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
2193            TRESPASS();  // Not currently used
2194            break;
2195        }
2196    }
2197
2198    return true;
2199}
2200
2201void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) {
2202    if (mCodec->mPortEOS[kPortIndexInput]) {
2203        return;
2204    }
2205
2206    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
2207
2208    sp<AMessage> notify = mCodec->mNotify->dup();
2209    notify->setInt32("what", ACodec::kWhatFillThisBuffer);
2210    notify->setPointer("buffer-id", info->mBufferID);
2211
2212    info->mData->meta()->clear();
2213    notify->setBuffer("buffer", info->mData);
2214
2215    sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id());
2216    reply->setPointer("buffer-id", info->mBufferID);
2217
2218    notify->setMessage("reply", reply);
2219
2220    notify->post();
2221
2222    info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
2223}
2224
2225void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
2226    IOMX::buffer_id bufferID;
2227    CHECK(msg->findPointer("buffer-id", &bufferID));
2228
2229    sp<ABuffer> buffer;
2230    int32_t err = OK;
2231    bool eos = false;
2232
2233    if (!msg->findBuffer("buffer", &buffer)) {
2234        CHECK(msg->findInt32("err", &err));
2235
2236        ALOGV("[%s] saw error %d instead of an input buffer",
2237             mCodec->mComponentName.c_str(), err);
2238
2239        buffer.clear();
2240
2241        eos = true;
2242    }
2243
2244    int32_t tmp;
2245    if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) {
2246        eos = true;
2247        err = ERROR_END_OF_STREAM;
2248    }
2249
2250    BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
2251    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM);
2252
2253    info->mStatus = BufferInfo::OWNED_BY_US;
2254
2255    PortMode mode = getPortMode(kPortIndexInput);
2256
2257    switch (mode) {
2258        case KEEP_BUFFERS:
2259        {
2260            if (eos) {
2261                if (!mCodec->mPortEOS[kPortIndexInput]) {
2262                    mCodec->mPortEOS[kPortIndexInput] = true;
2263                    mCodec->mInputEOSResult = err;
2264                }
2265            }
2266            break;
2267        }
2268
2269        case RESUBMIT_BUFFERS:
2270        {
2271            if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) {
2272                int64_t timeUs;
2273                CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
2274
2275                OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
2276
2277                int32_t isCSD;
2278                if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) {
2279                    flags |= OMX_BUFFERFLAG_CODECCONFIG;
2280                }
2281
2282                if (eos) {
2283                    flags |= OMX_BUFFERFLAG_EOS;
2284                }
2285
2286                if (buffer != info->mData) {
2287                    if (0 && !(flags & OMX_BUFFERFLAG_CODECCONFIG)) {
2288                        ALOGV("[%s] Needs to copy input data.",
2289                             mCodec->mComponentName.c_str());
2290                    }
2291
2292                    CHECK_LE(buffer->size(), info->mData->capacity());
2293                    memcpy(info->mData->data(), buffer->data(), buffer->size());
2294                }
2295
2296                if (flags & OMX_BUFFERFLAG_CODECCONFIG) {
2297                    ALOGV("[%s] calling emptyBuffer %p w/ codec specific data",
2298                         mCodec->mComponentName.c_str(), bufferID);
2299                } else if (flags & OMX_BUFFERFLAG_EOS) {
2300                    ALOGV("[%s] calling emptyBuffer %p w/ EOS",
2301                         mCodec->mComponentName.c_str(), bufferID);
2302                } else {
2303                    ALOGV("[%s] calling emptyBuffer %p w/ time %lld us",
2304                         mCodec->mComponentName.c_str(), bufferID, timeUs);
2305                }
2306
2307                CHECK_EQ(mCodec->mOMX->emptyBuffer(
2308                            mCodec->mNode,
2309                            bufferID,
2310                            0,
2311                            buffer->size(),
2312                            flags,
2313                            timeUs),
2314                         (status_t)OK);
2315
2316                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
2317
2318                if (!eos) {
2319                    getMoreInputDataIfPossible();
2320                } else {
2321                    ALOGV("[%s] Signalled EOS on the input port",
2322                         mCodec->mComponentName.c_str());
2323
2324                    mCodec->mPortEOS[kPortIndexInput] = true;
2325                    mCodec->mInputEOSResult = err;
2326                }
2327            } else if (!mCodec->mPortEOS[kPortIndexInput]) {
2328                if (err != ERROR_END_OF_STREAM) {
2329                    ALOGV("[%s] Signalling EOS on the input port "
2330                         "due to error %d",
2331                         mCodec->mComponentName.c_str(), err);
2332                } else {
2333                    ALOGV("[%s] Signalling EOS on the input port",
2334                         mCodec->mComponentName.c_str());
2335                }
2336
2337                ALOGV("[%s] calling emptyBuffer %p signalling EOS",
2338                     mCodec->mComponentName.c_str(), bufferID);
2339
2340                CHECK_EQ(mCodec->mOMX->emptyBuffer(
2341                            mCodec->mNode,
2342                            bufferID,
2343                            0,
2344                            0,
2345                            OMX_BUFFERFLAG_EOS,
2346                            0),
2347                         (status_t)OK);
2348
2349                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
2350
2351                mCodec->mPortEOS[kPortIndexInput] = true;
2352                mCodec->mInputEOSResult = err;
2353            }
2354            break;
2355
2356            default:
2357                CHECK_EQ((int)mode, (int)FREE_BUFFERS);
2358                break;
2359        }
2360    }
2361}
2362
2363void ACodec::BaseState::getMoreInputDataIfPossible() {
2364    if (mCodec->mPortEOS[kPortIndexInput]) {
2365        return;
2366    }
2367
2368    BufferInfo *eligible = NULL;
2369
2370    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
2371        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
2372
2373#if 0
2374        if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) {
2375            // There's already a "read" pending.
2376            return;
2377        }
2378#endif
2379
2380        if (info->mStatus == BufferInfo::OWNED_BY_US) {
2381            eligible = info;
2382        }
2383    }
2384
2385    if (eligible == NULL) {
2386        return;
2387    }
2388
2389    postFillThisBuffer(eligible);
2390}
2391
2392bool ACodec::BaseState::onOMXFillBufferDone(
2393        IOMX::buffer_id bufferID,
2394        size_t rangeOffset, size_t rangeLength,
2395        OMX_U32 flags,
2396        int64_t timeUs,
2397        void *platformPrivate,
2398        void *dataPtr) {
2399    ALOGV("[%s] onOMXFillBufferDone %p time %lld us, flags = 0x%08lx",
2400         mCodec->mComponentName.c_str(), bufferID, timeUs, flags);
2401
2402    ssize_t index;
2403    BufferInfo *info =
2404        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
2405
2406    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
2407
2408    info->mStatus = BufferInfo::OWNED_BY_US;
2409
2410    PortMode mode = getPortMode(kPortIndexOutput);
2411
2412    switch (mode) {
2413        case KEEP_BUFFERS:
2414            break;
2415
2416        case RESUBMIT_BUFFERS:
2417        {
2418            if (rangeLength == 0 && !(flags & OMX_BUFFERFLAG_EOS)) {
2419                ALOGV("[%s] calling fillBuffer %p",
2420                     mCodec->mComponentName.c_str(), info->mBufferID);
2421
2422                CHECK_EQ(mCodec->mOMX->fillBuffer(
2423                            mCodec->mNode, info->mBufferID),
2424                         (status_t)OK);
2425
2426                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
2427                break;
2428            }
2429
2430            if (!mCodec->mIsEncoder && !mCodec->mSentFormat) {
2431                mCodec->sendFormatChange();
2432            }
2433
2434            if (mCodec->mNativeWindow == NULL) {
2435                info->mData->setRange(rangeOffset, rangeLength);
2436            }
2437
2438            if (mCodec->mSkipCutBuffer != NULL) {
2439                mCodec->mSkipCutBuffer->submit(info->mData);
2440            }
2441            info->mData->meta()->setInt64("timeUs", timeUs);
2442
2443            sp<AMessage> notify = mCodec->mNotify->dup();
2444            notify->setInt32("what", ACodec::kWhatDrainThisBuffer);
2445            notify->setPointer("buffer-id", info->mBufferID);
2446            notify->setBuffer("buffer", info->mData);
2447            notify->setInt32("flags", flags);
2448
2449            sp<AMessage> reply =
2450                new AMessage(kWhatOutputBufferDrained, mCodec->id());
2451
2452            reply->setPointer("buffer-id", info->mBufferID);
2453
2454            notify->setMessage("reply", reply);
2455
2456            notify->post();
2457
2458            info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;
2459
2460            if (flags & OMX_BUFFERFLAG_EOS) {
2461                ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str());
2462
2463                sp<AMessage> notify = mCodec->mNotify->dup();
2464                notify->setInt32("what", ACodec::kWhatEOS);
2465                notify->setInt32("err", mCodec->mInputEOSResult);
2466                notify->post();
2467
2468                mCodec->mPortEOS[kPortIndexOutput] = true;
2469            }
2470            break;
2471        }
2472
2473        default:
2474        {
2475            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
2476
2477            CHECK_EQ((status_t)OK,
2478                     mCodec->freeBuffer(kPortIndexOutput, index));
2479            break;
2480        }
2481    }
2482
2483    return true;
2484}
2485
2486void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
2487    IOMX::buffer_id bufferID;
2488    CHECK(msg->findPointer("buffer-id", &bufferID));
2489
2490    ssize_t index;
2491    BufferInfo *info =
2492        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
2493    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
2494
2495    int32_t render;
2496    if (mCodec->mNativeWindow != NULL
2497            && msg->findInt32("render", &render) && render != 0) {
2498        // The client wants this buffer to be rendered.
2499
2500        status_t err;
2501        if ((err = mCodec->mNativeWindow->queueBuffer(
2502                    mCodec->mNativeWindow.get(),
2503                    info->mGraphicBuffer.get())) == OK) {
2504            info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
2505        } else {
2506            mCodec->signalError(OMX_ErrorUndefined, err);
2507            info->mStatus = BufferInfo::OWNED_BY_US;
2508        }
2509    } else {
2510        info->mStatus = BufferInfo::OWNED_BY_US;
2511    }
2512
2513    PortMode mode = getPortMode(kPortIndexOutput);
2514
2515    switch (mode) {
2516        case KEEP_BUFFERS:
2517        {
2518            // XXX fishy, revisit!!! What about the FREE_BUFFERS case below?
2519
2520            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
2521                // We cannot resubmit the buffer we just rendered, dequeue
2522                // the spare instead.
2523
2524                info = mCodec->dequeueBufferFromNativeWindow();
2525            }
2526            break;
2527        }
2528
2529        case RESUBMIT_BUFFERS:
2530        {
2531            if (!mCodec->mPortEOS[kPortIndexOutput]) {
2532                if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
2533                    // We cannot resubmit the buffer we just rendered, dequeue
2534                    // the spare instead.
2535
2536                    info = mCodec->dequeueBufferFromNativeWindow();
2537                }
2538
2539                if (info != NULL) {
2540                    ALOGV("[%s] calling fillBuffer %p",
2541                         mCodec->mComponentName.c_str(), info->mBufferID);
2542
2543                    CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
2544                             (status_t)OK);
2545
2546                    info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
2547                }
2548            }
2549            break;
2550        }
2551
2552        default:
2553        {
2554            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
2555
2556            CHECK_EQ((status_t)OK,
2557                     mCodec->freeBuffer(kPortIndexOutput, index));
2558            break;
2559        }
2560    }
2561}
2562
2563////////////////////////////////////////////////////////////////////////////////
2564
2565ACodec::UninitializedState::UninitializedState(ACodec *codec)
2566    : BaseState(codec) {
2567}
2568
2569void ACodec::UninitializedState::stateEntered() {
2570    ALOGV("Now uninitialized");
2571}
2572
2573bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
2574    bool handled = false;
2575
2576    switch (msg->what()) {
2577        case ACodec::kWhatSetup:
2578        {
2579            onSetup(msg);
2580
2581            handled = true;
2582            break;
2583        }
2584
2585        case ACodec::kWhatAllocateComponent:
2586        {
2587            onAllocateComponent(msg);
2588            handled = true;
2589            break;
2590        }
2591
2592        case ACodec::kWhatShutdown:
2593        {
2594            int32_t keepComponentAllocated;
2595            CHECK(msg->findInt32(
2596                        "keepComponentAllocated", &keepComponentAllocated));
2597            CHECK(!keepComponentAllocated);
2598
2599            sp<AMessage> notify = mCodec->mNotify->dup();
2600            notify->setInt32("what", ACodec::kWhatShutdownCompleted);
2601            notify->post();
2602
2603            handled = true;
2604            break;
2605        }
2606
2607        case ACodec::kWhatFlush:
2608        {
2609            sp<AMessage> notify = mCodec->mNotify->dup();
2610            notify->setInt32("what", ACodec::kWhatFlushCompleted);
2611            notify->post();
2612
2613            handled = true;
2614            break;
2615        }
2616
2617        default:
2618            return BaseState::onMessageReceived(msg);
2619    }
2620
2621    return handled;
2622}
2623
2624void ACodec::UninitializedState::onSetup(
2625        const sp<AMessage> &msg) {
2626    if (onAllocateComponent(msg)
2627            && mCodec->mLoadedState->onConfigureComponent(msg)) {
2628        mCodec->mLoadedState->onStart();
2629    }
2630}
2631
2632bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
2633    ALOGV("onAllocateComponent");
2634
2635    CHECK(mCodec->mNode == NULL);
2636
2637    OMXClient client;
2638    CHECK_EQ(client.connect(), (status_t)OK);
2639
2640    sp<IOMX> omx = client.interface();
2641
2642    Vector<String8> matchingCodecs;
2643    Vector<uint32_t> matchingCodecQuirks;
2644
2645    AString mime;
2646
2647    AString componentName;
2648    uint32_t quirks;
2649    if (msg->findString("componentName", &componentName)) {
2650        matchingCodecs.push_back(String8(componentName.c_str()));
2651
2652        if (!OMXCodec::findCodecQuirks(componentName.c_str(), &quirks)) {
2653            quirks = 0;
2654        }
2655        matchingCodecQuirks.push_back(quirks);
2656    } else {
2657        CHECK(msg->findString("mime", &mime));
2658
2659        int32_t encoder;
2660        if (!msg->findInt32("encoder", &encoder)) {
2661            encoder = false;
2662        }
2663
2664        OMXCodec::findMatchingCodecs(
2665                mime.c_str(),
2666                encoder, // createEncoder
2667                NULL,  // matchComponentName
2668                0,     // flags
2669                &matchingCodecs,
2670                &matchingCodecQuirks);
2671    }
2672
2673    sp<CodecObserver> observer = new CodecObserver;
2674    IOMX::node_id node = NULL;
2675
2676    for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
2677            ++matchIndex) {
2678        componentName = matchingCodecs.itemAt(matchIndex).string();
2679        quirks = matchingCodecQuirks.itemAt(matchIndex);
2680
2681        pid_t tid = androidGetTid();
2682        int prevPriority = androidGetThreadPriority(tid);
2683        androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
2684        status_t err = omx->allocateNode(componentName.c_str(), observer, &node);
2685        androidSetThreadPriority(tid, prevPriority);
2686
2687        if (err == OK) {
2688            break;
2689        }
2690
2691        node = NULL;
2692    }
2693
2694    if (node == NULL) {
2695        if (!mime.empty()) {
2696            ALOGE("Unable to instantiate a decoder for type '%s'.",
2697                 mime.c_str());
2698        } else {
2699            ALOGE("Unable to instantiate decoder '%s'.", componentName.c_str());
2700        }
2701
2702        mCodec->signalError(OMX_ErrorComponentNotFound);
2703        return false;
2704    }
2705
2706    sp<AMessage> notify = new AMessage(kWhatOMXMessage, mCodec->id());
2707    observer->setNotificationMessage(notify);
2708
2709    mCodec->mComponentName = componentName;
2710    mCodec->mFlags = 0;
2711
2712    if (componentName.endsWith(".secure")) {
2713        mCodec->mFlags |= kFlagIsSecure;
2714    }
2715
2716    mCodec->mQuirks = quirks;
2717    mCodec->mOMX = omx;
2718    mCodec->mNode = node;
2719
2720    mCodec->mPortEOS[kPortIndexInput] =
2721        mCodec->mPortEOS[kPortIndexOutput] = false;
2722
2723    mCodec->mInputEOSResult = OK;
2724
2725    {
2726        sp<AMessage> notify = mCodec->mNotify->dup();
2727        notify->setInt32("what", ACodec::kWhatComponentAllocated);
2728        notify->setString("componentName", mCodec->mComponentName.c_str());
2729        notify->post();
2730    }
2731
2732    mCodec->changeState(mCodec->mLoadedState);
2733
2734    return true;
2735}
2736
2737////////////////////////////////////////////////////////////////////////////////
2738
2739ACodec::LoadedState::LoadedState(ACodec *codec)
2740    : BaseState(codec) {
2741}
2742
2743void ACodec::LoadedState::stateEntered() {
2744    ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
2745
2746    if (mCodec->mShutdownInProgress) {
2747        bool keepComponentAllocated = mCodec->mKeepComponentAllocated;
2748
2749        mCodec->mShutdownInProgress = false;
2750        mCodec->mKeepComponentAllocated = false;
2751
2752        onShutdown(keepComponentAllocated);
2753    }
2754}
2755
2756void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) {
2757    if (!keepComponentAllocated) {
2758        CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
2759
2760        mCodec->mNativeWindow.clear();
2761        mCodec->mNode = NULL;
2762        mCodec->mOMX.clear();
2763        mCodec->mQuirks = 0;
2764        mCodec->mFlags = 0;
2765        mCodec->mComponentName.clear();
2766
2767        mCodec->changeState(mCodec->mUninitializedState);
2768    }
2769
2770    sp<AMessage> notify = mCodec->mNotify->dup();
2771    notify->setInt32("what", ACodec::kWhatShutdownCompleted);
2772    notify->post();
2773}
2774
2775bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) {
2776    bool handled = false;
2777
2778    switch (msg->what()) {
2779        case ACodec::kWhatConfigureComponent:
2780        {
2781            onConfigureComponent(msg);
2782            handled = true;
2783            break;
2784        }
2785
2786        case ACodec::kWhatStart:
2787        {
2788            onStart();
2789            handled = true;
2790            break;
2791        }
2792
2793        case ACodec::kWhatShutdown:
2794        {
2795            int32_t keepComponentAllocated;
2796            CHECK(msg->findInt32(
2797                        "keepComponentAllocated", &keepComponentAllocated));
2798
2799            onShutdown(keepComponentAllocated);
2800
2801            handled = true;
2802            break;
2803        }
2804
2805        case ACodec::kWhatFlush:
2806        {
2807            sp<AMessage> notify = mCodec->mNotify->dup();
2808            notify->setInt32("what", ACodec::kWhatFlushCompleted);
2809            notify->post();
2810
2811            handled = true;
2812            break;
2813        }
2814
2815        default:
2816            return BaseState::onMessageReceived(msg);
2817    }
2818
2819    return handled;
2820}
2821
2822bool ACodec::LoadedState::onConfigureComponent(
2823        const sp<AMessage> &msg) {
2824    ALOGV("onConfigureComponent");
2825
2826    CHECK(mCodec->mNode != NULL);
2827
2828    AString mime;
2829    CHECK(msg->findString("mime", &mime));
2830
2831    status_t err = mCodec->configureCodec(mime.c_str(), msg);
2832
2833    if (err != OK) {
2834        ALOGE("[%s] configureCodec returning error %d",
2835              mCodec->mComponentName.c_str(), err);
2836
2837        mCodec->signalError(OMX_ErrorUndefined, err);
2838        return false;
2839    }
2840
2841    sp<RefBase> obj;
2842    if (msg->findObject("native-window", &obj)
2843            && strncmp("OMX.google.", mCodec->mComponentName.c_str(), 11)) {
2844        sp<NativeWindowWrapper> nativeWindow(
2845                static_cast<NativeWindowWrapper *>(obj.get()));
2846        CHECK(nativeWindow != NULL);
2847        mCodec->mNativeWindow = nativeWindow->getNativeWindow();
2848    }
2849    CHECK_EQ((status_t)OK, mCodec->initNativeWindow());
2850
2851    {
2852        sp<AMessage> notify = mCodec->mNotify->dup();
2853        notify->setInt32("what", ACodec::kWhatComponentConfigured);
2854        notify->post();
2855    }
2856
2857    return true;
2858}
2859
2860void ACodec::LoadedState::onStart() {
2861    ALOGV("onStart");
2862
2863    CHECK_EQ(mCodec->mOMX->sendCommand(
2864                mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
2865             (status_t)OK);
2866
2867    mCodec->changeState(mCodec->mLoadedToIdleState);
2868}
2869
2870////////////////////////////////////////////////////////////////////////////////
2871
2872ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec)
2873    : BaseState(codec) {
2874}
2875
2876void ACodec::LoadedToIdleState::stateEntered() {
2877    ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
2878
2879    status_t err;
2880    if ((err = allocateBuffers()) != OK) {
2881        ALOGE("Failed to allocate buffers after transitioning to IDLE state "
2882             "(error 0x%08x)",
2883             err);
2884
2885        mCodec->signalError(OMX_ErrorUndefined, err);
2886    }
2887}
2888
2889status_t ACodec::LoadedToIdleState::allocateBuffers() {
2890    status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput);
2891
2892    if (err != OK) {
2893        return err;
2894    }
2895
2896    return mCodec->allocateBuffersOnPort(kPortIndexOutput);
2897}
2898
2899bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
2900    switch (msg->what()) {
2901        case kWhatShutdown:
2902        {
2903            mCodec->deferMessage(msg);
2904            return true;
2905        }
2906
2907        default:
2908            return BaseState::onMessageReceived(msg);
2909    }
2910}
2911
2912bool ACodec::LoadedToIdleState::onOMXEvent(
2913        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2914    switch (event) {
2915        case OMX_EventCmdComplete:
2916        {
2917            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
2918            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
2919
2920            CHECK_EQ(mCodec->mOMX->sendCommand(
2921                        mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting),
2922                     (status_t)OK);
2923
2924            mCodec->changeState(mCodec->mIdleToExecutingState);
2925
2926            return true;
2927        }
2928
2929        default:
2930            return BaseState::onOMXEvent(event, data1, data2);
2931    }
2932}
2933
2934////////////////////////////////////////////////////////////////////////////////
2935
2936ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec)
2937    : BaseState(codec) {
2938}
2939
2940void ACodec::IdleToExecutingState::stateEntered() {
2941    ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
2942}
2943
2944bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
2945    switch (msg->what()) {
2946        case kWhatShutdown:
2947        {
2948            mCodec->deferMessage(msg);
2949            return true;
2950        }
2951
2952        default:
2953            return BaseState::onMessageReceived(msg);
2954    }
2955}
2956
2957bool ACodec::IdleToExecutingState::onOMXEvent(
2958        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2959    switch (event) {
2960        case OMX_EventCmdComplete:
2961        {
2962            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
2963            CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting);
2964
2965            mCodec->mExecutingState->resume();
2966            mCodec->changeState(mCodec->mExecutingState);
2967
2968            return true;
2969        }
2970
2971        default:
2972            return BaseState::onOMXEvent(event, data1, data2);
2973    }
2974}
2975
2976////////////////////////////////////////////////////////////////////////////////
2977
2978ACodec::ExecutingState::ExecutingState(ACodec *codec)
2979    : BaseState(codec),
2980      mActive(false) {
2981}
2982
2983ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode(
2984        OMX_U32 portIndex) {
2985    return RESUBMIT_BUFFERS;
2986}
2987
2988void ACodec::ExecutingState::submitOutputBuffers() {
2989    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
2990        BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
2991
2992        if (mCodec->mNativeWindow != NULL) {
2993            CHECK(info->mStatus == BufferInfo::OWNED_BY_US
2994                    || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
2995
2996            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
2997                continue;
2998            }
2999
3000            status_t err = mCodec->mNativeWindow->lockBuffer(
3001                    mCodec->mNativeWindow.get(),
3002                    info->mGraphicBuffer.get());
3003            CHECK_EQ(err, (status_t)OK);
3004        } else {
3005            CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
3006        }
3007
3008        ALOGV("[%s] calling fillBuffer %p",
3009             mCodec->mComponentName.c_str(), info->mBufferID);
3010
3011        CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
3012                 (status_t)OK);
3013
3014        info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
3015    }
3016}
3017
3018void ACodec::ExecutingState::resume() {
3019    if (mActive) {
3020        ALOGV("[%s] We're already active, no need to resume.",
3021             mCodec->mComponentName.c_str());
3022
3023        return;
3024    }
3025
3026    submitOutputBuffers();
3027
3028    // Post the first input buffer.
3029    CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u);
3030    BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(0);
3031
3032    postFillThisBuffer(info);
3033
3034    mActive = true;
3035}
3036
3037void ACodec::ExecutingState::stateEntered() {
3038    ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
3039
3040    mCodec->processDeferredMessages();
3041}
3042
3043bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) {
3044    bool handled = false;
3045
3046    switch (msg->what()) {
3047        case kWhatShutdown:
3048        {
3049            int32_t keepComponentAllocated;
3050            CHECK(msg->findInt32(
3051                        "keepComponentAllocated", &keepComponentAllocated));
3052
3053            mCodec->mShutdownInProgress = true;
3054            mCodec->mKeepComponentAllocated = keepComponentAllocated;
3055
3056            mActive = false;
3057
3058            CHECK_EQ(mCodec->mOMX->sendCommand(
3059                        mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
3060                     (status_t)OK);
3061
3062            mCodec->changeState(mCodec->mExecutingToIdleState);
3063
3064            handled = true;
3065            break;
3066        }
3067
3068        case kWhatFlush:
3069        {
3070            ALOGV("[%s] ExecutingState flushing now "
3071                 "(codec owns %d/%d input, %d/%d output).",
3072                    mCodec->mComponentName.c_str(),
3073                    mCodec->countBuffersOwnedByComponent(kPortIndexInput),
3074                    mCodec->mBuffers[kPortIndexInput].size(),
3075                    mCodec->countBuffersOwnedByComponent(kPortIndexOutput),
3076                    mCodec->mBuffers[kPortIndexOutput].size());
3077
3078            mActive = false;
3079
3080            CHECK_EQ(mCodec->mOMX->sendCommand(
3081                        mCodec->mNode, OMX_CommandFlush, OMX_ALL),
3082                     (status_t)OK);
3083
3084            mCodec->changeState(mCodec->mFlushingState);
3085
3086            handled = true;
3087            break;
3088        }
3089
3090        case kWhatResume:
3091        {
3092            resume();
3093
3094            handled = true;
3095            break;
3096        }
3097
3098        default:
3099            handled = BaseState::onMessageReceived(msg);
3100            break;
3101    }
3102
3103    return handled;
3104}
3105
3106bool ACodec::ExecutingState::onOMXEvent(
3107        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3108    switch (event) {
3109        case OMX_EventPortSettingsChanged:
3110        {
3111            CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
3112
3113            if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
3114                CHECK_EQ(mCodec->mOMX->sendCommand(
3115                            mCodec->mNode,
3116                            OMX_CommandPortDisable, kPortIndexOutput),
3117                         (status_t)OK);
3118
3119                mCodec->freeOutputBuffersNotOwnedByComponent();
3120
3121                mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
3122            } else if (data2 == OMX_IndexConfigCommonOutputCrop) {
3123                mCodec->mSentFormat = false;
3124            } else {
3125                ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx",
3126                     mCodec->mComponentName.c_str(), data2);
3127            }
3128
3129            return true;
3130        }
3131
3132        case OMX_EventBufferFlag:
3133        {
3134            return true;
3135        }
3136
3137        default:
3138            return BaseState::onOMXEvent(event, data1, data2);
3139    }
3140}
3141
3142////////////////////////////////////////////////////////////////////////////////
3143
3144ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState(
3145        ACodec *codec)
3146    : BaseState(codec) {
3147}
3148
3149ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode(
3150        OMX_U32 portIndex) {
3151    if (portIndex == kPortIndexOutput) {
3152        return FREE_BUFFERS;
3153    }
3154
3155    CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput);
3156
3157    return RESUBMIT_BUFFERS;
3158}
3159
3160bool ACodec::OutputPortSettingsChangedState::onMessageReceived(
3161        const sp<AMessage> &msg) {
3162    bool handled = false;
3163
3164    switch (msg->what()) {
3165        case kWhatFlush:
3166        case kWhatShutdown:
3167        case kWhatResume:
3168        {
3169            if (msg->what() == kWhatResume) {
3170                ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
3171            }
3172
3173            mCodec->deferMessage(msg);
3174            handled = true;
3175            break;
3176        }
3177
3178        default:
3179            handled = BaseState::onMessageReceived(msg);
3180            break;
3181    }
3182
3183    return handled;
3184}
3185
3186void ACodec::OutputPortSettingsChangedState::stateEntered() {
3187    ALOGV("[%s] Now handling output port settings change",
3188         mCodec->mComponentName.c_str());
3189}
3190
3191bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
3192        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3193    switch (event) {
3194        case OMX_EventCmdComplete:
3195        {
3196            if (data1 == (OMX_U32)OMX_CommandPortDisable) {
3197                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
3198
3199                ALOGV("[%s] Output port now disabled.",
3200                        mCodec->mComponentName.c_str());
3201
3202                CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty());
3203                mCodec->mDealer[kPortIndexOutput].clear();
3204
3205                CHECK_EQ(mCodec->mOMX->sendCommand(
3206                            mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput),
3207                         (status_t)OK);
3208
3209                status_t err;
3210                if ((err = mCodec->allocateBuffersOnPort(
3211                                kPortIndexOutput)) != OK) {
3212                    ALOGE("Failed to allocate output port buffers after "
3213                         "port reconfiguration (error 0x%08x)",
3214                         err);
3215
3216                    mCodec->signalError(OMX_ErrorUndefined, err);
3217
3218                    // This is technically not correct, since we were unable
3219                    // to allocate output buffers and therefore the output port
3220                    // remains disabled. It is necessary however to allow us
3221                    // to shutdown the codec properly.
3222                    mCodec->changeState(mCodec->mExecutingState);
3223                }
3224
3225                return true;
3226            } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
3227                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
3228
3229                mCodec->mSentFormat = false;
3230
3231                ALOGV("[%s] Output port now reenabled.",
3232                        mCodec->mComponentName.c_str());
3233
3234                if (mCodec->mExecutingState->active()) {
3235                    mCodec->mExecutingState->submitOutputBuffers();
3236                }
3237
3238                mCodec->changeState(mCodec->mExecutingState);
3239
3240                return true;
3241            }
3242
3243            return false;
3244        }
3245
3246        default:
3247            return false;
3248    }
3249}
3250
3251////////////////////////////////////////////////////////////////////////////////
3252
3253ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec)
3254    : BaseState(codec),
3255      mComponentNowIdle(false) {
3256}
3257
3258bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) {
3259    bool handled = false;
3260
3261    switch (msg->what()) {
3262        case kWhatFlush:
3263        {
3264            // Don't send me a flush request if you previously wanted me
3265            // to shutdown.
3266            TRESPASS();
3267            break;
3268        }
3269
3270        case kWhatShutdown:
3271        {
3272            // We're already doing that...
3273
3274            handled = true;
3275            break;
3276        }
3277
3278        default:
3279            handled = BaseState::onMessageReceived(msg);
3280            break;
3281    }
3282
3283    return handled;
3284}
3285
3286void ACodec::ExecutingToIdleState::stateEntered() {
3287    ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
3288
3289    mComponentNowIdle = false;
3290    mCodec->mSentFormat = false;
3291}
3292
3293bool ACodec::ExecutingToIdleState::onOMXEvent(
3294        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3295    switch (event) {
3296        case OMX_EventCmdComplete:
3297        {
3298            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
3299            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
3300
3301            mComponentNowIdle = true;
3302
3303            changeStateIfWeOwnAllBuffers();
3304
3305            return true;
3306        }
3307
3308        case OMX_EventPortSettingsChanged:
3309        case OMX_EventBufferFlag:
3310        {
3311            // We're shutting down and don't care about this anymore.
3312            return true;
3313        }
3314
3315        default:
3316            return BaseState::onOMXEvent(event, data1, data2);
3317    }
3318}
3319
3320void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
3321    if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) {
3322        CHECK_EQ(mCodec->mOMX->sendCommand(
3323                    mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded),
3324                 (status_t)OK);
3325
3326        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK);
3327        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK);
3328
3329        mCodec->changeState(mCodec->mIdleToLoadedState);
3330    }
3331}
3332
3333void ACodec::ExecutingToIdleState::onInputBufferFilled(
3334        const sp<AMessage> &msg) {
3335    BaseState::onInputBufferFilled(msg);
3336
3337    changeStateIfWeOwnAllBuffers();
3338}
3339
3340void ACodec::ExecutingToIdleState::onOutputBufferDrained(
3341        const sp<AMessage> &msg) {
3342    BaseState::onOutputBufferDrained(msg);
3343
3344    changeStateIfWeOwnAllBuffers();
3345}
3346
3347////////////////////////////////////////////////////////////////////////////////
3348
3349ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec)
3350    : BaseState(codec) {
3351}
3352
3353bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) {
3354    bool handled = false;
3355
3356    switch (msg->what()) {
3357        case kWhatShutdown:
3358        {
3359            // We're already doing that...
3360
3361            handled = true;
3362            break;
3363        }
3364
3365        case kWhatFlush:
3366        {
3367            // Don't send me a flush request if you previously wanted me
3368            // to shutdown.
3369            TRESPASS();
3370            break;
3371        }
3372
3373        default:
3374            handled = BaseState::onMessageReceived(msg);
3375            break;
3376    }
3377
3378    return handled;
3379}
3380
3381void ACodec::IdleToLoadedState::stateEntered() {
3382    ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
3383}
3384
3385bool ACodec::IdleToLoadedState::onOMXEvent(
3386        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3387    switch (event) {
3388        case OMX_EventCmdComplete:
3389        {
3390            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
3391            CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded);
3392
3393            mCodec->changeState(mCodec->mLoadedState);
3394
3395            return true;
3396        }
3397
3398        default:
3399            return BaseState::onOMXEvent(event, data1, data2);
3400    }
3401}
3402
3403////////////////////////////////////////////////////////////////////////////////
3404
3405ACodec::FlushingState::FlushingState(ACodec *codec)
3406    : BaseState(codec) {
3407}
3408
3409void ACodec::FlushingState::stateEntered() {
3410    ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());
3411
3412    mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
3413}
3414
3415bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) {
3416    bool handled = false;
3417
3418    switch (msg->what()) {
3419        case kWhatShutdown:
3420        {
3421            mCodec->deferMessage(msg);
3422            break;
3423        }
3424
3425        case kWhatFlush:
3426        {
3427            // We're already doing this right now.
3428            handled = true;
3429            break;
3430        }
3431
3432        default:
3433            handled = BaseState::onMessageReceived(msg);
3434            break;
3435    }
3436
3437    return handled;
3438}
3439
3440bool ACodec::FlushingState::onOMXEvent(
3441        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3442    ALOGV("[%s] FlushingState onOMXEvent(%d,%ld)",
3443            mCodec->mComponentName.c_str(), event, data1);
3444
3445    switch (event) {
3446        case OMX_EventCmdComplete:
3447        {
3448            CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush);
3449
3450            if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
3451                CHECK(!mFlushComplete[data2]);
3452                mFlushComplete[data2] = true;
3453
3454                if (mFlushComplete[kPortIndexInput]
3455                        && mFlushComplete[kPortIndexOutput]) {
3456                    changeStateIfWeOwnAllBuffers();
3457                }
3458            } else {
3459                CHECK_EQ(data2, OMX_ALL);
3460                CHECK(mFlushComplete[kPortIndexInput]);
3461                CHECK(mFlushComplete[kPortIndexOutput]);
3462
3463                changeStateIfWeOwnAllBuffers();
3464            }
3465
3466            return true;
3467        }
3468
3469        case OMX_EventPortSettingsChanged:
3470        {
3471            sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id());
3472            msg->setInt32("type", omx_message::EVENT);
3473            msg->setPointer("node", mCodec->mNode);
3474            msg->setInt32("event", event);
3475            msg->setInt32("data1", data1);
3476            msg->setInt32("data2", data2);
3477
3478            ALOGV("[%s] Deferring OMX_EventPortSettingsChanged",
3479                 mCodec->mComponentName.c_str());
3480
3481            mCodec->deferMessage(msg);
3482
3483            return true;
3484        }
3485
3486        default:
3487            return BaseState::onOMXEvent(event, data1, data2);
3488    }
3489
3490    return true;
3491}
3492
3493void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) {
3494    BaseState::onOutputBufferDrained(msg);
3495
3496    changeStateIfWeOwnAllBuffers();
3497}
3498
3499void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) {
3500    BaseState::onInputBufferFilled(msg);
3501
3502    changeStateIfWeOwnAllBuffers();
3503}
3504
3505void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() {
3506    if (mFlushComplete[kPortIndexInput]
3507            && mFlushComplete[kPortIndexOutput]
3508            && mCodec->allYourBuffersAreBelongToUs()) {
3509        sp<AMessage> notify = mCodec->mNotify->dup();
3510        notify->setInt32("what", ACodec::kWhatFlushCompleted);
3511        notify->post();
3512
3513        mCodec->mPortEOS[kPortIndexInput] =
3514            mCodec->mPortEOS[kPortIndexOutput] = false;
3515
3516        mCodec->mInputEOSResult = OK;
3517
3518        mCodec->changeState(mCodec->mExecutingState);
3519    }
3520}
3521
3522}  // namespace android
3523