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