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