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