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