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