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