ACodec.cpp revision 1e5b2b3361ddd07259bf4b29820ca4aa5f3a861b
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
1363    return mOMX->setParameter(
1364            mNode, OMX_IndexParamVideoPortFormat,
1365            &format, sizeof(format));
1366}
1367
1368static status_t GetVideoCodingTypeFromMime(
1369        const char *mime, OMX_VIDEO_CODINGTYPE *codingType) {
1370    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
1371        *codingType = OMX_VIDEO_CodingAVC;
1372    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
1373        *codingType = OMX_VIDEO_CodingMPEG4;
1374    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
1375        *codingType = OMX_VIDEO_CodingH263;
1376    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG2, mime)) {
1377        *codingType = OMX_VIDEO_CodingMPEG2;
1378    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_VPX, mime)) {
1379        *codingType = OMX_VIDEO_CodingVPX;
1380    } else {
1381        *codingType = OMX_VIDEO_CodingUnused;
1382        return ERROR_UNSUPPORTED;
1383    }
1384
1385    return OK;
1386}
1387
1388status_t ACodec::setupVideoDecoder(
1389        const char *mime, int32_t width, int32_t height) {
1390    OMX_VIDEO_CODINGTYPE compressionFormat;
1391    status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
1392
1393    if (err != OK) {
1394        return err;
1395    }
1396
1397    err = setVideoPortFormatType(
1398            kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
1399
1400    if (err != OK) {
1401        return err;
1402    }
1403
1404    err = setSupportedOutputFormat();
1405
1406    if (err != OK) {
1407        return err;
1408    }
1409
1410    err = setVideoFormatOnPort(
1411            kPortIndexInput, width, height, compressionFormat);
1412
1413    if (err != OK) {
1414        return err;
1415    }
1416
1417    err = setVideoFormatOnPort(
1418            kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused);
1419
1420    if (err != OK) {
1421        return err;
1422    }
1423
1424    return OK;
1425}
1426
1427status_t ACodec::setupVideoEncoder(const char *mime, const sp<AMessage> &msg) {
1428    int32_t tmp;
1429    if (!msg->findInt32("color-format", &tmp)) {
1430        return INVALID_OPERATION;
1431    }
1432
1433    OMX_COLOR_FORMATTYPE colorFormat =
1434        static_cast<OMX_COLOR_FORMATTYPE>(tmp);
1435
1436    status_t err = setVideoPortFormatType(
1437            kPortIndexInput, OMX_VIDEO_CodingUnused, colorFormat);
1438
1439    if (err != OK) {
1440        ALOGE("[%s] does not support color format %d",
1441              mComponentName.c_str(), colorFormat);
1442
1443        return err;
1444    }
1445
1446    /* Input port configuration */
1447
1448    OMX_PARAM_PORTDEFINITIONTYPE def;
1449    InitOMXParams(&def);
1450
1451    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
1452
1453    def.nPortIndex = kPortIndexInput;
1454
1455    err = mOMX->getParameter(
1456            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1457
1458    if (err != OK) {
1459        return err;
1460    }
1461
1462    int32_t width, height, bitrate;
1463    if (!msg->findInt32("width", &width)
1464            || !msg->findInt32("height", &height)
1465            || !msg->findInt32("bitrate", &bitrate)) {
1466        return INVALID_OPERATION;
1467    }
1468
1469    video_def->nFrameWidth = width;
1470    video_def->nFrameHeight = height;
1471
1472    int32_t stride;
1473    if (!msg->findInt32("stride", &stride)) {
1474        stride = width;
1475    }
1476
1477    video_def->nStride = stride;
1478
1479    int32_t sliceHeight;
1480    if (!msg->findInt32("slice-height", &sliceHeight)) {
1481        sliceHeight = height;
1482    }
1483
1484    video_def->nSliceHeight = sliceHeight;
1485
1486    def.nBufferSize = (video_def->nStride * video_def->nSliceHeight * 3) / 2;
1487
1488    float frameRate;
1489    if (!msg->findFloat("frame-rate", &frameRate)) {
1490        int32_t tmp;
1491        if (!msg->findInt32("frame-rate", &tmp)) {
1492            return INVALID_OPERATION;
1493        }
1494        frameRate = (float)tmp;
1495    }
1496
1497    video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f);
1498    video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
1499    video_def->eColorFormat = colorFormat;
1500
1501    err = mOMX->setParameter(
1502            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1503
1504    if (err != OK) {
1505        ALOGE("[%s] failed to set input port definition parameters.",
1506              mComponentName.c_str());
1507
1508        return err;
1509    }
1510
1511    /* Output port configuration */
1512
1513    OMX_VIDEO_CODINGTYPE compressionFormat;
1514    err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
1515
1516    if (err != OK) {
1517        return err;
1518    }
1519
1520    err = setVideoPortFormatType(
1521            kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused);
1522
1523    if (err != OK) {
1524        ALOGE("[%s] does not support compression format %d",
1525             mComponentName.c_str(), compressionFormat);
1526
1527        return err;
1528    }
1529
1530    def.nPortIndex = kPortIndexOutput;
1531
1532    err = mOMX->getParameter(
1533            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1534
1535    if (err != OK) {
1536        return err;
1537    }
1538
1539    video_def->nFrameWidth = width;
1540    video_def->nFrameHeight = height;
1541    video_def->xFramerate = 0;
1542    video_def->nBitrate = bitrate;
1543    video_def->eCompressionFormat = compressionFormat;
1544    video_def->eColorFormat = OMX_COLOR_FormatUnused;
1545
1546    err = mOMX->setParameter(
1547            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1548
1549    if (err != OK) {
1550        ALOGE("[%s] failed to set output port definition parameters.",
1551              mComponentName.c_str());
1552
1553        return err;
1554    }
1555
1556    switch (compressionFormat) {
1557        case OMX_VIDEO_CodingMPEG4:
1558            err = setupMPEG4EncoderParameters(msg);
1559            break;
1560
1561        case OMX_VIDEO_CodingH263:
1562            err = setupH263EncoderParameters(msg);
1563            break;
1564
1565        case OMX_VIDEO_CodingAVC:
1566            err = setupAVCEncoderParameters(msg);
1567            break;
1568
1569        default:
1570            break;
1571    }
1572
1573    ALOGI("setupVideoEncoder succeeded");
1574
1575    return err;
1576}
1577
1578static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) {
1579    if (iFramesInterval < 0) {
1580        return 0xFFFFFFFF;
1581    } else if (iFramesInterval == 0) {
1582        return 0;
1583    }
1584    OMX_U32 ret = frameRate * iFramesInterval;
1585    CHECK(ret > 1);
1586    return ret;
1587}
1588
1589status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) {
1590    int32_t bitrate, iFrameInterval;
1591    if (!msg->findInt32("bitrate", &bitrate)
1592            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
1593        return INVALID_OPERATION;
1594    }
1595
1596    float frameRate;
1597    if (!msg->findFloat("frame-rate", &frameRate)) {
1598        int32_t tmp;
1599        if (!msg->findInt32("frame-rate", &tmp)) {
1600            return INVALID_OPERATION;
1601        }
1602        frameRate = (float)tmp;
1603    }
1604
1605    OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type;
1606    InitOMXParams(&mpeg4type);
1607    mpeg4type.nPortIndex = kPortIndexOutput;
1608
1609    status_t err = mOMX->getParameter(
1610            mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
1611
1612    if (err != OK) {
1613        return err;
1614    }
1615
1616    mpeg4type.nSliceHeaderSpacing = 0;
1617    mpeg4type.bSVH = OMX_FALSE;
1618    mpeg4type.bGov = OMX_FALSE;
1619
1620    mpeg4type.nAllowedPictureTypes =
1621        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
1622
1623    mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
1624    if (mpeg4type.nPFrames == 0) {
1625        mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
1626    }
1627    mpeg4type.nBFrames = 0;
1628    mpeg4type.nIDCVLCThreshold = 0;
1629    mpeg4type.bACPred = OMX_TRUE;
1630    mpeg4type.nMaxPacketSize = 256;
1631    mpeg4type.nTimeIncRes = 1000;
1632    mpeg4type.nHeaderExtension = 0;
1633    mpeg4type.bReversibleVLC = OMX_FALSE;
1634
1635    int32_t profile;
1636    if (msg->findInt32("profile", &profile)) {
1637        int32_t level;
1638        if (!msg->findInt32("level", &level)) {
1639            return INVALID_OPERATION;
1640        }
1641
1642        err = verifySupportForProfileAndLevel(profile, level);
1643
1644        if (err != OK) {
1645            return err;
1646        }
1647
1648        mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile);
1649        mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level);
1650    }
1651
1652    err = mOMX->setParameter(
1653            mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
1654
1655    if (err != OK) {
1656        return err;
1657    }
1658
1659    err = configureBitrate(bitrate);
1660
1661    if (err != OK) {
1662        return err;
1663    }
1664
1665    return setupErrorCorrectionParameters();
1666}
1667
1668status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) {
1669    int32_t bitrate, iFrameInterval;
1670    if (!msg->findInt32("bitrate", &bitrate)
1671            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
1672        return INVALID_OPERATION;
1673    }
1674
1675    float frameRate;
1676    if (!msg->findFloat("frame-rate", &frameRate)) {
1677        int32_t tmp;
1678        if (!msg->findInt32("frame-rate", &tmp)) {
1679            return INVALID_OPERATION;
1680        }
1681        frameRate = (float)tmp;
1682    }
1683
1684    OMX_VIDEO_PARAM_H263TYPE h263type;
1685    InitOMXParams(&h263type);
1686    h263type.nPortIndex = kPortIndexOutput;
1687
1688    status_t err = mOMX->getParameter(
1689            mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
1690
1691    if (err != OK) {
1692        return err;
1693    }
1694
1695    h263type.nAllowedPictureTypes =
1696        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
1697
1698    h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
1699    if (h263type.nPFrames == 0) {
1700        h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
1701    }
1702    h263type.nBFrames = 0;
1703
1704    int32_t profile;
1705    if (msg->findInt32("profile", &profile)) {
1706        int32_t level;
1707        if (!msg->findInt32("level", &level)) {
1708            return INVALID_OPERATION;
1709        }
1710
1711        err = verifySupportForProfileAndLevel(profile, level);
1712
1713        if (err != OK) {
1714            return err;
1715        }
1716
1717        h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile);
1718        h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level);
1719    }
1720
1721    h263type.bPLUSPTYPEAllowed = OMX_FALSE;
1722    h263type.bForceRoundingTypeToZero = OMX_FALSE;
1723    h263type.nPictureHeaderRepetition = 0;
1724    h263type.nGOBHeaderInterval = 0;
1725
1726    err = mOMX->setParameter(
1727            mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
1728
1729    if (err != OK) {
1730        return err;
1731    }
1732
1733    err = configureBitrate(bitrate);
1734
1735    if (err != OK) {
1736        return err;
1737    }
1738
1739    return setupErrorCorrectionParameters();
1740}
1741
1742status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) {
1743    int32_t bitrate, iFrameInterval;
1744    if (!msg->findInt32("bitrate", &bitrate)
1745            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
1746        return INVALID_OPERATION;
1747    }
1748
1749    float frameRate;
1750    if (!msg->findFloat("frame-rate", &frameRate)) {
1751        int32_t tmp;
1752        if (!msg->findInt32("frame-rate", &tmp)) {
1753            return INVALID_OPERATION;
1754        }
1755        frameRate = (float)tmp;
1756    }
1757
1758    OMX_VIDEO_PARAM_AVCTYPE h264type;
1759    InitOMXParams(&h264type);
1760    h264type.nPortIndex = kPortIndexOutput;
1761
1762    status_t err = mOMX->getParameter(
1763            mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
1764
1765    if (err != OK) {
1766        return err;
1767    }
1768
1769    h264type.nAllowedPictureTypes =
1770        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
1771
1772    int32_t profile;
1773    if (msg->findInt32("profile", &profile)) {
1774        int32_t level;
1775        if (!msg->findInt32("level", &level)) {
1776            return INVALID_OPERATION;
1777        }
1778
1779        err = verifySupportForProfileAndLevel(profile, level);
1780
1781        if (err != OK) {
1782            return err;
1783        }
1784
1785        h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile);
1786        h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level);
1787    }
1788
1789    // XXX
1790    if (h264type.eProfile != OMX_VIDEO_AVCProfileBaseline) {
1791        ALOGW("Use baseline profile instead of %d for AVC recording",
1792            h264type.eProfile);
1793        h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
1794    }
1795
1796    if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
1797        h264type.nSliceHeaderSpacing = 0;
1798        h264type.bUseHadamard = OMX_TRUE;
1799        h264type.nRefFrames = 1;
1800        h264type.nBFrames = 0;
1801        h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
1802        if (h264type.nPFrames == 0) {
1803            h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
1804        }
1805        h264type.nRefIdx10ActiveMinus1 = 0;
1806        h264type.nRefIdx11ActiveMinus1 = 0;
1807        h264type.bEntropyCodingCABAC = OMX_FALSE;
1808        h264type.bWeightedPPrediction = OMX_FALSE;
1809        h264type.bconstIpred = OMX_FALSE;
1810        h264type.bDirect8x8Inference = OMX_FALSE;
1811        h264type.bDirectSpatialTemporal = OMX_FALSE;
1812        h264type.nCabacInitIdc = 0;
1813    }
1814
1815    if (h264type.nBFrames != 0) {
1816        h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
1817    }
1818
1819    h264type.bEnableUEP = OMX_FALSE;
1820    h264type.bEnableFMO = OMX_FALSE;
1821    h264type.bEnableASO = OMX_FALSE;
1822    h264type.bEnableRS = OMX_FALSE;
1823    h264type.bFrameMBsOnly = OMX_TRUE;
1824    h264type.bMBAFF = OMX_FALSE;
1825    h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
1826
1827    err = mOMX->setParameter(
1828            mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
1829
1830    if (err != OK) {
1831        return err;
1832    }
1833
1834    return configureBitrate(bitrate);
1835}
1836
1837status_t ACodec::verifySupportForProfileAndLevel(
1838        int32_t profile, int32_t level) {
1839    OMX_VIDEO_PARAM_PROFILELEVELTYPE params;
1840    InitOMXParams(&params);
1841    params.nPortIndex = kPortIndexOutput;
1842
1843    for (params.nProfileIndex = 0;; ++params.nProfileIndex) {
1844        status_t err = mOMX->getParameter(
1845                mNode,
1846                OMX_IndexParamVideoProfileLevelQuerySupported,
1847                &params,
1848                sizeof(params));
1849
1850        if (err != OK) {
1851            return err;
1852        }
1853
1854        int32_t supportedProfile = static_cast<int32_t>(params.eProfile);
1855        int32_t supportedLevel = static_cast<int32_t>(params.eLevel);
1856
1857        if (profile == supportedProfile && level <= supportedLevel) {
1858            return OK;
1859        }
1860    }
1861}
1862
1863status_t ACodec::configureBitrate(int32_t bitrate) {
1864    OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
1865    InitOMXParams(&bitrateType);
1866    bitrateType.nPortIndex = kPortIndexOutput;
1867
1868    status_t err = mOMX->getParameter(
1869            mNode, OMX_IndexParamVideoBitrate,
1870            &bitrateType, sizeof(bitrateType));
1871
1872    if (err != OK) {
1873        return err;
1874    }
1875
1876    bitrateType.eControlRate = OMX_Video_ControlRateVariable;
1877    bitrateType.nTargetBitrate = bitrate;
1878
1879    return mOMX->setParameter(
1880            mNode, OMX_IndexParamVideoBitrate,
1881            &bitrateType, sizeof(bitrateType));
1882}
1883
1884status_t ACodec::setupErrorCorrectionParameters() {
1885    OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
1886    InitOMXParams(&errorCorrectionType);
1887    errorCorrectionType.nPortIndex = kPortIndexOutput;
1888
1889    status_t err = mOMX->getParameter(
1890            mNode, OMX_IndexParamVideoErrorCorrection,
1891            &errorCorrectionType, sizeof(errorCorrectionType));
1892
1893    if (err != OK) {
1894        return OK;  // Optional feature. Ignore this failure
1895    }
1896
1897    errorCorrectionType.bEnableHEC = OMX_FALSE;
1898    errorCorrectionType.bEnableResync = OMX_TRUE;
1899    errorCorrectionType.nResynchMarkerSpacing = 256;
1900    errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
1901    errorCorrectionType.bEnableRVLC = OMX_FALSE;
1902
1903    return mOMX->setParameter(
1904            mNode, OMX_IndexParamVideoErrorCorrection,
1905            &errorCorrectionType, sizeof(errorCorrectionType));
1906}
1907
1908status_t ACodec::setVideoFormatOnPort(
1909        OMX_U32 portIndex,
1910        int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat) {
1911    OMX_PARAM_PORTDEFINITIONTYPE def;
1912    InitOMXParams(&def);
1913    def.nPortIndex = portIndex;
1914
1915    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
1916
1917    status_t err = mOMX->getParameter(
1918            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1919
1920    CHECK_EQ(err, (status_t)OK);
1921
1922    if (portIndex == kPortIndexInput) {
1923        // XXX Need a (much) better heuristic to compute input buffer sizes.
1924        const size_t X = 64 * 1024;
1925        if (def.nBufferSize < X) {
1926            def.nBufferSize = X;
1927        }
1928    }
1929
1930    CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
1931
1932    video_def->nFrameWidth = width;
1933    video_def->nFrameHeight = height;
1934
1935    if (portIndex == kPortIndexInput) {
1936        video_def->eCompressionFormat = compressionFormat;
1937        video_def->eColorFormat = OMX_COLOR_FormatUnused;
1938    }
1939
1940    err = mOMX->setParameter(
1941            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1942
1943    return err;
1944}
1945
1946status_t ACodec::initNativeWindow() {
1947    if (mNativeWindow != NULL) {
1948        return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE);
1949    }
1950
1951    mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE);
1952    return OK;
1953}
1954
1955size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const {
1956    size_t n = 0;
1957
1958    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
1959        const BufferInfo &info = mBuffers[portIndex].itemAt(i);
1960
1961        if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) {
1962            ++n;
1963        }
1964    }
1965
1966    return n;
1967}
1968
1969bool ACodec::allYourBuffersAreBelongToUs(
1970        OMX_U32 portIndex) {
1971    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
1972        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
1973
1974        if (info->mStatus != BufferInfo::OWNED_BY_US
1975                && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
1976            ALOGV("[%s] Buffer %p on port %ld still has status %d",
1977                    mComponentName.c_str(),
1978                    info->mBufferID, portIndex, info->mStatus);
1979            return false;
1980        }
1981    }
1982
1983    return true;
1984}
1985
1986bool ACodec::allYourBuffersAreBelongToUs() {
1987    return allYourBuffersAreBelongToUs(kPortIndexInput)
1988        && allYourBuffersAreBelongToUs(kPortIndexOutput);
1989}
1990
1991void ACodec::deferMessage(const sp<AMessage> &msg) {
1992    bool wasEmptyBefore = mDeferredQueue.empty();
1993    mDeferredQueue.push_back(msg);
1994}
1995
1996void ACodec::processDeferredMessages() {
1997    List<sp<AMessage> > queue = mDeferredQueue;
1998    mDeferredQueue.clear();
1999
2000    List<sp<AMessage> >::iterator it = queue.begin();
2001    while (it != queue.end()) {
2002        onMessageReceived(*it++);
2003    }
2004}
2005
2006void ACodec::sendFormatChange() {
2007    sp<AMessage> notify = mNotify->dup();
2008    notify->setInt32("what", kWhatOutputFormatChanged);
2009
2010    OMX_PARAM_PORTDEFINITIONTYPE def;
2011    InitOMXParams(&def);
2012    def.nPortIndex = kPortIndexOutput;
2013
2014    CHECK_EQ(mOMX->getParameter(
2015                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)),
2016             (status_t)OK);
2017
2018    CHECK_EQ((int)def.eDir, (int)OMX_DirOutput);
2019
2020    switch (def.eDomain) {
2021        case OMX_PortDomainVideo:
2022        {
2023            OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
2024
2025            notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW);
2026            notify->setInt32("width", videoDef->nFrameWidth);
2027            notify->setInt32("height", videoDef->nFrameHeight);
2028            notify->setInt32("stride", videoDef->nStride);
2029            notify->setInt32("slice-height", videoDef->nSliceHeight);
2030            notify->setInt32("color-format", videoDef->eColorFormat);
2031
2032            OMX_CONFIG_RECTTYPE rect;
2033            InitOMXParams(&rect);
2034            rect.nPortIndex = kPortIndexOutput;
2035
2036            if (mOMX->getConfig(
2037                        mNode, OMX_IndexConfigCommonOutputCrop,
2038                        &rect, sizeof(rect)) != OK) {
2039                rect.nLeft = 0;
2040                rect.nTop = 0;
2041                rect.nWidth = videoDef->nFrameWidth;
2042                rect.nHeight = videoDef->nFrameHeight;
2043            }
2044
2045            CHECK_GE(rect.nLeft, 0);
2046            CHECK_GE(rect.nTop, 0);
2047            CHECK_GE(rect.nWidth, 0u);
2048            CHECK_GE(rect.nHeight, 0u);
2049            CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth);
2050            CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight);
2051
2052            notify->setRect(
2053                    "crop",
2054                    rect.nLeft,
2055                    rect.nTop,
2056                    rect.nLeft + rect.nWidth - 1,
2057                    rect.nTop + rect.nHeight - 1);
2058
2059            if (mNativeWindow != NULL) {
2060                android_native_rect_t crop;
2061                crop.left = rect.nLeft;
2062                crop.top = rect.nTop;
2063                crop.right = rect.nLeft + rect.nWidth;
2064                crop.bottom = rect.nTop + rect.nHeight;
2065
2066                CHECK_EQ(0, native_window_set_crop(
2067                            mNativeWindow.get(), &crop));
2068            }
2069            break;
2070        }
2071
2072        case OMX_PortDomainAudio:
2073        {
2074            OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
2075            CHECK_EQ((int)audioDef->eEncoding, (int)OMX_AUDIO_CodingPCM);
2076
2077            OMX_AUDIO_PARAM_PCMMODETYPE params;
2078            InitOMXParams(&params);
2079            params.nPortIndex = kPortIndexOutput;
2080
2081            CHECK_EQ(mOMX->getParameter(
2082                        mNode, OMX_IndexParamAudioPcm,
2083                        &params, sizeof(params)),
2084                     (status_t)OK);
2085
2086            CHECK(params.nChannels == 1 || params.bInterleaved);
2087            CHECK_EQ(params.nBitPerSample, 16u);
2088            CHECK_EQ((int)params.eNumData, (int)OMX_NumericalDataSigned);
2089            CHECK_EQ((int)params.ePCMMode, (int)OMX_AUDIO_PCMModeLinear);
2090
2091            notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
2092            notify->setInt32("channel-count", params.nChannels);
2093            notify->setInt32("sample-rate", params.nSamplingRate);
2094            if (mEncoderDelay + mEncoderPadding) {
2095                size_t frameSize = params.nChannels * sizeof(int16_t);
2096                if (mSkipCutBuffer != NULL) {
2097                    size_t prevbufsize = mSkipCutBuffer->size();
2098                    if (prevbufsize != 0) {
2099                        ALOGW("Replacing SkipCutBuffer holding %d bytes", prevbufsize);
2100                    }
2101                }
2102                mSkipCutBuffer = new SkipCutBuffer(mEncoderDelay * frameSize,
2103                                                   mEncoderPadding * frameSize);
2104            }
2105
2106            if (mChannelMaskPresent) {
2107                notify->setInt32("channel-mask", mChannelMask);
2108            }
2109
2110            break;
2111        }
2112
2113        default:
2114            TRESPASS();
2115    }
2116
2117    notify->post();
2118
2119    mSentFormat = true;
2120}
2121
2122void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) {
2123    sp<AMessage> notify = mNotify->dup();
2124    notify->setInt32("what", ACodec::kWhatError);
2125    notify->setInt32("omx-error", error);
2126    notify->setInt32("err", internalError);
2127    notify->post();
2128}
2129
2130status_t ACodec::pushBlankBuffersToNativeWindow() {
2131    status_t err = NO_ERROR;
2132    ANativeWindowBuffer* anb = NULL;
2133    int numBufs = 0;
2134    int minUndequeuedBufs = 0;
2135
2136    // We need to reconnect to the ANativeWindow as a CPU client to ensure that
2137    // no frames get dropped by SurfaceFlinger assuming that these are video
2138    // frames.
2139    err = native_window_api_disconnect(mNativeWindow.get(),
2140            NATIVE_WINDOW_API_MEDIA);
2141    if (err != NO_ERROR) {
2142        ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
2143                strerror(-err), -err);
2144        return err;
2145    }
2146
2147    err = native_window_api_connect(mNativeWindow.get(),
2148            NATIVE_WINDOW_API_CPU);
2149    if (err != NO_ERROR) {
2150        ALOGE("error pushing blank frames: api_connect failed: %s (%d)",
2151                strerror(-err), -err);
2152        return err;
2153    }
2154
2155    err = native_window_set_buffers_geometry(mNativeWindow.get(), 1, 1,
2156            HAL_PIXEL_FORMAT_RGBX_8888);
2157    if (err != NO_ERROR) {
2158        ALOGE("error pushing blank frames: set_buffers_geometry failed: %s (%d)",
2159                strerror(-err), -err);
2160        goto error;
2161    }
2162
2163    err = native_window_set_usage(mNativeWindow.get(),
2164            GRALLOC_USAGE_SW_WRITE_OFTEN);
2165    if (err != NO_ERROR) {
2166        ALOGE("error pushing blank frames: set_usage failed: %s (%d)",
2167                strerror(-err), -err);
2168        goto error;
2169    }
2170
2171    err = mNativeWindow->query(mNativeWindow.get(),
2172            NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs);
2173    if (err != NO_ERROR) {
2174        ALOGE("error pushing blank frames: MIN_UNDEQUEUED_BUFFERS query "
2175                "failed: %s (%d)", strerror(-err), -err);
2176        goto error;
2177    }
2178
2179    numBufs = minUndequeuedBufs + 1;
2180    err = native_window_set_buffer_count(mNativeWindow.get(), numBufs);
2181    if (err != NO_ERROR) {
2182        ALOGE("error pushing blank frames: set_buffer_count failed: %s (%d)",
2183                strerror(-err), -err);
2184        goto error;
2185    }
2186
2187    // We  push numBufs + 1 buffers to ensure that we've drawn into the same
2188    // buffer twice.  This should guarantee that the buffer has been displayed
2189    // on the screen and then been replaced, so an previous video frames are
2190    // guaranteed NOT to be currently displayed.
2191    for (int i = 0; i < numBufs + 1; i++) {
2192        int fenceFd = -1;
2193        err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &anb);
2194        if (err != NO_ERROR) {
2195            ALOGE("error pushing blank frames: dequeueBuffer failed: %s (%d)",
2196                    strerror(-err), -err);
2197            goto error;
2198        }
2199
2200        sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
2201
2202        // Fill the buffer with the a 1x1 checkerboard pattern ;)
2203        uint32_t* img = NULL;
2204        err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
2205        if (err != NO_ERROR) {
2206            ALOGE("error pushing blank frames: lock failed: %s (%d)",
2207                    strerror(-err), -err);
2208            goto error;
2209        }
2210
2211        *img = 0;
2212
2213        err = buf->unlock();
2214        if (err != NO_ERROR) {
2215            ALOGE("error pushing blank frames: unlock failed: %s (%d)",
2216                    strerror(-err), -err);
2217            goto error;
2218        }
2219
2220        err = mNativeWindow->queueBuffer(mNativeWindow.get(),
2221                buf->getNativeBuffer(), -1);
2222        if (err != NO_ERROR) {
2223            ALOGE("error pushing blank frames: queueBuffer failed: %s (%d)",
2224                    strerror(-err), -err);
2225            goto error;
2226        }
2227
2228        anb = NULL;
2229    }
2230
2231error:
2232
2233    if (err != NO_ERROR) {
2234        // Clean up after an error.
2235        if (anb != NULL) {
2236            mNativeWindow->cancelBuffer(mNativeWindow.get(), anb, -1);
2237        }
2238
2239        native_window_api_disconnect(mNativeWindow.get(),
2240                NATIVE_WINDOW_API_CPU);
2241        native_window_api_connect(mNativeWindow.get(),
2242                NATIVE_WINDOW_API_MEDIA);
2243
2244        return err;
2245    } else {
2246        // Clean up after success.
2247        err = native_window_api_disconnect(mNativeWindow.get(),
2248                NATIVE_WINDOW_API_CPU);
2249        if (err != NO_ERROR) {
2250            ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
2251                    strerror(-err), -err);
2252            return err;
2253        }
2254
2255        err = native_window_api_connect(mNativeWindow.get(),
2256                NATIVE_WINDOW_API_MEDIA);
2257        if (err != NO_ERROR) {
2258            ALOGE("error pushing blank frames: api_connect failed: %s (%d)",
2259                    strerror(-err), -err);
2260            return err;
2261        }
2262
2263        return NO_ERROR;
2264    }
2265}
2266
2267////////////////////////////////////////////////////////////////////////////////
2268
2269ACodec::PortDescription::PortDescription() {
2270}
2271
2272void ACodec::PortDescription::addBuffer(
2273        IOMX::buffer_id id, const sp<ABuffer> &buffer) {
2274    mBufferIDs.push_back(id);
2275    mBuffers.push_back(buffer);
2276}
2277
2278size_t ACodec::PortDescription::countBuffers() {
2279    return mBufferIDs.size();
2280}
2281
2282IOMX::buffer_id ACodec::PortDescription::bufferIDAt(size_t index) const {
2283    return mBufferIDs.itemAt(index);
2284}
2285
2286sp<ABuffer> ACodec::PortDescription::bufferAt(size_t index) const {
2287    return mBuffers.itemAt(index);
2288}
2289
2290////////////////////////////////////////////////////////////////////////////////
2291
2292ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
2293    : AState(parentState),
2294      mCodec(codec) {
2295}
2296
2297ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(OMX_U32 portIndex) {
2298    return KEEP_BUFFERS;
2299}
2300
2301bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) {
2302    switch (msg->what()) {
2303        case kWhatInputBufferFilled:
2304        {
2305            onInputBufferFilled(msg);
2306            break;
2307        }
2308
2309        case kWhatOutputBufferDrained:
2310        {
2311            onOutputBufferDrained(msg);
2312            break;
2313        }
2314
2315        case ACodec::kWhatOMXMessage:
2316        {
2317            return onOMXMessage(msg);
2318        }
2319
2320        default:
2321            return false;
2322    }
2323
2324    return true;
2325}
2326
2327bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) {
2328    int32_t type;
2329    CHECK(msg->findInt32("type", &type));
2330
2331    IOMX::node_id nodeID;
2332    CHECK(msg->findPointer("node", &nodeID));
2333    CHECK_EQ(nodeID, mCodec->mNode);
2334
2335    switch (type) {
2336        case omx_message::EVENT:
2337        {
2338            int32_t event, data1, data2;
2339            CHECK(msg->findInt32("event", &event));
2340            CHECK(msg->findInt32("data1", &data1));
2341            CHECK(msg->findInt32("data2", &data2));
2342
2343            if (event == OMX_EventCmdComplete
2344                    && data1 == OMX_CommandFlush
2345                    && data2 == (int32_t)OMX_ALL) {
2346                // Use of this notification is not consistent across
2347                // implementations. We'll drop this notification and rely
2348                // on flush-complete notifications on the individual port
2349                // indices instead.
2350
2351                return true;
2352            }
2353
2354            return onOMXEvent(
2355                    static_cast<OMX_EVENTTYPE>(event),
2356                    static_cast<OMX_U32>(data1),
2357                    static_cast<OMX_U32>(data2));
2358        }
2359
2360        case omx_message::EMPTY_BUFFER_DONE:
2361        {
2362            IOMX::buffer_id bufferID;
2363            CHECK(msg->findPointer("buffer", &bufferID));
2364
2365            return onOMXEmptyBufferDone(bufferID);
2366        }
2367
2368        case omx_message::FILL_BUFFER_DONE:
2369        {
2370            IOMX::buffer_id bufferID;
2371            CHECK(msg->findPointer("buffer", &bufferID));
2372
2373            int32_t rangeOffset, rangeLength, flags;
2374            int64_t timeUs;
2375            void *platformPrivate;
2376            void *dataPtr;
2377
2378            CHECK(msg->findInt32("range_offset", &rangeOffset));
2379            CHECK(msg->findInt32("range_length", &rangeLength));
2380            CHECK(msg->findInt32("flags", &flags));
2381            CHECK(msg->findInt64("timestamp", &timeUs));
2382            CHECK(msg->findPointer("platform_private", &platformPrivate));
2383            CHECK(msg->findPointer("data_ptr", &dataPtr));
2384
2385            return onOMXFillBufferDone(
2386                    bufferID,
2387                    (size_t)rangeOffset, (size_t)rangeLength,
2388                    (OMX_U32)flags,
2389                    timeUs,
2390                    platformPrivate,
2391                    dataPtr);
2392        }
2393
2394        default:
2395            TRESPASS();
2396            break;
2397    }
2398}
2399
2400bool ACodec::BaseState::onOMXEvent(
2401        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2402    if (event != OMX_EventError) {
2403        ALOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)",
2404             mCodec->mComponentName.c_str(), event, data1, data2);
2405
2406        return false;
2407    }
2408
2409    ALOGE("[%s] ERROR(0x%08lx)", mCodec->mComponentName.c_str(), data1);
2410
2411    mCodec->signalError((OMX_ERRORTYPE)data1);
2412
2413    return true;
2414}
2415
2416bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) {
2417    ALOGV("[%s] onOMXEmptyBufferDone %p",
2418         mCodec->mComponentName.c_str(), bufferID);
2419
2420    BufferInfo *info =
2421        mCodec->findBufferByID(kPortIndexInput, bufferID);
2422
2423    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
2424    info->mStatus = BufferInfo::OWNED_BY_US;
2425
2426    PortMode mode = getPortMode(kPortIndexInput);
2427
2428    switch (mode) {
2429        case KEEP_BUFFERS:
2430            break;
2431
2432        case RESUBMIT_BUFFERS:
2433            postFillThisBuffer(info);
2434            break;
2435
2436        default:
2437        {
2438            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
2439            TRESPASS();  // Not currently used
2440            break;
2441        }
2442    }
2443
2444    return true;
2445}
2446
2447void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) {
2448    if (mCodec->mPortEOS[kPortIndexInput]) {
2449        return;
2450    }
2451
2452    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
2453
2454    sp<AMessage> notify = mCodec->mNotify->dup();
2455    notify->setInt32("what", ACodec::kWhatFillThisBuffer);
2456    notify->setPointer("buffer-id", info->mBufferID);
2457
2458    info->mData->meta()->clear();
2459    notify->setBuffer("buffer", info->mData);
2460
2461    sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id());
2462    reply->setPointer("buffer-id", info->mBufferID);
2463
2464    notify->setMessage("reply", reply);
2465
2466    notify->post();
2467
2468    info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
2469}
2470
2471void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
2472    IOMX::buffer_id bufferID;
2473    CHECK(msg->findPointer("buffer-id", &bufferID));
2474
2475    sp<ABuffer> buffer;
2476    int32_t err = OK;
2477    bool eos = false;
2478
2479    if (!msg->findBuffer("buffer", &buffer)) {
2480        CHECK(msg->findInt32("err", &err));
2481
2482        ALOGV("[%s] saw error %d instead of an input buffer",
2483             mCodec->mComponentName.c_str(), err);
2484
2485        buffer.clear();
2486
2487        eos = true;
2488    }
2489
2490    int32_t tmp;
2491    if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) {
2492        eos = true;
2493        err = ERROR_END_OF_STREAM;
2494    }
2495
2496    BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
2497    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM);
2498
2499    info->mStatus = BufferInfo::OWNED_BY_US;
2500
2501    PortMode mode = getPortMode(kPortIndexInput);
2502
2503    switch (mode) {
2504        case KEEP_BUFFERS:
2505        {
2506            if (eos) {
2507                if (!mCodec->mPortEOS[kPortIndexInput]) {
2508                    mCodec->mPortEOS[kPortIndexInput] = true;
2509                    mCodec->mInputEOSResult = err;
2510                }
2511            }
2512            break;
2513        }
2514
2515        case RESUBMIT_BUFFERS:
2516        {
2517            if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) {
2518                int64_t timeUs;
2519                CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
2520
2521                OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
2522
2523                int32_t isCSD;
2524                if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) {
2525                    flags |= OMX_BUFFERFLAG_CODECCONFIG;
2526                }
2527
2528                if (eos) {
2529                    flags |= OMX_BUFFERFLAG_EOS;
2530                }
2531
2532                if (buffer != info->mData) {
2533                    if (0 && !(flags & OMX_BUFFERFLAG_CODECCONFIG)) {
2534                        ALOGV("[%s] Needs to copy input data.",
2535                             mCodec->mComponentName.c_str());
2536                    }
2537
2538                    CHECK_LE(buffer->size(), info->mData->capacity());
2539                    memcpy(info->mData->data(), buffer->data(), buffer->size());
2540                }
2541
2542                if (flags & OMX_BUFFERFLAG_CODECCONFIG) {
2543                    ALOGV("[%s] calling emptyBuffer %p w/ codec specific data",
2544                         mCodec->mComponentName.c_str(), bufferID);
2545                } else if (flags & OMX_BUFFERFLAG_EOS) {
2546                    ALOGV("[%s] calling emptyBuffer %p w/ EOS",
2547                         mCodec->mComponentName.c_str(), bufferID);
2548                } else {
2549                    ALOGV("[%s] calling emptyBuffer %p w/ time %lld us",
2550                         mCodec->mComponentName.c_str(), bufferID, timeUs);
2551                }
2552
2553                CHECK_EQ(mCodec->mOMX->emptyBuffer(
2554                            mCodec->mNode,
2555                            bufferID,
2556                            0,
2557                            buffer->size(),
2558                            flags,
2559                            timeUs),
2560                         (status_t)OK);
2561
2562                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
2563
2564                if (!eos) {
2565                    getMoreInputDataIfPossible();
2566                } else {
2567                    ALOGV("[%s] Signalled EOS on the input port",
2568                         mCodec->mComponentName.c_str());
2569
2570                    mCodec->mPortEOS[kPortIndexInput] = true;
2571                    mCodec->mInputEOSResult = err;
2572                }
2573            } else if (!mCodec->mPortEOS[kPortIndexInput]) {
2574                if (err != ERROR_END_OF_STREAM) {
2575                    ALOGV("[%s] Signalling EOS on the input port "
2576                         "due to error %d",
2577                         mCodec->mComponentName.c_str(), err);
2578                } else {
2579                    ALOGV("[%s] Signalling EOS on the input port",
2580                         mCodec->mComponentName.c_str());
2581                }
2582
2583                ALOGV("[%s] calling emptyBuffer %p signalling EOS",
2584                     mCodec->mComponentName.c_str(), bufferID);
2585
2586                CHECK_EQ(mCodec->mOMX->emptyBuffer(
2587                            mCodec->mNode,
2588                            bufferID,
2589                            0,
2590                            0,
2591                            OMX_BUFFERFLAG_EOS,
2592                            0),
2593                         (status_t)OK);
2594
2595                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
2596
2597                mCodec->mPortEOS[kPortIndexInput] = true;
2598                mCodec->mInputEOSResult = err;
2599            }
2600            break;
2601
2602            default:
2603                CHECK_EQ((int)mode, (int)FREE_BUFFERS);
2604                break;
2605        }
2606    }
2607}
2608
2609void ACodec::BaseState::getMoreInputDataIfPossible() {
2610    if (mCodec->mPortEOS[kPortIndexInput]) {
2611        return;
2612    }
2613
2614    BufferInfo *eligible = NULL;
2615
2616    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
2617        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
2618
2619#if 0
2620        if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) {
2621            // There's already a "read" pending.
2622            return;
2623        }
2624#endif
2625
2626        if (info->mStatus == BufferInfo::OWNED_BY_US) {
2627            eligible = info;
2628        }
2629    }
2630
2631    if (eligible == NULL) {
2632        return;
2633    }
2634
2635    postFillThisBuffer(eligible);
2636}
2637
2638bool ACodec::BaseState::onOMXFillBufferDone(
2639        IOMX::buffer_id bufferID,
2640        size_t rangeOffset, size_t rangeLength,
2641        OMX_U32 flags,
2642        int64_t timeUs,
2643        void *platformPrivate,
2644        void *dataPtr) {
2645    ALOGV("[%s] onOMXFillBufferDone %p time %lld us, flags = 0x%08lx",
2646         mCodec->mComponentName.c_str(), bufferID, timeUs, flags);
2647
2648    ssize_t index;
2649    BufferInfo *info =
2650        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
2651
2652    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
2653
2654    info->mStatus = BufferInfo::OWNED_BY_US;
2655
2656    PortMode mode = getPortMode(kPortIndexOutput);
2657
2658    switch (mode) {
2659        case KEEP_BUFFERS:
2660            break;
2661
2662        case RESUBMIT_BUFFERS:
2663        {
2664            if (rangeLength == 0 && !(flags & OMX_BUFFERFLAG_EOS)) {
2665                ALOGV("[%s] calling fillBuffer %p",
2666                     mCodec->mComponentName.c_str(), info->mBufferID);
2667
2668                CHECK_EQ(mCodec->mOMX->fillBuffer(
2669                            mCodec->mNode, info->mBufferID),
2670                         (status_t)OK);
2671
2672                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
2673                break;
2674            }
2675
2676            if (!mCodec->mIsEncoder && !mCodec->mSentFormat) {
2677                mCodec->sendFormatChange();
2678            }
2679
2680            if (mCodec->mNativeWindow == NULL) {
2681                info->mData->setRange(rangeOffset, rangeLength);
2682            }
2683
2684            if (mCodec->mSkipCutBuffer != NULL) {
2685                mCodec->mSkipCutBuffer->submit(info->mData);
2686            }
2687            info->mData->meta()->setInt64("timeUs", timeUs);
2688
2689            sp<AMessage> notify = mCodec->mNotify->dup();
2690            notify->setInt32("what", ACodec::kWhatDrainThisBuffer);
2691            notify->setPointer("buffer-id", info->mBufferID);
2692            notify->setBuffer("buffer", info->mData);
2693            notify->setInt32("flags", flags);
2694
2695            sp<AMessage> reply =
2696                new AMessage(kWhatOutputBufferDrained, mCodec->id());
2697
2698            reply->setPointer("buffer-id", info->mBufferID);
2699
2700            notify->setMessage("reply", reply);
2701
2702            notify->post();
2703
2704            info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;
2705
2706            if (flags & OMX_BUFFERFLAG_EOS) {
2707                ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str());
2708
2709                sp<AMessage> notify = mCodec->mNotify->dup();
2710                notify->setInt32("what", ACodec::kWhatEOS);
2711                notify->setInt32("err", mCodec->mInputEOSResult);
2712                notify->post();
2713
2714                mCodec->mPortEOS[kPortIndexOutput] = true;
2715            }
2716            break;
2717        }
2718
2719        default:
2720        {
2721            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
2722
2723            CHECK_EQ((status_t)OK,
2724                     mCodec->freeBuffer(kPortIndexOutput, index));
2725            break;
2726        }
2727    }
2728
2729    return true;
2730}
2731
2732void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
2733    IOMX::buffer_id bufferID;
2734    CHECK(msg->findPointer("buffer-id", &bufferID));
2735
2736    ssize_t index;
2737    BufferInfo *info =
2738        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
2739    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
2740
2741    int32_t render;
2742    if (mCodec->mNativeWindow != NULL
2743            && msg->findInt32("render", &render) && render != 0) {
2744        // The client wants this buffer to be rendered.
2745
2746        status_t err;
2747        if ((err = mCodec->mNativeWindow->queueBuffer(
2748                    mCodec->mNativeWindow.get(),
2749                    info->mGraphicBuffer.get(), -1)) == OK) {
2750            info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
2751        } else {
2752            mCodec->signalError(OMX_ErrorUndefined, err);
2753            info->mStatus = BufferInfo::OWNED_BY_US;
2754        }
2755    } else {
2756        info->mStatus = BufferInfo::OWNED_BY_US;
2757    }
2758
2759    PortMode mode = getPortMode(kPortIndexOutput);
2760
2761    switch (mode) {
2762        case KEEP_BUFFERS:
2763        {
2764            // XXX fishy, revisit!!! What about the FREE_BUFFERS case below?
2765
2766            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
2767                // We cannot resubmit the buffer we just rendered, dequeue
2768                // the spare instead.
2769
2770                info = mCodec->dequeueBufferFromNativeWindow();
2771            }
2772            break;
2773        }
2774
2775        case RESUBMIT_BUFFERS:
2776        {
2777            if (!mCodec->mPortEOS[kPortIndexOutput]) {
2778                if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
2779                    // We cannot resubmit the buffer we just rendered, dequeue
2780                    // the spare instead.
2781
2782                    info = mCodec->dequeueBufferFromNativeWindow();
2783                }
2784
2785                if (info != NULL) {
2786                    ALOGV("[%s] calling fillBuffer %p",
2787                         mCodec->mComponentName.c_str(), info->mBufferID);
2788
2789                    CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
2790                             (status_t)OK);
2791
2792                    info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
2793                }
2794            }
2795            break;
2796        }
2797
2798        default:
2799        {
2800            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
2801
2802            CHECK_EQ((status_t)OK,
2803                     mCodec->freeBuffer(kPortIndexOutput, index));
2804            break;
2805        }
2806    }
2807}
2808
2809////////////////////////////////////////////////////////////////////////////////
2810
2811ACodec::UninitializedState::UninitializedState(ACodec *codec)
2812    : BaseState(codec) {
2813}
2814
2815void ACodec::UninitializedState::stateEntered() {
2816    ALOGV("Now uninitialized");
2817}
2818
2819bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
2820    bool handled = false;
2821
2822    switch (msg->what()) {
2823        case ACodec::kWhatSetup:
2824        {
2825            onSetup(msg);
2826
2827            handled = true;
2828            break;
2829        }
2830
2831        case ACodec::kWhatAllocateComponent:
2832        {
2833            onAllocateComponent(msg);
2834            handled = true;
2835            break;
2836        }
2837
2838        case ACodec::kWhatShutdown:
2839        {
2840            int32_t keepComponentAllocated;
2841            CHECK(msg->findInt32(
2842                        "keepComponentAllocated", &keepComponentAllocated));
2843            CHECK(!keepComponentAllocated);
2844
2845            sp<AMessage> notify = mCodec->mNotify->dup();
2846            notify->setInt32("what", ACodec::kWhatShutdownCompleted);
2847            notify->post();
2848
2849            handled = true;
2850            break;
2851        }
2852
2853        case ACodec::kWhatFlush:
2854        {
2855            sp<AMessage> notify = mCodec->mNotify->dup();
2856            notify->setInt32("what", ACodec::kWhatFlushCompleted);
2857            notify->post();
2858
2859            handled = true;
2860            break;
2861        }
2862
2863        default:
2864            return BaseState::onMessageReceived(msg);
2865    }
2866
2867    return handled;
2868}
2869
2870void ACodec::UninitializedState::onSetup(
2871        const sp<AMessage> &msg) {
2872    if (onAllocateComponent(msg)
2873            && mCodec->mLoadedState->onConfigureComponent(msg)) {
2874        mCodec->mLoadedState->onStart();
2875    }
2876}
2877
2878bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
2879    ALOGV("onAllocateComponent");
2880
2881    CHECK(mCodec->mNode == NULL);
2882
2883    OMXClient client;
2884    CHECK_EQ(client.connect(), (status_t)OK);
2885
2886    sp<IOMX> omx = client.interface();
2887
2888    Vector<String8> matchingCodecs;
2889    Vector<uint32_t> matchingCodecQuirks;
2890
2891    AString mime;
2892
2893    AString componentName;
2894    uint32_t quirks;
2895    if (msg->findString("componentName", &componentName)) {
2896        matchingCodecs.push_back(String8(componentName.c_str()));
2897
2898        if (!OMXCodec::findCodecQuirks(componentName.c_str(), &quirks)) {
2899            quirks = 0;
2900        }
2901        matchingCodecQuirks.push_back(quirks);
2902    } else {
2903        CHECK(msg->findString("mime", &mime));
2904
2905        int32_t encoder;
2906        if (!msg->findInt32("encoder", &encoder)) {
2907            encoder = false;
2908        }
2909
2910        OMXCodec::findMatchingCodecs(
2911                mime.c_str(),
2912                encoder, // createEncoder
2913                NULL,  // matchComponentName
2914                0,     // flags
2915                &matchingCodecs,
2916                &matchingCodecQuirks);
2917    }
2918
2919    sp<CodecObserver> observer = new CodecObserver;
2920    IOMX::node_id node = NULL;
2921
2922    for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
2923            ++matchIndex) {
2924        componentName = matchingCodecs.itemAt(matchIndex).string();
2925        quirks = matchingCodecQuirks.itemAt(matchIndex);
2926
2927        pid_t tid = androidGetTid();
2928        int prevPriority = androidGetThreadPriority(tid);
2929        androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
2930        status_t err = omx->allocateNode(componentName.c_str(), observer, &node);
2931        androidSetThreadPriority(tid, prevPriority);
2932
2933        if (err == OK) {
2934            break;
2935        }
2936
2937        node = NULL;
2938    }
2939
2940    if (node == NULL) {
2941        if (!mime.empty()) {
2942            ALOGE("Unable to instantiate a decoder for type '%s'.",
2943                 mime.c_str());
2944        } else {
2945            ALOGE("Unable to instantiate decoder '%s'.", componentName.c_str());
2946        }
2947
2948        mCodec->signalError(OMX_ErrorComponentNotFound);
2949        return false;
2950    }
2951
2952    sp<AMessage> notify = new AMessage(kWhatOMXMessage, mCodec->id());
2953    observer->setNotificationMessage(notify);
2954
2955    mCodec->mComponentName = componentName;
2956    mCodec->mFlags = 0;
2957
2958    if (componentName.endsWith(".secure")) {
2959        mCodec->mFlags |= kFlagIsSecure;
2960    }
2961
2962    mCodec->mQuirks = quirks;
2963    mCodec->mOMX = omx;
2964    mCodec->mNode = node;
2965
2966    mCodec->mPortEOS[kPortIndexInput] =
2967        mCodec->mPortEOS[kPortIndexOutput] = false;
2968
2969    mCodec->mInputEOSResult = OK;
2970
2971    {
2972        sp<AMessage> notify = mCodec->mNotify->dup();
2973        notify->setInt32("what", ACodec::kWhatComponentAllocated);
2974        notify->setString("componentName", mCodec->mComponentName.c_str());
2975        notify->post();
2976    }
2977
2978    mCodec->changeState(mCodec->mLoadedState);
2979
2980    return true;
2981}
2982
2983////////////////////////////////////////////////////////////////////////////////
2984
2985ACodec::LoadedState::LoadedState(ACodec *codec)
2986    : BaseState(codec) {
2987}
2988
2989void ACodec::LoadedState::stateEntered() {
2990    ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
2991
2992    if (mCodec->mShutdownInProgress) {
2993        bool keepComponentAllocated = mCodec->mKeepComponentAllocated;
2994
2995        mCodec->mShutdownInProgress = false;
2996        mCodec->mKeepComponentAllocated = false;
2997
2998        onShutdown(keepComponentAllocated);
2999    }
3000}
3001
3002void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) {
3003    if (!keepComponentAllocated) {
3004        CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
3005
3006        mCodec->mNativeWindow.clear();
3007        mCodec->mNode = NULL;
3008        mCodec->mOMX.clear();
3009        mCodec->mQuirks = 0;
3010        mCodec->mFlags = 0;
3011        mCodec->mComponentName.clear();
3012
3013        mCodec->changeState(mCodec->mUninitializedState);
3014    }
3015
3016    sp<AMessage> notify = mCodec->mNotify->dup();
3017    notify->setInt32("what", ACodec::kWhatShutdownCompleted);
3018    notify->post();
3019}
3020
3021bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) {
3022    bool handled = false;
3023
3024    switch (msg->what()) {
3025        case ACodec::kWhatConfigureComponent:
3026        {
3027            onConfigureComponent(msg);
3028            handled = true;
3029            break;
3030        }
3031
3032        case ACodec::kWhatStart:
3033        {
3034            onStart();
3035            handled = true;
3036            break;
3037        }
3038
3039        case ACodec::kWhatShutdown:
3040        {
3041            int32_t keepComponentAllocated;
3042            CHECK(msg->findInt32(
3043                        "keepComponentAllocated", &keepComponentAllocated));
3044
3045            onShutdown(keepComponentAllocated);
3046
3047            handled = true;
3048            break;
3049        }
3050
3051        case ACodec::kWhatFlush:
3052        {
3053            sp<AMessage> notify = mCodec->mNotify->dup();
3054            notify->setInt32("what", ACodec::kWhatFlushCompleted);
3055            notify->post();
3056
3057            handled = true;
3058            break;
3059        }
3060
3061        default:
3062            return BaseState::onMessageReceived(msg);
3063    }
3064
3065    return handled;
3066}
3067
3068bool ACodec::LoadedState::onConfigureComponent(
3069        const sp<AMessage> &msg) {
3070    ALOGV("onConfigureComponent");
3071
3072    CHECK(mCodec->mNode != NULL);
3073
3074    AString mime;
3075    CHECK(msg->findString("mime", &mime));
3076
3077    status_t err = mCodec->configureCodec(mime.c_str(), msg);
3078
3079    if (err != OK) {
3080        ALOGE("[%s] configureCodec returning error %d",
3081              mCodec->mComponentName.c_str(), err);
3082
3083        mCodec->signalError(OMX_ErrorUndefined, err);
3084        return false;
3085    }
3086
3087    sp<RefBase> obj;
3088    if (msg->findObject("native-window", &obj)
3089            && strncmp("OMX.google.", mCodec->mComponentName.c_str(), 11)) {
3090        sp<NativeWindowWrapper> nativeWindow(
3091                static_cast<NativeWindowWrapper *>(obj.get()));
3092        CHECK(nativeWindow != NULL);
3093        mCodec->mNativeWindow = nativeWindow->getNativeWindow();
3094
3095        native_window_set_scaling_mode(
3096                mCodec->mNativeWindow.get(),
3097                NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
3098    }
3099    CHECK_EQ((status_t)OK, mCodec->initNativeWindow());
3100
3101    {
3102        sp<AMessage> notify = mCodec->mNotify->dup();
3103        notify->setInt32("what", ACodec::kWhatComponentConfigured);
3104        notify->post();
3105    }
3106
3107    return true;
3108}
3109
3110void ACodec::LoadedState::onStart() {
3111    ALOGV("onStart");
3112
3113    CHECK_EQ(mCodec->mOMX->sendCommand(
3114                mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
3115             (status_t)OK);
3116
3117    mCodec->changeState(mCodec->mLoadedToIdleState);
3118}
3119
3120////////////////////////////////////////////////////////////////////////////////
3121
3122ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec)
3123    : BaseState(codec) {
3124}
3125
3126void ACodec::LoadedToIdleState::stateEntered() {
3127    ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
3128
3129    status_t err;
3130    if ((err = allocateBuffers()) != OK) {
3131        ALOGE("Failed to allocate buffers after transitioning to IDLE state "
3132             "(error 0x%08x)",
3133             err);
3134
3135        mCodec->signalError(OMX_ErrorUndefined, err);
3136
3137        mCodec->changeState(mCodec->mLoadedState);
3138    }
3139}
3140
3141status_t ACodec::LoadedToIdleState::allocateBuffers() {
3142    status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput);
3143
3144    if (err != OK) {
3145        return err;
3146    }
3147
3148    return mCodec->allocateBuffersOnPort(kPortIndexOutput);
3149}
3150
3151bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
3152    switch (msg->what()) {
3153        case kWhatShutdown:
3154        {
3155            mCodec->deferMessage(msg);
3156            return true;
3157        }
3158
3159        default:
3160            return BaseState::onMessageReceived(msg);
3161    }
3162}
3163
3164bool ACodec::LoadedToIdleState::onOMXEvent(
3165        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3166    switch (event) {
3167        case OMX_EventCmdComplete:
3168        {
3169            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
3170            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
3171
3172            CHECK_EQ(mCodec->mOMX->sendCommand(
3173                        mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting),
3174                     (status_t)OK);
3175
3176            mCodec->changeState(mCodec->mIdleToExecutingState);
3177
3178            return true;
3179        }
3180
3181        default:
3182            return BaseState::onOMXEvent(event, data1, data2);
3183    }
3184}
3185
3186////////////////////////////////////////////////////////////////////////////////
3187
3188ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec)
3189    : BaseState(codec) {
3190}
3191
3192void ACodec::IdleToExecutingState::stateEntered() {
3193    ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
3194}
3195
3196bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
3197    switch (msg->what()) {
3198        case kWhatShutdown:
3199        {
3200            mCodec->deferMessage(msg);
3201            return true;
3202        }
3203
3204        default:
3205            return BaseState::onMessageReceived(msg);
3206    }
3207}
3208
3209bool ACodec::IdleToExecutingState::onOMXEvent(
3210        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3211    switch (event) {
3212        case OMX_EventCmdComplete:
3213        {
3214            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
3215            CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting);
3216
3217            mCodec->mExecutingState->resume();
3218            mCodec->changeState(mCodec->mExecutingState);
3219
3220            return true;
3221        }
3222
3223        default:
3224            return BaseState::onOMXEvent(event, data1, data2);
3225    }
3226}
3227
3228////////////////////////////////////////////////////////////////////////////////
3229
3230ACodec::ExecutingState::ExecutingState(ACodec *codec)
3231    : BaseState(codec),
3232      mActive(false) {
3233}
3234
3235ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode(
3236        OMX_U32 portIndex) {
3237    return RESUBMIT_BUFFERS;
3238}
3239
3240void ACodec::ExecutingState::submitOutputBuffers() {
3241    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
3242        BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
3243
3244        if (mCodec->mNativeWindow != NULL) {
3245            CHECK(info->mStatus == BufferInfo::OWNED_BY_US
3246                    || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
3247
3248            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
3249                continue;
3250            }
3251        } else {
3252            CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
3253        }
3254
3255        ALOGV("[%s] calling fillBuffer %p",
3256             mCodec->mComponentName.c_str(), info->mBufferID);
3257
3258        CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
3259                 (status_t)OK);
3260
3261        info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
3262    }
3263}
3264
3265void ACodec::ExecutingState::resume() {
3266    if (mActive) {
3267        ALOGV("[%s] We're already active, no need to resume.",
3268             mCodec->mComponentName.c_str());
3269
3270        return;
3271    }
3272
3273    submitOutputBuffers();
3274
3275    // Post the first input buffer.
3276    CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u);
3277    BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(0);
3278
3279    postFillThisBuffer(info);
3280
3281    mActive = true;
3282}
3283
3284void ACodec::ExecutingState::stateEntered() {
3285    ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
3286
3287    mCodec->processDeferredMessages();
3288}
3289
3290bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) {
3291    bool handled = false;
3292
3293    switch (msg->what()) {
3294        case kWhatShutdown:
3295        {
3296            int32_t keepComponentAllocated;
3297            CHECK(msg->findInt32(
3298                        "keepComponentAllocated", &keepComponentAllocated));
3299
3300            mCodec->mShutdownInProgress = true;
3301            mCodec->mKeepComponentAllocated = keepComponentAllocated;
3302
3303            mActive = false;
3304
3305            CHECK_EQ(mCodec->mOMX->sendCommand(
3306                        mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
3307                     (status_t)OK);
3308
3309            mCodec->changeState(mCodec->mExecutingToIdleState);
3310
3311            handled = true;
3312            break;
3313        }
3314
3315        case kWhatFlush:
3316        {
3317            ALOGV("[%s] ExecutingState flushing now "
3318                 "(codec owns %d/%d input, %d/%d output).",
3319                    mCodec->mComponentName.c_str(),
3320                    mCodec->countBuffersOwnedByComponent(kPortIndexInput),
3321                    mCodec->mBuffers[kPortIndexInput].size(),
3322                    mCodec->countBuffersOwnedByComponent(kPortIndexOutput),
3323                    mCodec->mBuffers[kPortIndexOutput].size());
3324
3325            mActive = false;
3326
3327            CHECK_EQ(mCodec->mOMX->sendCommand(
3328                        mCodec->mNode, OMX_CommandFlush, OMX_ALL),
3329                     (status_t)OK);
3330
3331            mCodec->changeState(mCodec->mFlushingState);
3332
3333            handled = true;
3334            break;
3335        }
3336
3337        case kWhatResume:
3338        {
3339            resume();
3340
3341            handled = true;
3342            break;
3343        }
3344
3345        default:
3346            handled = BaseState::onMessageReceived(msg);
3347            break;
3348    }
3349
3350    return handled;
3351}
3352
3353bool ACodec::ExecutingState::onOMXEvent(
3354        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3355    switch (event) {
3356        case OMX_EventPortSettingsChanged:
3357        {
3358            CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
3359
3360            if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
3361                CHECK_EQ(mCodec->mOMX->sendCommand(
3362                            mCodec->mNode,
3363                            OMX_CommandPortDisable, kPortIndexOutput),
3364                         (status_t)OK);
3365
3366                mCodec->freeOutputBuffersNotOwnedByComponent();
3367
3368                mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
3369            } else if (data2 == OMX_IndexConfigCommonOutputCrop) {
3370                mCodec->mSentFormat = false;
3371            } else {
3372                ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx",
3373                     mCodec->mComponentName.c_str(), data2);
3374            }
3375
3376            return true;
3377        }
3378
3379        case OMX_EventBufferFlag:
3380        {
3381            return true;
3382        }
3383
3384        default:
3385            return BaseState::onOMXEvent(event, data1, data2);
3386    }
3387}
3388
3389////////////////////////////////////////////////////////////////////////////////
3390
3391ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState(
3392        ACodec *codec)
3393    : BaseState(codec) {
3394}
3395
3396ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode(
3397        OMX_U32 portIndex) {
3398    if (portIndex == kPortIndexOutput) {
3399        return FREE_BUFFERS;
3400    }
3401
3402    CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput);
3403
3404    return RESUBMIT_BUFFERS;
3405}
3406
3407bool ACodec::OutputPortSettingsChangedState::onMessageReceived(
3408        const sp<AMessage> &msg) {
3409    bool handled = false;
3410
3411    switch (msg->what()) {
3412        case kWhatFlush:
3413        case kWhatShutdown:
3414        case kWhatResume:
3415        {
3416            if (msg->what() == kWhatResume) {
3417                ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
3418            }
3419
3420            mCodec->deferMessage(msg);
3421            handled = true;
3422            break;
3423        }
3424
3425        default:
3426            handled = BaseState::onMessageReceived(msg);
3427            break;
3428    }
3429
3430    return handled;
3431}
3432
3433void ACodec::OutputPortSettingsChangedState::stateEntered() {
3434    ALOGV("[%s] Now handling output port settings change",
3435         mCodec->mComponentName.c_str());
3436}
3437
3438bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
3439        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3440    switch (event) {
3441        case OMX_EventCmdComplete:
3442        {
3443            if (data1 == (OMX_U32)OMX_CommandPortDisable) {
3444                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
3445
3446                ALOGV("[%s] Output port now disabled.",
3447                        mCodec->mComponentName.c_str());
3448
3449                CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty());
3450                mCodec->mDealer[kPortIndexOutput].clear();
3451
3452                CHECK_EQ(mCodec->mOMX->sendCommand(
3453                            mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput),
3454                         (status_t)OK);
3455
3456                status_t err;
3457                if ((err = mCodec->allocateBuffersOnPort(
3458                                kPortIndexOutput)) != OK) {
3459                    ALOGE("Failed to allocate output port buffers after "
3460                         "port reconfiguration (error 0x%08x)",
3461                         err);
3462
3463                    mCodec->signalError(OMX_ErrorUndefined, err);
3464
3465                    // This is technically not correct, but appears to be
3466                    // the only way to free the component instance.
3467                    // Controlled transitioning from excecuting->idle
3468                    // and idle->loaded seem impossible probably because
3469                    // the output port never finishes re-enabling.
3470                    mCodec->mShutdownInProgress = true;
3471                    mCodec->mKeepComponentAllocated = false;
3472                    mCodec->changeState(mCodec->mLoadedState);
3473                }
3474
3475                return true;
3476            } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
3477                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
3478
3479                mCodec->mSentFormat = false;
3480
3481                ALOGV("[%s] Output port now reenabled.",
3482                        mCodec->mComponentName.c_str());
3483
3484                if (mCodec->mExecutingState->active()) {
3485                    mCodec->mExecutingState->submitOutputBuffers();
3486                }
3487
3488                mCodec->changeState(mCodec->mExecutingState);
3489
3490                return true;
3491            }
3492
3493            return false;
3494        }
3495
3496        default:
3497            return false;
3498    }
3499}
3500
3501////////////////////////////////////////////////////////////////////////////////
3502
3503ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec)
3504    : BaseState(codec),
3505      mComponentNowIdle(false) {
3506}
3507
3508bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) {
3509    bool handled = false;
3510
3511    switch (msg->what()) {
3512        case kWhatFlush:
3513        {
3514            // Don't send me a flush request if you previously wanted me
3515            // to shutdown.
3516            TRESPASS();
3517            break;
3518        }
3519
3520        case kWhatShutdown:
3521        {
3522            // We're already doing that...
3523
3524            handled = true;
3525            break;
3526        }
3527
3528        default:
3529            handled = BaseState::onMessageReceived(msg);
3530            break;
3531    }
3532
3533    return handled;
3534}
3535
3536void ACodec::ExecutingToIdleState::stateEntered() {
3537    ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
3538
3539    mComponentNowIdle = false;
3540    mCodec->mSentFormat = false;
3541}
3542
3543bool ACodec::ExecutingToIdleState::onOMXEvent(
3544        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3545    switch (event) {
3546        case OMX_EventCmdComplete:
3547        {
3548            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
3549            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
3550
3551            mComponentNowIdle = true;
3552
3553            changeStateIfWeOwnAllBuffers();
3554
3555            return true;
3556        }
3557
3558        case OMX_EventPortSettingsChanged:
3559        case OMX_EventBufferFlag:
3560        {
3561            // We're shutting down and don't care about this anymore.
3562            return true;
3563        }
3564
3565        default:
3566            return BaseState::onOMXEvent(event, data1, data2);
3567    }
3568}
3569
3570void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
3571    if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) {
3572        CHECK_EQ(mCodec->mOMX->sendCommand(
3573                    mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded),
3574                 (status_t)OK);
3575
3576        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK);
3577        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK);
3578
3579        if (mCodec->mFlags & kFlagIsSecure && mCodec->mNativeWindow != NULL) {
3580            // We push enough 1x1 blank buffers to ensure that one of
3581            // them has made it to the display.  This allows the OMX
3582            // component teardown to zero out any protected buffers
3583            // without the risk of scanning out one of those buffers.
3584            mCodec->pushBlankBuffersToNativeWindow();
3585        }
3586
3587        mCodec->changeState(mCodec->mIdleToLoadedState);
3588    }
3589}
3590
3591void ACodec::ExecutingToIdleState::onInputBufferFilled(
3592        const sp<AMessage> &msg) {
3593    BaseState::onInputBufferFilled(msg);
3594
3595    changeStateIfWeOwnAllBuffers();
3596}
3597
3598void ACodec::ExecutingToIdleState::onOutputBufferDrained(
3599        const sp<AMessage> &msg) {
3600    BaseState::onOutputBufferDrained(msg);
3601
3602    changeStateIfWeOwnAllBuffers();
3603}
3604
3605////////////////////////////////////////////////////////////////////////////////
3606
3607ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec)
3608    : BaseState(codec) {
3609}
3610
3611bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) {
3612    bool handled = false;
3613
3614    switch (msg->what()) {
3615        case kWhatShutdown:
3616        {
3617            // We're already doing that...
3618
3619            handled = true;
3620            break;
3621        }
3622
3623        case kWhatFlush:
3624        {
3625            // Don't send me a flush request if you previously wanted me
3626            // to shutdown.
3627            TRESPASS();
3628            break;
3629        }
3630
3631        default:
3632            handled = BaseState::onMessageReceived(msg);
3633            break;
3634    }
3635
3636    return handled;
3637}
3638
3639void ACodec::IdleToLoadedState::stateEntered() {
3640    ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
3641}
3642
3643bool ACodec::IdleToLoadedState::onOMXEvent(
3644        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3645    switch (event) {
3646        case OMX_EventCmdComplete:
3647        {
3648            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
3649            CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded);
3650
3651            mCodec->changeState(mCodec->mLoadedState);
3652
3653            return true;
3654        }
3655
3656        default:
3657            return BaseState::onOMXEvent(event, data1, data2);
3658    }
3659}
3660
3661////////////////////////////////////////////////////////////////////////////////
3662
3663ACodec::FlushingState::FlushingState(ACodec *codec)
3664    : BaseState(codec) {
3665}
3666
3667void ACodec::FlushingState::stateEntered() {
3668    ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());
3669
3670    mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
3671}
3672
3673bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) {
3674    bool handled = false;
3675
3676    switch (msg->what()) {
3677        case kWhatShutdown:
3678        {
3679            mCodec->deferMessage(msg);
3680            break;
3681        }
3682
3683        case kWhatFlush:
3684        {
3685            // We're already doing this right now.
3686            handled = true;
3687            break;
3688        }
3689
3690        default:
3691            handled = BaseState::onMessageReceived(msg);
3692            break;
3693    }
3694
3695    return handled;
3696}
3697
3698bool ACodec::FlushingState::onOMXEvent(
3699        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3700    ALOGV("[%s] FlushingState onOMXEvent(%d,%ld)",
3701            mCodec->mComponentName.c_str(), event, data1);
3702
3703    switch (event) {
3704        case OMX_EventCmdComplete:
3705        {
3706            CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush);
3707
3708            if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
3709                CHECK(!mFlushComplete[data2]);
3710                mFlushComplete[data2] = true;
3711
3712                if (mFlushComplete[kPortIndexInput]
3713                        && mFlushComplete[kPortIndexOutput]) {
3714                    changeStateIfWeOwnAllBuffers();
3715                }
3716            } else {
3717                CHECK_EQ(data2, OMX_ALL);
3718                CHECK(mFlushComplete[kPortIndexInput]);
3719                CHECK(mFlushComplete[kPortIndexOutput]);
3720
3721                changeStateIfWeOwnAllBuffers();
3722            }
3723
3724            return true;
3725        }
3726
3727        case OMX_EventPortSettingsChanged:
3728        {
3729            sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id());
3730            msg->setInt32("type", omx_message::EVENT);
3731            msg->setPointer("node", mCodec->mNode);
3732            msg->setInt32("event", event);
3733            msg->setInt32("data1", data1);
3734            msg->setInt32("data2", data2);
3735
3736            ALOGV("[%s] Deferring OMX_EventPortSettingsChanged",
3737                 mCodec->mComponentName.c_str());
3738
3739            mCodec->deferMessage(msg);
3740
3741            return true;
3742        }
3743
3744        default:
3745            return BaseState::onOMXEvent(event, data1, data2);
3746    }
3747
3748    return true;
3749}
3750
3751void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) {
3752    BaseState::onOutputBufferDrained(msg);
3753
3754    changeStateIfWeOwnAllBuffers();
3755}
3756
3757void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) {
3758    BaseState::onInputBufferFilled(msg);
3759
3760    changeStateIfWeOwnAllBuffers();
3761}
3762
3763void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() {
3764    if (mFlushComplete[kPortIndexInput]
3765            && mFlushComplete[kPortIndexOutput]
3766            && mCodec->allYourBuffersAreBelongToUs()) {
3767        sp<AMessage> notify = mCodec->mNotify->dup();
3768        notify->setInt32("what", ACodec::kWhatFlushCompleted);
3769        notify->post();
3770
3771        mCodec->mPortEOS[kPortIndexInput] =
3772            mCodec->mPortEOS[kPortIndexOutput] = false;
3773
3774        mCodec->mInputEOSResult = OK;
3775
3776        mCodec->changeState(mCodec->mExecutingState);
3777    }
3778}
3779
3780}  // namespace android
3781