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