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