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