ACodec.cpp revision 5778822d86b0337407514b9372562b86edfa91cd
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->setObject(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->setObject("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<RefBase> obj;
2162    int32_t err = OK;
2163    bool eos = false;
2164
2165    if (!msg->findObject("buffer", &obj)) {
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        obj.clear();
2172
2173        eos = true;
2174    }
2175
2176    sp<ABuffer> buffer = static_cast<ABuffer *>(obj.get());
2177
2178    int32_t tmp;
2179    if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) {
2180        eos = true;
2181        err = ERROR_END_OF_STREAM;
2182    }
2183
2184    BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
2185    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM);
2186
2187    info->mStatus = BufferInfo::OWNED_BY_US;
2188
2189    PortMode mode = getPortMode(kPortIndexInput);
2190
2191    switch (mode) {
2192        case KEEP_BUFFERS:
2193        {
2194            if (eos) {
2195                if (!mCodec->mPortEOS[kPortIndexInput]) {
2196                    mCodec->mPortEOS[kPortIndexInput] = true;
2197                    mCodec->mInputEOSResult = err;
2198                }
2199            }
2200            break;
2201        }
2202
2203        case RESUBMIT_BUFFERS:
2204        {
2205            if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) {
2206                int64_t timeUs;
2207                CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
2208
2209                OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
2210
2211                int32_t isCSD;
2212                if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) {
2213                    flags |= OMX_BUFFERFLAG_CODECCONFIG;
2214                }
2215
2216                if (eos) {
2217                    flags |= OMX_BUFFERFLAG_EOS;
2218                }
2219
2220                if (buffer != info->mData) {
2221                    if (0 && !(flags & OMX_BUFFERFLAG_CODECCONFIG)) {
2222                        ALOGV("[%s] Needs to copy input data.",
2223                             mCodec->mComponentName.c_str());
2224                    }
2225
2226                    CHECK_LE(buffer->size(), info->mData->capacity());
2227                    memcpy(info->mData->data(), buffer->data(), buffer->size());
2228                }
2229
2230                if (flags & OMX_BUFFERFLAG_CODECCONFIG) {
2231                    ALOGV("[%s] calling emptyBuffer %p w/ codec specific data",
2232                         mCodec->mComponentName.c_str(), bufferID);
2233                } else if (flags & OMX_BUFFERFLAG_EOS) {
2234                    ALOGV("[%s] calling emptyBuffer %p w/ EOS",
2235                         mCodec->mComponentName.c_str(), bufferID);
2236                } else {
2237                    ALOGV("[%s] calling emptyBuffer %p w/ time %lld us",
2238                         mCodec->mComponentName.c_str(), bufferID, timeUs);
2239                }
2240
2241                CHECK_EQ(mCodec->mOMX->emptyBuffer(
2242                            mCodec->mNode,
2243                            bufferID,
2244                            0,
2245                            buffer->size(),
2246                            flags,
2247                            timeUs),
2248                         (status_t)OK);
2249
2250                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
2251
2252                if (!eos) {
2253                    getMoreInputDataIfPossible();
2254                } else {
2255                    ALOGV("[%s] Signalled EOS on the input port",
2256                         mCodec->mComponentName.c_str());
2257
2258                    mCodec->mPortEOS[kPortIndexInput] = true;
2259                    mCodec->mInputEOSResult = err;
2260                }
2261            } else if (!mCodec->mPortEOS[kPortIndexInput]) {
2262                if (err != ERROR_END_OF_STREAM) {
2263                    ALOGV("[%s] Signalling EOS on the input port "
2264                         "due to error %d",
2265                         mCodec->mComponentName.c_str(), err);
2266                } else {
2267                    ALOGV("[%s] Signalling EOS on the input port",
2268                         mCodec->mComponentName.c_str());
2269                }
2270
2271                ALOGV("[%s] calling emptyBuffer %p signalling EOS",
2272                     mCodec->mComponentName.c_str(), bufferID);
2273
2274                CHECK_EQ(mCodec->mOMX->emptyBuffer(
2275                            mCodec->mNode,
2276                            bufferID,
2277                            0,
2278                            0,
2279                            OMX_BUFFERFLAG_EOS,
2280                            0),
2281                         (status_t)OK);
2282
2283                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
2284
2285                mCodec->mPortEOS[kPortIndexInput] = true;
2286                mCodec->mInputEOSResult = err;
2287            }
2288            break;
2289
2290            default:
2291                CHECK_EQ((int)mode, (int)FREE_BUFFERS);
2292                break;
2293        }
2294    }
2295}
2296
2297void ACodec::BaseState::getMoreInputDataIfPossible() {
2298    if (mCodec->mPortEOS[kPortIndexInput]) {
2299        return;
2300    }
2301
2302    BufferInfo *eligible = NULL;
2303
2304    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
2305        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
2306
2307#if 0
2308        if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) {
2309            // There's already a "read" pending.
2310            return;
2311        }
2312#endif
2313
2314        if (info->mStatus == BufferInfo::OWNED_BY_US) {
2315            eligible = info;
2316        }
2317    }
2318
2319    if (eligible == NULL) {
2320        return;
2321    }
2322
2323    postFillThisBuffer(eligible);
2324}
2325
2326bool ACodec::BaseState::onOMXFillBufferDone(
2327        IOMX::buffer_id bufferID,
2328        size_t rangeOffset, size_t rangeLength,
2329        OMX_U32 flags,
2330        int64_t timeUs,
2331        void *platformPrivate,
2332        void *dataPtr) {
2333    ALOGV("[%s] onOMXFillBufferDone %p time %lld us, flags = 0x%08lx",
2334         mCodec->mComponentName.c_str(), bufferID, timeUs, flags);
2335
2336    ssize_t index;
2337    BufferInfo *info =
2338        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
2339
2340    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
2341
2342    info->mStatus = BufferInfo::OWNED_BY_US;
2343
2344    PortMode mode = getPortMode(kPortIndexOutput);
2345
2346    switch (mode) {
2347        case KEEP_BUFFERS:
2348            break;
2349
2350        case RESUBMIT_BUFFERS:
2351        {
2352            if (rangeLength == 0 && !(flags & OMX_BUFFERFLAG_EOS)) {
2353                ALOGV("[%s] calling fillBuffer %p",
2354                     mCodec->mComponentName.c_str(), info->mBufferID);
2355
2356                CHECK_EQ(mCodec->mOMX->fillBuffer(
2357                            mCodec->mNode, info->mBufferID),
2358                         (status_t)OK);
2359
2360                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
2361                break;
2362            }
2363
2364            if (!mCodec->mIsEncoder && !mCodec->mSentFormat) {
2365                mCodec->sendFormatChange();
2366            }
2367
2368            if (mCodec->mNativeWindow == NULL) {
2369                info->mData->setRange(rangeOffset, rangeLength);
2370            }
2371
2372            info->mData->meta()->setInt64("timeUs", timeUs);
2373
2374            sp<AMessage> notify = mCodec->mNotify->dup();
2375            notify->setInt32("what", ACodec::kWhatDrainThisBuffer);
2376            notify->setPointer("buffer-id", info->mBufferID);
2377            notify->setObject("buffer", info->mData);
2378            notify->setInt32("flags", flags);
2379
2380            sp<AMessage> reply =
2381                new AMessage(kWhatOutputBufferDrained, mCodec->id());
2382
2383            reply->setPointer("buffer-id", info->mBufferID);
2384
2385            notify->setMessage("reply", reply);
2386
2387            notify->post();
2388
2389            info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;
2390
2391            if (flags & OMX_BUFFERFLAG_EOS) {
2392                ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str());
2393
2394                sp<AMessage> notify = mCodec->mNotify->dup();
2395                notify->setInt32("what", ACodec::kWhatEOS);
2396                notify->setInt32("err", mCodec->mInputEOSResult);
2397                notify->post();
2398
2399                mCodec->mPortEOS[kPortIndexOutput] = true;
2400            }
2401            break;
2402        }
2403
2404        default:
2405        {
2406            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
2407
2408            CHECK_EQ((status_t)OK,
2409                     mCodec->freeBuffer(kPortIndexOutput, index));
2410            break;
2411        }
2412    }
2413
2414    return true;
2415}
2416
2417void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
2418    IOMX::buffer_id bufferID;
2419    CHECK(msg->findPointer("buffer-id", &bufferID));
2420
2421    ssize_t index;
2422    BufferInfo *info =
2423        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
2424    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
2425
2426    int32_t render;
2427    if (mCodec->mNativeWindow != NULL
2428            && msg->findInt32("render", &render) && render != 0) {
2429        // The client wants this buffer to be rendered.
2430
2431        status_t err;
2432        if ((err = mCodec->mNativeWindow->queueBuffer(
2433                    mCodec->mNativeWindow.get(),
2434                    info->mGraphicBuffer.get())) == OK) {
2435            info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
2436        } else {
2437            mCodec->signalError(OMX_ErrorUndefined, err);
2438            info->mStatus = BufferInfo::OWNED_BY_US;
2439        }
2440    } else {
2441        info->mStatus = BufferInfo::OWNED_BY_US;
2442    }
2443
2444    PortMode mode = getPortMode(kPortIndexOutput);
2445
2446    switch (mode) {
2447        case KEEP_BUFFERS:
2448        {
2449            // XXX fishy, revisit!!! What about the FREE_BUFFERS case below?
2450
2451            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
2452                // We cannot resubmit the buffer we just rendered, dequeue
2453                // the spare instead.
2454
2455                info = mCodec->dequeueBufferFromNativeWindow();
2456            }
2457            break;
2458        }
2459
2460        case RESUBMIT_BUFFERS:
2461        {
2462            if (!mCodec->mPortEOS[kPortIndexOutput]) {
2463                if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
2464                    // We cannot resubmit the buffer we just rendered, dequeue
2465                    // the spare instead.
2466
2467                    info = mCodec->dequeueBufferFromNativeWindow();
2468                }
2469
2470                if (info != NULL) {
2471                    ALOGV("[%s] calling fillBuffer %p",
2472                         mCodec->mComponentName.c_str(), info->mBufferID);
2473
2474                    CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
2475                             (status_t)OK);
2476
2477                    info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
2478                }
2479            }
2480            break;
2481        }
2482
2483        default:
2484        {
2485            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
2486
2487            CHECK_EQ((status_t)OK,
2488                     mCodec->freeBuffer(kPortIndexOutput, index));
2489            break;
2490        }
2491    }
2492}
2493
2494////////////////////////////////////////////////////////////////////////////////
2495
2496ACodec::UninitializedState::UninitializedState(ACodec *codec)
2497    : BaseState(codec) {
2498}
2499
2500bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
2501    bool handled = false;
2502
2503    switch (msg->what()) {
2504        case ACodec::kWhatSetup:
2505        {
2506            onSetup(msg);
2507
2508            handled = true;
2509            break;
2510        }
2511
2512        case ACodec::kWhatAllocateComponent:
2513        {
2514            onAllocateComponent(msg);
2515            handled = true;
2516            break;
2517        }
2518
2519        case ACodec::kWhatConfigureComponent:
2520        {
2521            onConfigureComponent(msg);
2522            handled = true;
2523            break;
2524        }
2525
2526        case ACodec::kWhatStart:
2527        {
2528            onStart();
2529            handled = true;
2530            break;
2531        }
2532
2533        case ACodec::kWhatShutdown:
2534        {
2535            sp<AMessage> notify = mCodec->mNotify->dup();
2536            notify->setInt32("what", ACodec::kWhatShutdownCompleted);
2537            notify->post();
2538
2539            handled = true;
2540            break;
2541        }
2542
2543        case ACodec::kWhatFlush:
2544        {
2545            sp<AMessage> notify = mCodec->mNotify->dup();
2546            notify->setInt32("what", ACodec::kWhatFlushCompleted);
2547            notify->post();
2548
2549            handled = true;
2550            break;
2551        }
2552
2553        default:
2554            return BaseState::onMessageReceived(msg);
2555    }
2556
2557    return handled;
2558}
2559
2560void ACodec::UninitializedState::onSetup(
2561        const sp<AMessage> &msg) {
2562    onAllocateComponent(msg);
2563    onConfigureComponent(msg);
2564    onStart();
2565}
2566
2567void ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
2568    ALOGV("onAllocateComponent");
2569
2570    if (mCodec->mNode != NULL) {
2571        CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
2572
2573        mCodec->mNativeWindow.clear();
2574        mCodec->mNode = NULL;
2575        mCodec->mOMX.clear();
2576        mCodec->mComponentName.clear();
2577    }
2578
2579    OMXClient client;
2580    CHECK_EQ(client.connect(), (status_t)OK);
2581
2582    sp<IOMX> omx = client.interface();
2583
2584    Vector<String8> matchingCodecs;
2585
2586    AString mime;
2587
2588    AString componentName;
2589    if (msg->findString("componentName", &componentName)) {
2590        matchingCodecs.push_back(String8(componentName.c_str()));
2591    } else {
2592        CHECK(msg->findString("mime", &mime));
2593
2594        int32_t encoder;
2595        if (!msg->findInt32("encoder", &encoder)) {
2596            encoder = false;
2597        }
2598
2599        OMXCodec::findMatchingCodecs(
2600                mime.c_str(),
2601                encoder, // createEncoder
2602                NULL,  // matchComponentName
2603                0,     // flags
2604                &matchingCodecs);
2605    }
2606
2607    sp<CodecObserver> observer = new CodecObserver;
2608    IOMX::node_id node = NULL;
2609
2610    for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
2611            ++matchIndex) {
2612        componentName = matchingCodecs.itemAt(matchIndex).string();
2613
2614        pid_t tid = androidGetTid();
2615        int prevPriority = androidGetThreadPriority(tid);
2616        androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
2617        status_t err = omx->allocateNode(componentName.c_str(), observer, &node);
2618        androidSetThreadPriority(tid, prevPriority);
2619
2620        if (err == OK) {
2621            break;
2622        }
2623
2624        node = NULL;
2625    }
2626
2627    if (node == NULL) {
2628        if (!mime.empty()) {
2629            ALOGE("Unable to instantiate a decoder for type '%s'.",
2630                 mime.c_str());
2631        } else {
2632            ALOGE("Unable to instantiate decoder '%s'.", componentName.c_str());
2633        }
2634
2635        mCodec->signalError(OMX_ErrorComponentNotFound);
2636        return;
2637    }
2638
2639    sp<AMessage> notify = new AMessage(kWhatOMXMessage, mCodec->id());
2640    observer->setNotificationMessage(notify);
2641
2642    mCodec->mComponentName = componentName;
2643    mCodec->mOMX = omx;
2644    mCodec->mNode = node;
2645
2646    mCodec->mPortEOS[kPortIndexInput] =
2647        mCodec->mPortEOS[kPortIndexOutput] = false;
2648
2649    mCodec->mInputEOSResult = OK;
2650
2651    {
2652        sp<AMessage> notify = mCodec->mNotify->dup();
2653        notify->setInt32("what", ACodec::kWhatComponentAllocated);
2654        notify->setString("componentName", mCodec->mComponentName.c_str());
2655        notify->post();
2656    }
2657}
2658
2659void ACodec::UninitializedState::onConfigureComponent(
2660        const sp<AMessage> &msg) {
2661    ALOGV("onConfigureComponent");
2662
2663    CHECK(mCodec->mNode != NULL);
2664
2665    AString mime;
2666    CHECK(msg->findString("mime", &mime));
2667
2668    status_t err = mCodec->configureCodec(mime.c_str(), msg);
2669
2670    if (err != OK) {
2671        mCodec->signalError(OMX_ErrorUndefined, err);
2672        return;
2673    }
2674
2675    sp<RefBase> obj;
2676    if (msg->findObject("native-window", &obj)
2677            && strncmp("OMX.google.", mCodec->mComponentName.c_str(), 11)) {
2678        sp<NativeWindowWrapper> nativeWindow(
2679                static_cast<NativeWindowWrapper *>(obj.get()));
2680        CHECK(nativeWindow != NULL);
2681        mCodec->mNativeWindow = nativeWindow->getNativeWindow();
2682    }
2683    CHECK_EQ((status_t)OK, mCodec->initNativeWindow());
2684
2685    {
2686        sp<AMessage> notify = mCodec->mNotify->dup();
2687        notify->setInt32("what", ACodec::kWhatComponentConfigured);
2688        notify->post();
2689    }
2690}
2691
2692void ACodec::UninitializedState::onStart() {
2693    ALOGV("onStart");
2694
2695    CHECK_EQ(mCodec->mOMX->sendCommand(
2696                mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
2697             (status_t)OK);
2698
2699    mCodec->changeState(mCodec->mLoadedToIdleState);
2700}
2701
2702////////////////////////////////////////////////////////////////////////////////
2703
2704ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec)
2705    : BaseState(codec) {
2706}
2707
2708void ACodec::LoadedToIdleState::stateEntered() {
2709    ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
2710
2711    status_t err;
2712    if ((err = allocateBuffers()) != OK) {
2713        ALOGE("Failed to allocate buffers after transitioning to IDLE state "
2714             "(error 0x%08x)",
2715             err);
2716
2717        mCodec->signalError(OMX_ErrorUndefined, err);
2718    }
2719}
2720
2721status_t ACodec::LoadedToIdleState::allocateBuffers() {
2722    status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput);
2723
2724    if (err != OK) {
2725        return err;
2726    }
2727
2728    return mCodec->allocateBuffersOnPort(kPortIndexOutput);
2729}
2730
2731bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
2732    switch (msg->what()) {
2733        case kWhatShutdown:
2734        {
2735            mCodec->deferMessage(msg);
2736            return true;
2737        }
2738
2739        default:
2740            return BaseState::onMessageReceived(msg);
2741    }
2742}
2743
2744bool ACodec::LoadedToIdleState::onOMXEvent(
2745        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2746    switch (event) {
2747        case OMX_EventCmdComplete:
2748        {
2749            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
2750            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
2751
2752            CHECK_EQ(mCodec->mOMX->sendCommand(
2753                        mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting),
2754                     (status_t)OK);
2755
2756            mCodec->changeState(mCodec->mIdleToExecutingState);
2757
2758            return true;
2759        }
2760
2761        default:
2762            return BaseState::onOMXEvent(event, data1, data2);
2763    }
2764}
2765
2766////////////////////////////////////////////////////////////////////////////////
2767
2768ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec)
2769    : BaseState(codec) {
2770}
2771
2772void ACodec::IdleToExecutingState::stateEntered() {
2773    ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
2774}
2775
2776bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
2777    switch (msg->what()) {
2778        case kWhatShutdown:
2779        {
2780            mCodec->deferMessage(msg);
2781            return true;
2782        }
2783
2784        default:
2785            return BaseState::onMessageReceived(msg);
2786    }
2787}
2788
2789bool ACodec::IdleToExecutingState::onOMXEvent(
2790        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2791    switch (event) {
2792        case OMX_EventCmdComplete:
2793        {
2794            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
2795            CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting);
2796
2797            mCodec->mExecutingState->resume();
2798            mCodec->changeState(mCodec->mExecutingState);
2799
2800            return true;
2801        }
2802
2803        default:
2804            return BaseState::onOMXEvent(event, data1, data2);
2805    }
2806}
2807
2808////////////////////////////////////////////////////////////////////////////////
2809
2810ACodec::ExecutingState::ExecutingState(ACodec *codec)
2811    : BaseState(codec),
2812      mActive(false) {
2813}
2814
2815ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode(
2816        OMX_U32 portIndex) {
2817    return RESUBMIT_BUFFERS;
2818}
2819
2820void ACodec::ExecutingState::submitOutputBuffers() {
2821    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
2822        BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
2823
2824        if (mCodec->mNativeWindow != NULL) {
2825            CHECK(info->mStatus == BufferInfo::OWNED_BY_US
2826                    || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
2827
2828            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
2829                continue;
2830            }
2831
2832            status_t err = mCodec->mNativeWindow->lockBuffer(
2833                    mCodec->mNativeWindow.get(),
2834                    info->mGraphicBuffer.get());
2835            CHECK_EQ(err, (status_t)OK);
2836        } else {
2837            CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
2838        }
2839
2840        ALOGV("[%s] calling fillBuffer %p",
2841             mCodec->mComponentName.c_str(), info->mBufferID);
2842
2843        CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
2844                 (status_t)OK);
2845
2846        info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
2847    }
2848}
2849
2850void ACodec::ExecutingState::resume() {
2851    if (mActive) {
2852        ALOGV("[%s] We're already active, no need to resume.",
2853             mCodec->mComponentName.c_str());
2854
2855        return;
2856    }
2857
2858    submitOutputBuffers();
2859
2860    // Post the first input buffer.
2861    CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u);
2862    BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(0);
2863
2864    postFillThisBuffer(info);
2865
2866    mActive = true;
2867}
2868
2869void ACodec::ExecutingState::stateEntered() {
2870    ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
2871
2872    mCodec->processDeferredMessages();
2873}
2874
2875bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) {
2876    bool handled = false;
2877
2878    switch (msg->what()) {
2879        case kWhatShutdown:
2880        {
2881            mActive = false;
2882
2883            CHECK_EQ(mCodec->mOMX->sendCommand(
2884                        mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
2885                     (status_t)OK);
2886
2887            mCodec->changeState(mCodec->mExecutingToIdleState);
2888
2889            handled = true;
2890            break;
2891        }
2892
2893        case kWhatFlush:
2894        {
2895            ALOGV("[%s] ExecutingState flushing now "
2896                 "(codec owns %d/%d input, %d/%d output).",
2897                    mCodec->mComponentName.c_str(),
2898                    mCodec->countBuffersOwnedByComponent(kPortIndexInput),
2899                    mCodec->mBuffers[kPortIndexInput].size(),
2900                    mCodec->countBuffersOwnedByComponent(kPortIndexOutput),
2901                    mCodec->mBuffers[kPortIndexOutput].size());
2902
2903            mActive = false;
2904
2905            CHECK_EQ(mCodec->mOMX->sendCommand(
2906                        mCodec->mNode, OMX_CommandFlush, OMX_ALL),
2907                     (status_t)OK);
2908
2909            mCodec->changeState(mCodec->mFlushingState);
2910
2911            handled = true;
2912            break;
2913        }
2914
2915        case kWhatResume:
2916        {
2917            resume();
2918
2919            handled = true;
2920            break;
2921        }
2922
2923        default:
2924            handled = BaseState::onMessageReceived(msg);
2925            break;
2926    }
2927
2928    return handled;
2929}
2930
2931bool ACodec::ExecutingState::onOMXEvent(
2932        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2933    switch (event) {
2934        case OMX_EventPortSettingsChanged:
2935        {
2936            CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
2937
2938            if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
2939                CHECK_EQ(mCodec->mOMX->sendCommand(
2940                            mCodec->mNode,
2941                            OMX_CommandPortDisable, kPortIndexOutput),
2942                         (status_t)OK);
2943
2944                mCodec->freeOutputBuffersNotOwnedByComponent();
2945
2946                mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
2947            } else if (data2 == OMX_IndexConfigCommonOutputCrop) {
2948                mCodec->mSentFormat = false;
2949            } else {
2950                ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx",
2951                     mCodec->mComponentName.c_str(), data2);
2952            }
2953
2954            return true;
2955        }
2956
2957        case OMX_EventBufferFlag:
2958        {
2959            return true;
2960        }
2961
2962        default:
2963            return BaseState::onOMXEvent(event, data1, data2);
2964    }
2965}
2966
2967////////////////////////////////////////////////////////////////////////////////
2968
2969ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState(
2970        ACodec *codec)
2971    : BaseState(codec) {
2972}
2973
2974ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode(
2975        OMX_U32 portIndex) {
2976    if (portIndex == kPortIndexOutput) {
2977        return FREE_BUFFERS;
2978    }
2979
2980    CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput);
2981
2982    return RESUBMIT_BUFFERS;
2983}
2984
2985bool ACodec::OutputPortSettingsChangedState::onMessageReceived(
2986        const sp<AMessage> &msg) {
2987    bool handled = false;
2988
2989    switch (msg->what()) {
2990        case kWhatFlush:
2991        case kWhatShutdown:
2992        case kWhatResume:
2993        {
2994            if (msg->what() == kWhatResume) {
2995                ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
2996            }
2997
2998            mCodec->deferMessage(msg);
2999            handled = true;
3000            break;
3001        }
3002
3003        default:
3004            handled = BaseState::onMessageReceived(msg);
3005            break;
3006    }
3007
3008    return handled;
3009}
3010
3011void ACodec::OutputPortSettingsChangedState::stateEntered() {
3012    ALOGV("[%s] Now handling output port settings change",
3013         mCodec->mComponentName.c_str());
3014}
3015
3016bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
3017        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3018    switch (event) {
3019        case OMX_EventCmdComplete:
3020        {
3021            if (data1 == (OMX_U32)OMX_CommandPortDisable) {
3022                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
3023
3024                ALOGV("[%s] Output port now disabled.",
3025                        mCodec->mComponentName.c_str());
3026
3027                CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty());
3028                mCodec->mDealer[kPortIndexOutput].clear();
3029
3030                CHECK_EQ(mCodec->mOMX->sendCommand(
3031                            mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput),
3032                         (status_t)OK);
3033
3034                status_t err;
3035                if ((err = mCodec->allocateBuffersOnPort(
3036                                kPortIndexOutput)) != OK) {
3037                    ALOGE("Failed to allocate output port buffers after "
3038                         "port reconfiguration (error 0x%08x)",
3039                         err);
3040
3041                    mCodec->signalError(OMX_ErrorUndefined, err);
3042
3043                    // This is technically not correct, since we were unable
3044                    // to allocate output buffers and therefore the output port
3045                    // remains disabled. It is necessary however to allow us
3046                    // to shutdown the codec properly.
3047                    mCodec->changeState(mCodec->mExecutingState);
3048                }
3049
3050                return true;
3051            } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
3052                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
3053
3054                mCodec->mSentFormat = false;
3055
3056                ALOGV("[%s] Output port now reenabled.",
3057                        mCodec->mComponentName.c_str());
3058
3059                if (mCodec->mExecutingState->active()) {
3060                    mCodec->mExecutingState->submitOutputBuffers();
3061                }
3062
3063                mCodec->changeState(mCodec->mExecutingState);
3064
3065                return true;
3066            }
3067
3068            return false;
3069        }
3070
3071        default:
3072            return false;
3073    }
3074}
3075
3076////////////////////////////////////////////////////////////////////////////////
3077
3078ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec)
3079    : BaseState(codec),
3080      mComponentNowIdle(false) {
3081}
3082
3083bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) {
3084    bool handled = false;
3085
3086    switch (msg->what()) {
3087        case kWhatFlush:
3088        {
3089            // Don't send me a flush request if you previously wanted me
3090            // to shutdown.
3091            TRESPASS();
3092            break;
3093        }
3094
3095        case kWhatShutdown:
3096        {
3097            // We're already doing that...
3098
3099            handled = true;
3100            break;
3101        }
3102
3103        default:
3104            handled = BaseState::onMessageReceived(msg);
3105            break;
3106    }
3107
3108    return handled;
3109}
3110
3111void ACodec::ExecutingToIdleState::stateEntered() {
3112    ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
3113
3114    mComponentNowIdle = false;
3115    mCodec->mSentFormat = false;
3116}
3117
3118bool ACodec::ExecutingToIdleState::onOMXEvent(
3119        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3120    switch (event) {
3121        case OMX_EventCmdComplete:
3122        {
3123            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
3124            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
3125
3126            mComponentNowIdle = true;
3127
3128            changeStateIfWeOwnAllBuffers();
3129
3130            return true;
3131        }
3132
3133        case OMX_EventPortSettingsChanged:
3134        case OMX_EventBufferFlag:
3135        {
3136            // We're shutting down and don't care about this anymore.
3137            return true;
3138        }
3139
3140        default:
3141            return BaseState::onOMXEvent(event, data1, data2);
3142    }
3143}
3144
3145void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
3146    if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) {
3147        CHECK_EQ(mCodec->mOMX->sendCommand(
3148                    mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded),
3149                 (status_t)OK);
3150
3151        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK);
3152        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK);
3153
3154        mCodec->changeState(mCodec->mIdleToLoadedState);
3155    }
3156}
3157
3158void ACodec::ExecutingToIdleState::onInputBufferFilled(
3159        const sp<AMessage> &msg) {
3160    BaseState::onInputBufferFilled(msg);
3161
3162    changeStateIfWeOwnAllBuffers();
3163}
3164
3165void ACodec::ExecutingToIdleState::onOutputBufferDrained(
3166        const sp<AMessage> &msg) {
3167    BaseState::onOutputBufferDrained(msg);
3168
3169    changeStateIfWeOwnAllBuffers();
3170}
3171
3172////////////////////////////////////////////////////////////////////////////////
3173
3174ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec)
3175    : BaseState(codec) {
3176}
3177
3178bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) {
3179    bool handled = false;
3180
3181    switch (msg->what()) {
3182        case kWhatShutdown:
3183        {
3184            // We're already doing that...
3185
3186            handled = true;
3187            break;
3188        }
3189
3190        case kWhatFlush:
3191        {
3192            // Don't send me a flush request if you previously wanted me
3193            // to shutdown.
3194            TRESPASS();
3195            break;
3196        }
3197
3198        default:
3199            handled = BaseState::onMessageReceived(msg);
3200            break;
3201    }
3202
3203    return handled;
3204}
3205
3206void ACodec::IdleToLoadedState::stateEntered() {
3207    ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
3208}
3209
3210bool ACodec::IdleToLoadedState::onOMXEvent(
3211        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3212    switch (event) {
3213        case OMX_EventCmdComplete:
3214        {
3215            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
3216            CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded);
3217
3218            ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
3219
3220            CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
3221
3222            mCodec->mNativeWindow.clear();
3223            mCodec->mNode = NULL;
3224            mCodec->mOMX.clear();
3225            mCodec->mComponentName.clear();
3226
3227            mCodec->changeState(mCodec->mUninitializedState);
3228
3229            sp<AMessage> notify = mCodec->mNotify->dup();
3230            notify->setInt32("what", ACodec::kWhatShutdownCompleted);
3231            notify->post();
3232
3233            return true;
3234        }
3235
3236        default:
3237            return BaseState::onOMXEvent(event, data1, data2);
3238    }
3239}
3240
3241////////////////////////////////////////////////////////////////////////////////
3242
3243ACodec::FlushingState::FlushingState(ACodec *codec)
3244    : BaseState(codec) {
3245}
3246
3247void ACodec::FlushingState::stateEntered() {
3248    ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());
3249
3250    mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
3251}
3252
3253bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) {
3254    bool handled = false;
3255
3256    switch (msg->what()) {
3257        case kWhatShutdown:
3258        {
3259            mCodec->deferMessage(msg);
3260            break;
3261        }
3262
3263        case kWhatFlush:
3264        {
3265            // We're already doing this right now.
3266            handled = true;
3267            break;
3268        }
3269
3270        default:
3271            handled = BaseState::onMessageReceived(msg);
3272            break;
3273    }
3274
3275    return handled;
3276}
3277
3278bool ACodec::FlushingState::onOMXEvent(
3279        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3280    ALOGV("[%s] FlushingState onOMXEvent(%d,%ld)",
3281            mCodec->mComponentName.c_str(), event, data1);
3282
3283    switch (event) {
3284        case OMX_EventCmdComplete:
3285        {
3286            CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush);
3287
3288            if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
3289                CHECK(!mFlushComplete[data2]);
3290                mFlushComplete[data2] = true;
3291
3292                if (mFlushComplete[kPortIndexInput]
3293                        && mFlushComplete[kPortIndexOutput]) {
3294                    changeStateIfWeOwnAllBuffers();
3295                }
3296            } else {
3297                CHECK_EQ(data2, OMX_ALL);
3298                CHECK(mFlushComplete[kPortIndexInput]);
3299                CHECK(mFlushComplete[kPortIndexOutput]);
3300
3301                changeStateIfWeOwnAllBuffers();
3302            }
3303
3304            return true;
3305        }
3306
3307        case OMX_EventPortSettingsChanged:
3308        {
3309            sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id());
3310            msg->setInt32("type", omx_message::EVENT);
3311            msg->setPointer("node", mCodec->mNode);
3312            msg->setInt32("event", event);
3313            msg->setInt32("data1", data1);
3314            msg->setInt32("data2", data2);
3315
3316            ALOGV("[%s] Deferring OMX_EventPortSettingsChanged",
3317                 mCodec->mComponentName.c_str());
3318
3319            mCodec->deferMessage(msg);
3320
3321            return true;
3322        }
3323
3324        default:
3325            return BaseState::onOMXEvent(event, data1, data2);
3326    }
3327
3328    return true;
3329}
3330
3331void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) {
3332    BaseState::onOutputBufferDrained(msg);
3333
3334    changeStateIfWeOwnAllBuffers();
3335}
3336
3337void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) {
3338    BaseState::onInputBufferFilled(msg);
3339
3340    changeStateIfWeOwnAllBuffers();
3341}
3342
3343void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() {
3344    if (mFlushComplete[kPortIndexInput]
3345            && mFlushComplete[kPortIndexOutput]
3346            && mCodec->allYourBuffersAreBelongToUs()) {
3347        sp<AMessage> notify = mCodec->mNotify->dup();
3348        notify->setInt32("what", ACodec::kWhatFlushCompleted);
3349        notify->post();
3350
3351        mCodec->mPortEOS[kPortIndexInput] =
3352            mCodec->mPortEOS[kPortIndexOutput] = false;
3353
3354        mCodec->mInputEOSResult = OK;
3355
3356        mCodec->changeState(mCodec->mExecutingState);
3357    }
3358}
3359
3360}  // namespace android
3361