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