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