ACodec.cpp revision 59e7879a8482284a434268d51b4b438f0625d1be
1//#define LOG_NDEBUG 0
2#define LOG_TAG "ACodec"
3
4#include <media/stagefright/ACodec.h>
5
6#include <binder/MemoryDealer.h>
7
8#include <media/stagefright/foundation/hexdump.h>
9#include <media/stagefright/foundation/ABuffer.h>
10#include <media/stagefright/foundation/ADebug.h>
11#include <media/stagefright/foundation/AMessage.h>
12
13#include <media/stagefright/MediaDefs.h>
14#include <media/stagefright/NativeWindowWrapper.h>
15#include <media/stagefright/OMXClient.h>
16
17#include <surfaceflinger/Surface.h>
18#include <gui/SurfaceTextureClient.h>
19
20#include <OMX_Component.h>
21
22namespace android {
23
24template<class T>
25static void InitOMXParams(T *params) {
26    params->nSize = sizeof(T);
27    params->nVersion.s.nVersionMajor = 1;
28    params->nVersion.s.nVersionMinor = 0;
29    params->nVersion.s.nRevision = 0;
30    params->nVersion.s.nStep = 0;
31}
32
33struct CodecObserver : public BnOMXObserver {
34    CodecObserver() {}
35
36    void setNotificationMessage(const sp<AMessage> &msg) {
37        mNotify = msg;
38    }
39
40    // from IOMXObserver
41    virtual void onMessage(const omx_message &omx_msg) {
42        sp<AMessage> msg = mNotify->dup();
43
44        msg->setInt32("type", omx_msg.type);
45        msg->setPointer("node", omx_msg.node);
46
47        switch (omx_msg.type) {
48            case omx_message::EVENT:
49            {
50                msg->setInt32("event", omx_msg.u.event_data.event);
51                msg->setInt32("data1", omx_msg.u.event_data.data1);
52                msg->setInt32("data2", omx_msg.u.event_data.data2);
53                break;
54            }
55
56            case omx_message::EMPTY_BUFFER_DONE:
57            {
58                msg->setPointer("buffer", omx_msg.u.buffer_data.buffer);
59                break;
60            }
61
62            case omx_message::FILL_BUFFER_DONE:
63            {
64                msg->setPointer(
65                        "buffer", omx_msg.u.extended_buffer_data.buffer);
66                msg->setInt32(
67                        "range_offset",
68                        omx_msg.u.extended_buffer_data.range_offset);
69                msg->setInt32(
70                        "range_length",
71                        omx_msg.u.extended_buffer_data.range_length);
72                msg->setInt32(
73                        "flags",
74                        omx_msg.u.extended_buffer_data.flags);
75                msg->setInt64(
76                        "timestamp",
77                        omx_msg.u.extended_buffer_data.timestamp);
78                msg->setPointer(
79                        "platform_private",
80                        omx_msg.u.extended_buffer_data.platform_private);
81                msg->setPointer(
82                        "data_ptr",
83                        omx_msg.u.extended_buffer_data.data_ptr);
84                break;
85            }
86
87            default:
88                TRESPASS();
89                break;
90        }
91
92        msg->post();
93    }
94
95protected:
96    virtual ~CodecObserver() {}
97
98private:
99    sp<AMessage> mNotify;
100
101    DISALLOW_EVIL_CONSTRUCTORS(CodecObserver);
102};
103
104////////////////////////////////////////////////////////////////////////////////
105
106struct ACodec::BaseState : public AState {
107    BaseState(ACodec *codec, const sp<AState> &parentState = NULL);
108
109protected:
110    enum PortMode {
111        KEEP_BUFFERS,
112        RESUBMIT_BUFFERS,
113        FREE_BUFFERS,
114    };
115
116    ACodec *mCodec;
117
118    virtual PortMode getPortMode(OMX_U32 portIndex);
119
120    virtual bool onMessageReceived(const sp<AMessage> &msg);
121
122    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
123
124    virtual void onOutputBufferDrained(const sp<AMessage> &msg);
125    virtual void onInputBufferFilled(const sp<AMessage> &msg);
126
127    void postFillThisBuffer(BufferInfo *info);
128
129private:
130    bool onOMXMessage(const sp<AMessage> &msg);
131
132    bool onOMXEmptyBufferDone(IOMX::buffer_id bufferID);
133
134    bool onOMXFillBufferDone(
135            IOMX::buffer_id bufferID,
136            size_t rangeOffset, size_t rangeLength,
137            OMX_U32 flags,
138            int64_t timeUs,
139            void *platformPrivate,
140            void *dataPtr);
141
142    void getMoreInputDataIfPossible();
143
144    DISALLOW_EVIL_CONSTRUCTORS(BaseState);
145};
146
147////////////////////////////////////////////////////////////////////////////////
148
149struct ACodec::UninitializedState : public ACodec::BaseState {
150    UninitializedState(ACodec *codec);
151
152protected:
153    virtual bool onMessageReceived(const sp<AMessage> &msg);
154
155private:
156    void onSetup(const sp<AMessage> &msg);
157
158    DISALLOW_EVIL_CONSTRUCTORS(UninitializedState);
159};
160
161////////////////////////////////////////////////////////////////////////////////
162
163struct ACodec::LoadedToIdleState : public ACodec::BaseState {
164    LoadedToIdleState(ACodec *codec);
165
166protected:
167    virtual bool onMessageReceived(const sp<AMessage> &msg);
168    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
169    virtual void stateEntered();
170
171private:
172    status_t allocateBuffers();
173
174    DISALLOW_EVIL_CONSTRUCTORS(LoadedToIdleState);
175};
176
177////////////////////////////////////////////////////////////////////////////////
178
179struct ACodec::IdleToExecutingState : public ACodec::BaseState {
180    IdleToExecutingState(ACodec *codec);
181
182protected:
183    virtual bool onMessageReceived(const sp<AMessage> &msg);
184    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
185    virtual void stateEntered();
186
187private:
188    DISALLOW_EVIL_CONSTRUCTORS(IdleToExecutingState);
189};
190
191////////////////////////////////////////////////////////////////////////////////
192
193struct ACodec::ExecutingState : public ACodec::BaseState {
194    ExecutingState(ACodec *codec);
195
196    void submitOutputBuffers();
197
198    // Submit output buffers to the decoder, submit input buffers to client
199    // to fill with data.
200    void resume();
201
202    // Returns true iff input and output buffers are in play.
203    bool active() const { return mActive; }
204
205protected:
206    virtual PortMode getPortMode(OMX_U32 portIndex);
207    virtual bool onMessageReceived(const sp<AMessage> &msg);
208    virtual void stateEntered();
209
210    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
211
212private:
213    bool mActive;
214
215    DISALLOW_EVIL_CONSTRUCTORS(ExecutingState);
216};
217
218////////////////////////////////////////////////////////////////////////////////
219
220struct ACodec::OutputPortSettingsChangedState : public ACodec::BaseState {
221    OutputPortSettingsChangedState(ACodec *codec);
222
223protected:
224    virtual PortMode getPortMode(OMX_U32 portIndex);
225    virtual bool onMessageReceived(const sp<AMessage> &msg);
226    virtual void stateEntered();
227
228    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
229
230private:
231    DISALLOW_EVIL_CONSTRUCTORS(OutputPortSettingsChangedState);
232};
233
234////////////////////////////////////////////////////////////////////////////////
235
236struct ACodec::ExecutingToIdleState : public ACodec::BaseState {
237    ExecutingToIdleState(ACodec *codec);
238
239protected:
240    virtual bool onMessageReceived(const sp<AMessage> &msg);
241    virtual void stateEntered();
242
243    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
244
245    virtual void onOutputBufferDrained(const sp<AMessage> &msg);
246    virtual void onInputBufferFilled(const sp<AMessage> &msg);
247
248private:
249    void changeStateIfWeOwnAllBuffers();
250
251    DISALLOW_EVIL_CONSTRUCTORS(ExecutingToIdleState);
252};
253
254////////////////////////////////////////////////////////////////////////////////
255
256struct ACodec::IdleToLoadedState : public ACodec::BaseState {
257    IdleToLoadedState(ACodec *codec);
258
259protected:
260    virtual bool onMessageReceived(const sp<AMessage> &msg);
261    virtual void stateEntered();
262
263    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
264
265private:
266    DISALLOW_EVIL_CONSTRUCTORS(IdleToLoadedState);
267};
268
269////////////////////////////////////////////////////////////////////////////////
270
271struct ACodec::ErrorState : public ACodec::BaseState {
272    ErrorState(ACodec *codec);
273
274protected:
275    virtual bool onMessageReceived(const sp<AMessage> &msg);
276    virtual void stateEntered();
277
278    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
279
280private:
281    DISALLOW_EVIL_CONSTRUCTORS(ErrorState);
282};
283
284////////////////////////////////////////////////////////////////////////////////
285
286struct ACodec::FlushingState : public ACodec::BaseState {
287    FlushingState(ACodec *codec);
288
289protected:
290    virtual bool onMessageReceived(const sp<AMessage> &msg);
291    virtual void stateEntered();
292
293    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
294
295    virtual void onOutputBufferDrained(const sp<AMessage> &msg);
296    virtual void onInputBufferFilled(const sp<AMessage> &msg);
297
298private:
299    bool mFlushComplete[2];
300
301    void changeStateIfWeOwnAllBuffers();
302
303    DISALLOW_EVIL_CONSTRUCTORS(FlushingState);
304};
305
306////////////////////////////////////////////////////////////////////////////////
307
308ACodec::ACodec()
309    : mNode(NULL),
310      mSentFormat(false) {
311    mUninitializedState = new UninitializedState(this);
312    mLoadedToIdleState = new LoadedToIdleState(this);
313    mIdleToExecutingState = new IdleToExecutingState(this);
314    mExecutingState = new ExecutingState(this);
315
316    mOutputPortSettingsChangedState =
317        new OutputPortSettingsChangedState(this);
318
319    mExecutingToIdleState = new ExecutingToIdleState(this);
320    mIdleToLoadedState = new IdleToLoadedState(this);
321    mErrorState = new ErrorState(this);
322    mFlushingState = new FlushingState(this);
323
324    mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false;
325
326    changeState(mUninitializedState);
327}
328
329ACodec::~ACodec() {
330}
331
332void ACodec::setNotificationMessage(const sp<AMessage> &msg) {
333    mNotify = msg;
334}
335
336void ACodec::initiateSetup(const sp<AMessage> &msg) {
337    msg->setWhat(kWhatSetup);
338    msg->setTarget(id());
339    msg->post();
340}
341
342void ACodec::signalFlush() {
343    (new AMessage(kWhatFlush, id()))->post();
344}
345
346void ACodec::signalResume() {
347    (new AMessage(kWhatResume, id()))->post();
348}
349
350void ACodec::initiateShutdown() {
351    (new AMessage(kWhatShutdown, id()))->post();
352}
353
354status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) {
355    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
356
357    CHECK(mDealer[portIndex] == NULL);
358    CHECK(mBuffers[portIndex].isEmpty());
359
360    if (mNativeWindow != NULL && portIndex == kPortIndexOutput) {
361        return allocateOutputBuffersFromNativeWindow();
362    }
363
364    OMX_PARAM_PORTDEFINITIONTYPE def;
365    InitOMXParams(&def);
366    def.nPortIndex = portIndex;
367
368    status_t err = mOMX->getParameter(
369            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
370
371    if (err != OK) {
372        return err;
373    }
374
375    LOGV("[%s] Allocating %lu buffers of size %lu on %s port",
376            mComponentName.c_str(),
377            def.nBufferCountActual, def.nBufferSize,
378            portIndex == kPortIndexInput ? "input" : "output");
379
380    size_t totalSize = def.nBufferCountActual * def.nBufferSize;
381    mDealer[portIndex] = new MemoryDealer(totalSize, "OMXCodec");
382
383    for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
384        sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
385        CHECK(mem.get() != NULL);
386
387        IOMX::buffer_id buffer;
388#if 0
389        err = mOMX->allocateBufferWithBackup(mNode, portIndex, mem, &buffer);
390#else
391        err = mOMX->useBuffer(mNode, portIndex, mem, &buffer);
392#endif
393
394        if (err != OK) {
395            return err;
396        }
397
398        BufferInfo info;
399        info.mBufferID = buffer;
400        info.mStatus = BufferInfo::OWNED_BY_US;
401        info.mData = new ABuffer(mem->pointer(), def.nBufferSize);
402        mBuffers[portIndex].push(info);
403    }
404
405    return OK;
406}
407
408status_t ACodec::allocateOutputBuffersFromNativeWindow() {
409    OMX_PARAM_PORTDEFINITIONTYPE def;
410    InitOMXParams(&def);
411    def.nPortIndex = kPortIndexOutput;
412
413    status_t err = mOMX->getParameter(
414            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
415
416    if (err != OK) {
417        return err;
418    }
419
420    err = native_window_set_buffers_geometry(
421            mNativeWindow.get(),
422            def.format.video.nFrameWidth,
423            def.format.video.nFrameHeight,
424            def.format.video.eColorFormat);
425
426    if (err != 0) {
427        LOGE("native_window_set_buffers_geometry failed: %s (%d)",
428                strerror(-err), -err);
429        return err;
430    }
431
432    // Increase the buffer count by one to allow for the ANativeWindow to hold
433    // on to one of the buffers.
434    def.nBufferCountActual++;
435    err = mOMX->setParameter(
436            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
437
438    if (err != OK) {
439        return err;
440    }
441
442    // Set up the native window.
443    OMX_U32 usage = 0;
444    err = mOMX->getGraphicBufferUsage(mNode, kPortIndexOutput, &usage);
445    if (err != 0) {
446        LOGW("querying usage flags from OMX IL component failed: %d", err);
447        // XXX: Currently this error is logged, but not fatal.
448        usage = 0;
449    }
450
451    err = native_window_set_usage(
452            mNativeWindow.get(),
453            usage | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP);
454
455    if (err != 0) {
456        LOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err);
457        return err;
458    }
459
460    err = native_window_set_buffer_count(
461            mNativeWindow.get(), def.nBufferCountActual);
462
463    if (err != 0) {
464        LOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err),
465                -err);
466        return err;
467    }
468
469    LOGV("[%s] Allocating %lu buffers from a native window of size %lu on "
470         "output port",
471         mComponentName.c_str(), def.nBufferCountActual, def.nBufferSize);
472
473    // Dequeue buffers and send them to OMX
474    for (OMX_U32 i = 0; i < def.nBufferCountActual; i++) {
475        android_native_buffer_t *buf;
476        err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf);
477        if (err != 0) {
478            LOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
479            break;
480        }
481
482        sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false));
483        BufferInfo info;
484        info.mStatus = BufferInfo::OWNED_BY_US;
485        info.mData = new ABuffer(0);
486        info.mGraphicBuffer = graphicBuffer;
487        mBuffers[kPortIndexOutput].push(info);
488
489        IOMX::buffer_id bufferId;
490        err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer,
491                &bufferId);
492        if (err != 0) {
493            LOGE("registering GraphicBuffer %lu with OMX IL component failed: "
494                 "%d", i, err);
495            break;
496        }
497
498        mBuffers[kPortIndexOutput].editItemAt(i).mBufferID = bufferId;
499
500        LOGV("[%s] Registered graphic buffer with ID %p (pointer = %p)",
501             mComponentName.c_str(),
502             bufferId, graphicBuffer.get());
503    }
504
505    OMX_U32 cancelStart;
506    OMX_U32 cancelEnd;
507
508    if (err != 0) {
509        // If an error occurred while dequeuing we need to cancel any buffers
510        // that were dequeued.
511        cancelStart = 0;
512        cancelEnd = mBuffers[kPortIndexOutput].size();
513    } else {
514        // Return the last two buffers to the native window.
515        // XXX TODO: The number of buffers the native window owns should
516        // probably be queried from it when we put the native window in
517        // fixed buffer pool mode (which needs to be implemented).
518        // Currently it's hard-coded to 2.
519        cancelStart = def.nBufferCountActual - 2;
520        cancelEnd = def.nBufferCountActual;
521    }
522
523    for (OMX_U32 i = cancelStart; i < cancelEnd; i++) {
524        BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
525        cancelBufferToNativeWindow(info);
526    }
527
528    return err;
529}
530
531status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) {
532    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
533
534    LOGV("[%s] Calling cancelBuffer on buffer %p",
535         mComponentName.c_str(), info->mBufferID);
536
537    int err = mNativeWindow->cancelBuffer(
538        mNativeWindow.get(), info->mGraphicBuffer.get());
539
540    CHECK_EQ(err, 0);
541
542    info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
543
544    return OK;
545}
546
547ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() {
548    android_native_buffer_t *buf;
549    CHECK_EQ(mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf), 0);
550
551    for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
552        BufferInfo *info =
553            &mBuffers[kPortIndexOutput].editItemAt(i);
554
555        if (info->mGraphicBuffer->handle == buf->handle) {
556            CHECK_EQ((int)info->mStatus,
557                     (int)BufferInfo::OWNED_BY_NATIVE_WINDOW);
558
559            info->mStatus = BufferInfo::OWNED_BY_US;
560
561            return info;
562        }
563    }
564
565    TRESPASS();
566
567    return NULL;
568}
569
570status_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) {
571    for (size_t i = mBuffers[portIndex].size(); i-- > 0;) {
572        CHECK_EQ((status_t)OK, freeBuffer(portIndex, i));
573    }
574
575    mDealer[portIndex].clear();
576
577    return OK;
578}
579
580status_t ACodec::freeOutputBuffersNotOwnedByComponent() {
581    for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
582        BufferInfo *info =
583            &mBuffers[kPortIndexOutput].editItemAt(i);
584
585        if (info->mStatus !=
586                BufferInfo::OWNED_BY_COMPONENT) {
587            // We shouldn't have sent out any buffers to the client at this
588            // point.
589            CHECK_NE((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
590
591            CHECK_EQ((status_t)OK, freeBuffer(kPortIndexOutput, i));
592        }
593    }
594
595    return OK;
596}
597
598status_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) {
599    BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
600
601    CHECK(info->mStatus == BufferInfo::OWNED_BY_US
602            || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
603
604    if (portIndex == kPortIndexOutput && mNativeWindow != NULL
605            && info->mStatus == BufferInfo::OWNED_BY_US) {
606        CHECK_EQ((status_t)OK, cancelBufferToNativeWindow(info));
607    }
608
609    CHECK_EQ(mOMX->freeBuffer(
610                mNode, portIndex, info->mBufferID),
611             (status_t)OK);
612
613    mBuffers[portIndex].removeAt(i);
614
615    return OK;
616}
617
618ACodec::BufferInfo *ACodec::findBufferByID(
619        uint32_t portIndex, IOMX::buffer_id bufferID,
620        ssize_t *index) {
621    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
622        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
623
624        if (info->mBufferID == bufferID) {
625            if (index != NULL) {
626                *index = i;
627            }
628            return info;
629        }
630    }
631
632    TRESPASS();
633
634    return NULL;
635}
636
637void ACodec::setComponentRole(
638        bool isEncoder, const char *mime) {
639    struct MimeToRole {
640        const char *mime;
641        const char *decoderRole;
642        const char *encoderRole;
643    };
644
645    static const MimeToRole kMimeToRole[] = {
646        { MEDIA_MIMETYPE_AUDIO_MPEG,
647            "audio_decoder.mp3", "audio_encoder.mp3" },
648        { MEDIA_MIMETYPE_AUDIO_AMR_NB,
649            "audio_decoder.amrnb", "audio_encoder.amrnb" },
650        { MEDIA_MIMETYPE_AUDIO_AMR_WB,
651            "audio_decoder.amrwb", "audio_encoder.amrwb" },
652        { MEDIA_MIMETYPE_AUDIO_AAC,
653            "audio_decoder.aac", "audio_encoder.aac" },
654        { MEDIA_MIMETYPE_VIDEO_AVC,
655            "video_decoder.avc", "video_encoder.avc" },
656        { MEDIA_MIMETYPE_VIDEO_MPEG4,
657            "video_decoder.mpeg4", "video_encoder.mpeg4" },
658        { MEDIA_MIMETYPE_VIDEO_H263,
659            "video_decoder.h263", "video_encoder.h263" },
660    };
661
662    static const size_t kNumMimeToRole =
663        sizeof(kMimeToRole) / sizeof(kMimeToRole[0]);
664
665    size_t i;
666    for (i = 0; i < kNumMimeToRole; ++i) {
667        if (!strcasecmp(mime, kMimeToRole[i].mime)) {
668            break;
669        }
670    }
671
672    if (i == kNumMimeToRole) {
673        return;
674    }
675
676    const char *role =
677        isEncoder ? kMimeToRole[i].encoderRole
678                  : kMimeToRole[i].decoderRole;
679
680    if (role != NULL) {
681        OMX_PARAM_COMPONENTROLETYPE roleParams;
682        InitOMXParams(&roleParams);
683
684        strncpy((char *)roleParams.cRole,
685                role, OMX_MAX_STRINGNAME_SIZE - 1);
686
687        roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
688
689        status_t err = mOMX->setParameter(
690                mNode, OMX_IndexParamStandardComponentRole,
691                &roleParams, sizeof(roleParams));
692
693        if (err != OK) {
694            LOGW("[%s] Failed to set standard component role '%s'.",
695                 mComponentName.c_str(), role);
696        }
697    }
698}
699
700void ACodec::configureCodec(
701        const char *mime, const sp<AMessage> &msg) {
702    setComponentRole(false /* isEncoder */, mime);
703
704    if (!strncasecmp(mime, "video/", 6)) {
705        int32_t width, height;
706        CHECK(msg->findInt32("width", &width));
707        CHECK(msg->findInt32("height", &height));
708
709        CHECK_EQ(setupVideoDecoder(mime, width, height),
710                 (status_t)OK);
711    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
712        int32_t numChannels, sampleRate;
713        CHECK(msg->findInt32("channel-count", &numChannels));
714        CHECK(msg->findInt32("sample-rate", &sampleRate));
715
716        CHECK_EQ(setupAACDecoder(numChannels, sampleRate), (status_t)OK);
717    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
718    } else {
719        TRESPASS();
720    }
721
722    int32_t maxInputSize;
723    if (msg->findInt32("max-input-size", &maxInputSize)) {
724        CHECK_EQ(setMinBufferSize(kPortIndexInput, (size_t)maxInputSize),
725                 (status_t)OK);
726    } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) {
727        CHECK_EQ(setMinBufferSize(kPortIndexInput, 8192),  // XXX
728                 (status_t)OK);
729    }
730}
731
732status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) {
733    OMX_PARAM_PORTDEFINITIONTYPE def;
734    InitOMXParams(&def);
735    def.nPortIndex = portIndex;
736
737    status_t err = mOMX->getParameter(
738            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
739
740    if (err != OK) {
741        return err;
742    }
743
744    if (def.nBufferSize >= size) {
745        return OK;
746    }
747
748    def.nBufferSize = size;
749
750    err = mOMX->setParameter(
751            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
752
753    if (err != OK) {
754        return err;
755    }
756
757    err = mOMX->getParameter(
758            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
759
760    if (err != OK) {
761        return err;
762    }
763
764    CHECK(def.nBufferSize >= size);
765
766    return OK;
767}
768
769status_t ACodec::setupAACDecoder(int32_t numChannels, int32_t sampleRate) {
770    OMX_AUDIO_PARAM_AACPROFILETYPE profile;
771    InitOMXParams(&profile);
772    profile.nPortIndex = kPortIndexInput;
773
774    status_t err = mOMX->getParameter(
775            mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
776
777    if (err != OK) {
778        return err;
779    }
780
781    profile.nChannels = numChannels;
782    profile.nSampleRate = sampleRate;
783    profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS;
784
785    err = mOMX->setParameter(
786            mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
787
788    return err;
789}
790
791status_t ACodec::setVideoPortFormatType(
792        OMX_U32 portIndex,
793        OMX_VIDEO_CODINGTYPE compressionFormat,
794        OMX_COLOR_FORMATTYPE colorFormat) {
795    OMX_VIDEO_PARAM_PORTFORMATTYPE format;
796    InitOMXParams(&format);
797    format.nPortIndex = portIndex;
798    format.nIndex = 0;
799    bool found = false;
800
801    OMX_U32 index = 0;
802    for (;;) {
803        format.nIndex = index;
804        status_t err = mOMX->getParameter(
805                mNode, OMX_IndexParamVideoPortFormat,
806                &format, sizeof(format));
807
808        if (err != OK) {
809            return err;
810        }
811
812        // The following assertion is violated by TI's video decoder.
813        // CHECK_EQ(format.nIndex, index);
814
815        if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) {
816            if (portIndex == kPortIndexInput
817                    && colorFormat == format.eColorFormat) {
818                // eCompressionFormat does not seem right.
819                found = true;
820                break;
821            }
822            if (portIndex == kPortIndexOutput
823                    && compressionFormat == format.eCompressionFormat) {
824                // eColorFormat does not seem right.
825                found = true;
826                break;
827            }
828        }
829
830        if (format.eCompressionFormat == compressionFormat
831            && format.eColorFormat == colorFormat) {
832            found = true;
833            break;
834        }
835
836        ++index;
837    }
838
839    if (!found) {
840        return UNKNOWN_ERROR;
841    }
842
843    status_t err = mOMX->setParameter(
844            mNode, OMX_IndexParamVideoPortFormat,
845            &format, sizeof(format));
846
847    return err;
848}
849
850status_t ACodec::setSupportedOutputFormat() {
851    OMX_VIDEO_PARAM_PORTFORMATTYPE format;
852    InitOMXParams(&format);
853    format.nPortIndex = kPortIndexOutput;
854    format.nIndex = 0;
855
856    status_t err = mOMX->getParameter(
857            mNode, OMX_IndexParamVideoPortFormat,
858            &format, sizeof(format));
859    CHECK_EQ(err, (status_t)OK);
860    CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused);
861
862    static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
863
864    CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar
865           || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
866           || format.eColorFormat == OMX_COLOR_FormatCbYCrY
867           || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar);
868
869    return mOMX->setParameter(
870            mNode, OMX_IndexParamVideoPortFormat,
871            &format, sizeof(format));
872}
873
874status_t ACodec::setupVideoDecoder(
875        const char *mime, int32_t width, int32_t height) {
876    OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused;
877    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
878        compressionFormat = OMX_VIDEO_CodingAVC;
879    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
880        compressionFormat = OMX_VIDEO_CodingMPEG4;
881    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
882        compressionFormat = OMX_VIDEO_CodingH263;
883    } else {
884        TRESPASS();
885    }
886
887    status_t err = setVideoPortFormatType(
888            kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
889
890    if (err != OK) {
891        return err;
892    }
893
894    err = setSupportedOutputFormat();
895
896    if (err != OK) {
897        return err;
898    }
899
900    err = setVideoFormatOnPort(
901            kPortIndexInput, width, height, compressionFormat);
902
903    if (err != OK) {
904        return err;
905    }
906
907    err = setVideoFormatOnPort(
908            kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused);
909
910    if (err != OK) {
911        return err;
912    }
913
914    return OK;
915}
916
917status_t ACodec::setVideoFormatOnPort(
918        OMX_U32 portIndex,
919        int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat) {
920    OMX_PARAM_PORTDEFINITIONTYPE def;
921    InitOMXParams(&def);
922    def.nPortIndex = portIndex;
923
924    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
925
926    status_t err = mOMX->getParameter(
927            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
928
929    CHECK_EQ(err, (status_t)OK);
930
931    if (portIndex == kPortIndexInput) {
932        // XXX Need a (much) better heuristic to compute input buffer sizes.
933        const size_t X = 64 * 1024;
934        if (def.nBufferSize < X) {
935            def.nBufferSize = X;
936        }
937    }
938
939    CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
940
941    video_def->nFrameWidth = width;
942    video_def->nFrameHeight = height;
943
944    if (portIndex == kPortIndexInput) {
945        video_def->eCompressionFormat = compressionFormat;
946        video_def->eColorFormat = OMX_COLOR_FormatUnused;
947    }
948
949    err = mOMX->setParameter(
950            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
951
952    return err;
953}
954
955status_t ACodec::initNativeWindow() {
956    if (mNativeWindow != NULL) {
957        return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE);
958    }
959
960    mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE);
961    return OK;
962}
963
964bool ACodec::allYourBuffersAreBelongToUs(
965        OMX_U32 portIndex) {
966    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
967        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
968
969        if (info->mStatus != BufferInfo::OWNED_BY_US
970                && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
971            LOGV("[%s] Buffer %p on port %ld still has status %d",
972                    mComponentName.c_str(),
973                    info->mBufferID, portIndex, info->mStatus);
974            return false;
975        }
976    }
977
978    return true;
979}
980
981bool ACodec::allYourBuffersAreBelongToUs() {
982    return allYourBuffersAreBelongToUs(kPortIndexInput)
983        && allYourBuffersAreBelongToUs(kPortIndexOutput);
984}
985
986void ACodec::deferMessage(const sp<AMessage> &msg) {
987    bool wasEmptyBefore = mDeferredQueue.empty();
988    mDeferredQueue.push_back(msg);
989}
990
991void ACodec::processDeferredMessages() {
992    List<sp<AMessage> > queue = mDeferredQueue;
993    mDeferredQueue.clear();
994
995    List<sp<AMessage> >::iterator it = queue.begin();
996    while (it != queue.end()) {
997        onMessageReceived(*it++);
998    }
999}
1000
1001void ACodec::sendFormatChange() {
1002    sp<AMessage> notify = mNotify->dup();
1003    notify->setInt32("what", kWhatOutputFormatChanged);
1004
1005    OMX_PARAM_PORTDEFINITIONTYPE def;
1006    InitOMXParams(&def);
1007    def.nPortIndex = kPortIndexOutput;
1008
1009    CHECK_EQ(mOMX->getParameter(
1010                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)),
1011             (status_t)OK);
1012
1013    CHECK_EQ((int)def.eDir, (int)OMX_DirOutput);
1014
1015    switch (def.eDomain) {
1016        case OMX_PortDomainVideo:
1017        {
1018            OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
1019
1020            notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW);
1021            notify->setInt32("width", videoDef->nFrameWidth);
1022            notify->setInt32("height", videoDef->nFrameHeight);
1023
1024            OMX_CONFIG_RECTTYPE rect;
1025            InitOMXParams(&rect);
1026            rect.nPortIndex = kPortIndexOutput;
1027
1028            if (mOMX->getConfig(
1029                        mNode, OMX_IndexConfigCommonOutputCrop,
1030                        &rect, sizeof(rect)) != OK) {
1031                rect.nLeft = 0;
1032                rect.nTop = 0;
1033                rect.nWidth = videoDef->nFrameWidth;
1034                rect.nHeight = videoDef->nFrameHeight;
1035            }
1036
1037            CHECK_GE(rect.nLeft, 0);
1038            CHECK_GE(rect.nTop, 0);
1039            CHECK_GE(rect.nWidth, 0u);
1040            CHECK_GE(rect.nHeight, 0u);
1041            CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth);
1042            CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight);
1043
1044            notify->setRect(
1045                    "crop",
1046                    rect.nLeft,
1047                    rect.nTop,
1048                    rect.nLeft + rect.nWidth - 1,
1049                    rect.nTop + rect.nHeight - 1);
1050
1051            if (mNativeWindow != NULL) {
1052                android_native_rect_t crop;
1053                crop.left = rect.nLeft;
1054                crop.top = rect.nTop;
1055                crop.right = rect.nLeft + rect.nWidth - 1;
1056                crop.bottom = rect.nTop + rect.nHeight - 1;
1057
1058                CHECK_EQ(0, native_window_set_crop(
1059                            mNativeWindow.get(), &crop));
1060            }
1061            break;
1062        }
1063
1064        case OMX_PortDomainAudio:
1065        {
1066            OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
1067            CHECK_EQ((int)audioDef->eEncoding, (int)OMX_AUDIO_CodingPCM);
1068
1069            OMX_AUDIO_PARAM_PCMMODETYPE params;
1070            InitOMXParams(&params);
1071            params.nPortIndex = kPortIndexOutput;
1072
1073            CHECK_EQ(mOMX->getParameter(
1074                        mNode, OMX_IndexParamAudioPcm,
1075                        &params, sizeof(params)),
1076                     (status_t)OK);
1077
1078            CHECK(params.nChannels == 1 || params.bInterleaved);
1079            CHECK_EQ(params.nBitPerSample, 16u);
1080            CHECK_EQ((int)params.eNumData, (int)OMX_NumericalDataSigned);
1081            CHECK_EQ((int)params.ePCMMode, (int)OMX_AUDIO_PCMModeLinear);
1082
1083            notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
1084            notify->setInt32("channel-count", params.nChannels);
1085            notify->setInt32("sample-rate", params.nSamplingRate);
1086            break;
1087        }
1088
1089        default:
1090            TRESPASS();
1091    }
1092
1093    notify->post();
1094
1095    mSentFormat = true;
1096}
1097
1098////////////////////////////////////////////////////////////////////////////////
1099
1100ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
1101    : AState(parentState),
1102      mCodec(codec) {
1103}
1104
1105ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(OMX_U32 portIndex) {
1106    return KEEP_BUFFERS;
1107}
1108
1109bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) {
1110    switch (msg->what()) {
1111        case kWhatInputBufferFilled:
1112        {
1113            onInputBufferFilled(msg);
1114            break;
1115        }
1116
1117        case kWhatOutputBufferDrained:
1118        {
1119            onOutputBufferDrained(msg);
1120            break;
1121        }
1122
1123        case ACodec::kWhatOMXMessage:
1124        {
1125            return onOMXMessage(msg);
1126        }
1127
1128        default:
1129            return false;
1130    }
1131
1132    return true;
1133}
1134
1135bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) {
1136    int32_t type;
1137    CHECK(msg->findInt32("type", &type));
1138
1139    IOMX::node_id nodeID;
1140    CHECK(msg->findPointer("node", &nodeID));
1141    CHECK_EQ(nodeID, mCodec->mNode);
1142
1143    switch (type) {
1144        case omx_message::EVENT:
1145        {
1146            int32_t event, data1, data2;
1147            CHECK(msg->findInt32("event", &event));
1148            CHECK(msg->findInt32("data1", &data1));
1149            CHECK(msg->findInt32("data2", &data2));
1150
1151            return onOMXEvent(
1152                    static_cast<OMX_EVENTTYPE>(event),
1153                    static_cast<OMX_U32>(data1),
1154                    static_cast<OMX_U32>(data2));
1155        }
1156
1157        case omx_message::EMPTY_BUFFER_DONE:
1158        {
1159            IOMX::buffer_id bufferID;
1160            CHECK(msg->findPointer("buffer", &bufferID));
1161
1162            return onOMXEmptyBufferDone(bufferID);
1163        }
1164
1165        case omx_message::FILL_BUFFER_DONE:
1166        {
1167            IOMX::buffer_id bufferID;
1168            CHECK(msg->findPointer("buffer", &bufferID));
1169
1170            int32_t rangeOffset, rangeLength, flags;
1171            int64_t timeUs;
1172            void *platformPrivate;
1173            void *dataPtr;
1174
1175            CHECK(msg->findInt32("range_offset", &rangeOffset));
1176            CHECK(msg->findInt32("range_length", &rangeLength));
1177            CHECK(msg->findInt32("flags", &flags));
1178            CHECK(msg->findInt64("timestamp", &timeUs));
1179            CHECK(msg->findPointer("platform_private", &platformPrivate));
1180            CHECK(msg->findPointer("data_ptr", &dataPtr));
1181
1182            return onOMXFillBufferDone(
1183                    bufferID,
1184                    (size_t)rangeOffset, (size_t)rangeLength,
1185                    (OMX_U32)flags,
1186                    timeUs,
1187                    platformPrivate,
1188                    dataPtr);
1189        }
1190
1191        default:
1192            TRESPASS();
1193            break;
1194    }
1195}
1196
1197bool ACodec::BaseState::onOMXEvent(
1198        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1199    if (event != OMX_EventError) {
1200        LOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)",
1201             mCodec->mComponentName.c_str(), event, data1, data2);
1202
1203        return false;
1204    }
1205
1206    LOGE("[%s] ERROR(0x%08lx, 0x%08lx)",
1207         mCodec->mComponentName.c_str(), data1, data2);
1208
1209    mCodec->changeState(mCodec->mErrorState);
1210
1211    return true;
1212}
1213
1214bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) {
1215    LOGV("[%s] onOMXEmptyBufferDone %p",
1216         mCodec->mComponentName.c_str(), bufferID);
1217
1218    BufferInfo *info =
1219        mCodec->findBufferByID(kPortIndexInput, bufferID);
1220
1221    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
1222    info->mStatus = BufferInfo::OWNED_BY_US;
1223
1224    PortMode mode = getPortMode(kPortIndexInput);
1225
1226    switch (mode) {
1227        case KEEP_BUFFERS:
1228            break;
1229
1230        case RESUBMIT_BUFFERS:
1231            postFillThisBuffer(info);
1232            break;
1233
1234        default:
1235        {
1236            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
1237            TRESPASS();  // Not currently used
1238            break;
1239        }
1240    }
1241
1242    return true;
1243}
1244
1245void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) {
1246    if (mCodec->mPortEOS[kPortIndexInput]) {
1247        return;
1248    }
1249
1250    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
1251
1252    sp<AMessage> notify = mCodec->mNotify->dup();
1253    notify->setInt32("what", ACodec::kWhatFillThisBuffer);
1254    notify->setPointer("buffer-id", info->mBufferID);
1255
1256    info->mData->meta()->clear();
1257    notify->setObject("buffer", info->mData);
1258
1259    sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id());
1260    reply->setPointer("buffer-id", info->mBufferID);
1261
1262    notify->setMessage("reply", reply);
1263
1264    notify->post();
1265
1266    info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
1267}
1268
1269void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
1270    IOMX::buffer_id bufferID;
1271    CHECK(msg->findPointer("buffer-id", &bufferID));
1272
1273    sp<RefBase> obj;
1274    int32_t err = OK;
1275    if (!msg->findObject("buffer", &obj)) {
1276        CHECK(msg->findInt32("err", &err));
1277
1278        LOGV("[%s] saw error %d instead of an input buffer",
1279             mCodec->mComponentName.c_str(), err);
1280
1281        obj.clear();
1282    }
1283
1284    sp<ABuffer> buffer = static_cast<ABuffer *>(obj.get());
1285
1286    BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
1287    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM);
1288
1289    info->mStatus = BufferInfo::OWNED_BY_US;
1290
1291    PortMode mode = getPortMode(kPortIndexInput);
1292
1293    switch (mode) {
1294        case KEEP_BUFFERS:
1295        {
1296            if (buffer == NULL) {
1297                mCodec->mPortEOS[kPortIndexInput] = true;
1298            }
1299            break;
1300        }
1301
1302        case RESUBMIT_BUFFERS:
1303        {
1304            if (buffer != NULL) {
1305                CHECK(!mCodec->mPortEOS[kPortIndexInput]);
1306
1307                int64_t timeUs;
1308                CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
1309
1310                OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
1311
1312                int32_t isCSD;
1313                if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) {
1314                    flags |= OMX_BUFFERFLAG_CODECCONFIG;
1315                }
1316
1317                if (buffer != info->mData) {
1318                    if (0 && !(flags & OMX_BUFFERFLAG_CODECCONFIG)) {
1319                        LOGV("[%s] Needs to copy input data.",
1320                             mCodec->mComponentName.c_str());
1321                    }
1322
1323                    CHECK_LE(buffer->size(), info->mData->capacity());
1324                    memcpy(info->mData->data(), buffer->data(), buffer->size());
1325                }
1326
1327                LOGV("[%s] calling emptyBuffer %p",
1328                     mCodec->mComponentName.c_str(), bufferID);
1329
1330                CHECK_EQ(mCodec->mOMX->emptyBuffer(
1331                            mCodec->mNode,
1332                            bufferID,
1333                            0,
1334                            buffer->size(),
1335                            flags,
1336                            timeUs),
1337                         (status_t)OK);
1338
1339                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1340
1341                getMoreInputDataIfPossible();
1342            } else if (!mCodec->mPortEOS[kPortIndexInput]) {
1343                LOGV("[%s] Signalling EOS on the input port",
1344                     mCodec->mComponentName.c_str());
1345
1346                LOGV("[%s] calling emptyBuffer %p",
1347                     mCodec->mComponentName.c_str(), bufferID);
1348
1349                CHECK_EQ(mCodec->mOMX->emptyBuffer(
1350                            mCodec->mNode,
1351                            bufferID,
1352                            0,
1353                            0,
1354                            OMX_BUFFERFLAG_EOS,
1355                            0),
1356                         (status_t)OK);
1357
1358                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1359
1360                mCodec->mPortEOS[kPortIndexInput] = true;
1361            }
1362            break;
1363
1364            default:
1365                CHECK_EQ((int)mode, (int)FREE_BUFFERS);
1366                break;
1367        }
1368    }
1369}
1370
1371void ACodec::BaseState::getMoreInputDataIfPossible() {
1372    if (mCodec->mPortEOS[kPortIndexInput]) {
1373        return;
1374    }
1375
1376    BufferInfo *eligible = NULL;
1377
1378    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
1379        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
1380
1381#if 0
1382        if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) {
1383            // There's already a "read" pending.
1384            return;
1385        }
1386#endif
1387
1388        if (info->mStatus == BufferInfo::OWNED_BY_US) {
1389            eligible = info;
1390        }
1391    }
1392
1393    if (eligible == NULL) {
1394        return;
1395    }
1396
1397    postFillThisBuffer(eligible);
1398}
1399
1400bool ACodec::BaseState::onOMXFillBufferDone(
1401        IOMX::buffer_id bufferID,
1402        size_t rangeOffset, size_t rangeLength,
1403        OMX_U32 flags,
1404        int64_t timeUs,
1405        void *platformPrivate,
1406        void *dataPtr) {
1407    LOGV("[%s] onOMXFillBufferDone %p",
1408         mCodec->mComponentName.c_str(), bufferID);
1409
1410    ssize_t index;
1411    BufferInfo *info =
1412        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
1413
1414    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
1415
1416    info->mStatus = BufferInfo::OWNED_BY_US;
1417
1418    PortMode mode = getPortMode(kPortIndexOutput);
1419
1420    switch (mode) {
1421        case KEEP_BUFFERS:
1422            break;
1423
1424        case RESUBMIT_BUFFERS:
1425        {
1426            if (rangeLength == 0) {
1427                if (!(flags & OMX_BUFFERFLAG_EOS)) {
1428                    LOGV("[%s] calling fillBuffer %p",
1429                         mCodec->mComponentName.c_str(), info->mBufferID);
1430
1431                    CHECK_EQ(mCodec->mOMX->fillBuffer(
1432                                mCodec->mNode, info->mBufferID),
1433                             (status_t)OK);
1434
1435                    info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1436                }
1437            } else {
1438                if (!mCodec->mSentFormat) {
1439                    mCodec->sendFormatChange();
1440                }
1441
1442                if (mCodec->mNativeWindow == NULL) {
1443                    info->mData->setRange(rangeOffset, rangeLength);
1444                }
1445
1446                info->mData->meta()->setInt64("timeUs", timeUs);
1447
1448                sp<AMessage> notify = mCodec->mNotify->dup();
1449                notify->setInt32("what", ACodec::kWhatDrainThisBuffer);
1450                notify->setPointer("buffer-id", info->mBufferID);
1451                notify->setObject("buffer", info->mData);
1452
1453                sp<AMessage> reply =
1454                    new AMessage(kWhatOutputBufferDrained, mCodec->id());
1455
1456                reply->setPointer("buffer-id", info->mBufferID);
1457
1458                notify->setMessage("reply", reply);
1459
1460                notify->post();
1461
1462                info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;
1463            }
1464
1465            if (flags & OMX_BUFFERFLAG_EOS) {
1466                sp<AMessage> notify = mCodec->mNotify->dup();
1467                notify->setInt32("what", ACodec::kWhatEOS);
1468                notify->post();
1469
1470                mCodec->mPortEOS[kPortIndexOutput] = true;
1471            }
1472            break;
1473        }
1474
1475        default:
1476        {
1477            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
1478
1479            CHECK_EQ((status_t)OK,
1480                     mCodec->freeBuffer(kPortIndexOutput, index));
1481            break;
1482        }
1483    }
1484
1485    return true;
1486}
1487
1488void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
1489    IOMX::buffer_id bufferID;
1490    CHECK(msg->findPointer("buffer-id", &bufferID));
1491
1492    ssize_t index;
1493    BufferInfo *info =
1494        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
1495    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
1496
1497    int32_t render;
1498    if (mCodec->mNativeWindow != NULL
1499            && msg->findInt32("render", &render) && render != 0) {
1500        // The client wants this buffer to be rendered.
1501
1502        CHECK_EQ(mCodec->mNativeWindow->queueBuffer(
1503                    mCodec->mNativeWindow.get(),
1504                    info->mGraphicBuffer.get()),
1505                 0);
1506
1507        info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
1508    } else {
1509        info->mStatus = BufferInfo::OWNED_BY_US;
1510    }
1511
1512    PortMode mode = getPortMode(kPortIndexOutput);
1513
1514    switch (mode) {
1515        case KEEP_BUFFERS:
1516        {
1517            // XXX fishy, revisit!!! What about the FREE_BUFFERS case below?
1518
1519            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
1520                // We cannot resubmit the buffer we just rendered, dequeue
1521                // the spare instead.
1522
1523                info = mCodec->dequeueBufferFromNativeWindow();
1524            }
1525            break;
1526        }
1527
1528        case RESUBMIT_BUFFERS:
1529        {
1530            if (!mCodec->mPortEOS[kPortIndexOutput]) {
1531                if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
1532                    // We cannot resubmit the buffer we just rendered, dequeue
1533                    // the spare instead.
1534
1535                    info = mCodec->dequeueBufferFromNativeWindow();
1536                }
1537
1538                LOGV("[%s] calling fillBuffer %p",
1539                     mCodec->mComponentName.c_str(), info->mBufferID);
1540
1541                CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
1542                         (status_t)OK);
1543
1544                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1545            }
1546            break;
1547        }
1548
1549        default:
1550        {
1551            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
1552
1553            CHECK_EQ((status_t)OK,
1554                     mCodec->freeBuffer(kPortIndexOutput, index));
1555            break;
1556        }
1557    }
1558}
1559
1560////////////////////////////////////////////////////////////////////////////////
1561
1562ACodec::UninitializedState::UninitializedState(ACodec *codec)
1563    : BaseState(codec) {
1564}
1565
1566bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
1567    bool handled = false;
1568
1569    switch (msg->what()) {
1570        case ACodec::kWhatSetup:
1571        {
1572            onSetup(msg);
1573
1574            handled = true;
1575            break;
1576        }
1577
1578        case ACodec::kWhatShutdown:
1579        {
1580            sp<AMessage> notify = mCodec->mNotify->dup();
1581            notify->setInt32("what", ACodec::kWhatShutdownCompleted);
1582            notify->post();
1583
1584            handled = true;
1585        }
1586
1587        case ACodec::kWhatFlush:
1588        {
1589            sp<AMessage> notify = mCodec->mNotify->dup();
1590            notify->setInt32("what", ACodec::kWhatFlushCompleted);
1591            notify->post();
1592
1593            handled = true;
1594        }
1595
1596        default:
1597            return BaseState::onMessageReceived(msg);
1598    }
1599
1600    return handled;
1601}
1602
1603void ACodec::UninitializedState::onSetup(
1604        const sp<AMessage> &msg) {
1605    OMXClient client;
1606    CHECK_EQ(client.connect(), (status_t)OK);
1607
1608    sp<IOMX> omx = client.interface();
1609
1610    AString mime;
1611    CHECK(msg->findString("mime", &mime));
1612
1613    AString componentName;
1614
1615    if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) {
1616        componentName = "OMX.Nvidia.h264.decode";
1617    } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) {
1618        componentName = "OMX.Nvidia.aac.decoder";
1619    } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_MPEG)) {
1620        componentName = "OMX.Nvidia.mp3.decoder";
1621    } else {
1622        TRESPASS();
1623    }
1624
1625    sp<CodecObserver> observer = new CodecObserver;
1626
1627    IOMX::node_id node;
1628    CHECK_EQ(omx->allocateNode(componentName.c_str(), observer, &node),
1629             (status_t)OK);
1630
1631    sp<AMessage> notify = new AMessage(kWhatOMXMessage, mCodec->id());
1632    observer->setNotificationMessage(notify);
1633
1634    mCodec->mComponentName = componentName;
1635    mCodec->mOMX = omx;
1636    mCodec->mNode = node;
1637
1638    mCodec->mPortEOS[kPortIndexInput] =
1639        mCodec->mPortEOS[kPortIndexOutput] = false;
1640
1641    mCodec->configureCodec(mime.c_str(), msg);
1642
1643    sp<RefBase> obj;
1644    if (msg->findObject("native-window", &obj)) {
1645        sp<NativeWindowWrapper> nativeWindow(
1646                static_cast<NativeWindowWrapper *>(obj.get()));
1647        CHECK(nativeWindow != NULL);
1648        mCodec->mNativeWindow = nativeWindow->getNativeWindow();
1649    }
1650
1651    CHECK_EQ((status_t)OK, mCodec->initNativeWindow());
1652
1653    CHECK_EQ(omx->sendCommand(node, OMX_CommandStateSet, OMX_StateIdle),
1654             (status_t)OK);
1655
1656    mCodec->changeState(mCodec->mLoadedToIdleState);
1657}
1658
1659////////////////////////////////////////////////////////////////////////////////
1660
1661ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec)
1662    : BaseState(codec) {
1663}
1664
1665void ACodec::LoadedToIdleState::stateEntered() {
1666    LOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
1667
1668    CHECK_EQ(allocateBuffers(), (status_t)OK);
1669}
1670
1671status_t ACodec::LoadedToIdleState::allocateBuffers() {
1672    status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput);
1673
1674    if (err != OK) {
1675        return err;
1676    }
1677
1678    return mCodec->allocateBuffersOnPort(kPortIndexOutput);
1679}
1680
1681bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
1682    switch (msg->what()) {
1683        case kWhatShutdown:
1684        {
1685            mCodec->deferMessage(msg);
1686            return true;
1687        }
1688
1689        default:
1690            return BaseState::onMessageReceived(msg);
1691    }
1692}
1693
1694bool ACodec::LoadedToIdleState::onOMXEvent(
1695        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1696    switch (event) {
1697        case OMX_EventCmdComplete:
1698        {
1699            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
1700            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
1701
1702            CHECK_EQ(mCodec->mOMX->sendCommand(
1703                        mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting),
1704                     (status_t)OK);
1705
1706            mCodec->changeState(mCodec->mIdleToExecutingState);
1707
1708            return true;
1709        }
1710
1711        default:
1712            return BaseState::onOMXEvent(event, data1, data2);
1713    }
1714}
1715
1716////////////////////////////////////////////////////////////////////////////////
1717
1718ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec)
1719    : BaseState(codec) {
1720}
1721
1722void ACodec::IdleToExecutingState::stateEntered() {
1723    LOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
1724}
1725
1726bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
1727    switch (msg->what()) {
1728        case kWhatShutdown:
1729        {
1730            mCodec->deferMessage(msg);
1731            return true;
1732        }
1733
1734        default:
1735            return BaseState::onMessageReceived(msg);
1736    }
1737}
1738
1739bool ACodec::IdleToExecutingState::onOMXEvent(
1740        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1741    switch (event) {
1742        case OMX_EventCmdComplete:
1743        {
1744            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
1745            CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting);
1746
1747            mCodec->mExecutingState->resume();
1748            mCodec->changeState(mCodec->mExecutingState);
1749
1750            return true;
1751        }
1752
1753        default:
1754            return BaseState::onOMXEvent(event, data1, data2);
1755    }
1756}
1757
1758////////////////////////////////////////////////////////////////////////////////
1759
1760ACodec::ExecutingState::ExecutingState(ACodec *codec)
1761    : BaseState(codec),
1762      mActive(false) {
1763}
1764
1765ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode(
1766        OMX_U32 portIndex) {
1767    return RESUBMIT_BUFFERS;
1768}
1769
1770void ACodec::ExecutingState::submitOutputBuffers() {
1771    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
1772        BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
1773
1774        if (mCodec->mNativeWindow != NULL) {
1775            CHECK(info->mStatus == BufferInfo::OWNED_BY_US
1776                    || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
1777
1778            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
1779                continue;
1780            }
1781
1782            status_t err = mCodec->mNativeWindow->lockBuffer(
1783                    mCodec->mNativeWindow.get(),
1784                    info->mGraphicBuffer.get());
1785            CHECK_EQ(err, (status_t)OK);
1786        } else {
1787            CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
1788        }
1789
1790        LOGV("[%s] calling fillBuffer %p",
1791             mCodec->mComponentName.c_str(), info->mBufferID);
1792
1793        CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
1794                 (status_t)OK);
1795
1796        info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1797    }
1798}
1799
1800void ACodec::ExecutingState::resume() {
1801    if (mActive) {
1802        LOGV("[%s] We're already active, no need to resume.",
1803             mCodec->mComponentName.c_str());
1804
1805        return;
1806    }
1807
1808    submitOutputBuffers();
1809
1810    // Post the first input buffer.
1811    CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u);
1812    BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(0);
1813
1814    postFillThisBuffer(info);
1815
1816    mActive = true;
1817}
1818
1819void ACodec::ExecutingState::stateEntered() {
1820    LOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
1821
1822    mCodec->processDeferredMessages();
1823}
1824
1825bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) {
1826    bool handled = false;
1827
1828    switch (msg->what()) {
1829        case kWhatShutdown:
1830        {
1831            mActive = false;
1832
1833            CHECK_EQ(mCodec->mOMX->sendCommand(
1834                        mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
1835                     (status_t)OK);
1836
1837            mCodec->changeState(mCodec->mExecutingToIdleState);
1838
1839            handled = true;
1840            break;
1841        }
1842
1843        case kWhatFlush:
1844        {
1845            mActive = false;
1846
1847            CHECK_EQ(mCodec->mOMX->sendCommand(
1848                        mCodec->mNode, OMX_CommandFlush, OMX_ALL),
1849                     (status_t)OK);
1850
1851            mCodec->changeState(mCodec->mFlushingState);
1852
1853            handled = true;
1854            break;
1855        }
1856
1857        case kWhatResume:
1858        {
1859            resume();
1860
1861            handled = true;
1862            break;
1863        }
1864
1865        default:
1866            handled = BaseState::onMessageReceived(msg);
1867            break;
1868    }
1869
1870    return handled;
1871}
1872
1873bool ACodec::ExecutingState::onOMXEvent(
1874        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1875    switch (event) {
1876        case OMX_EventPortSettingsChanged:
1877        {
1878            CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
1879
1880            if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
1881                CHECK_EQ(mCodec->mOMX->sendCommand(
1882                            mCodec->mNode,
1883                            OMX_CommandPortDisable, kPortIndexOutput),
1884                         (status_t)OK);
1885
1886                mCodec->freeOutputBuffersNotOwnedByComponent();
1887
1888                mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
1889            } else if (data2 == OMX_IndexConfigCommonOutputCrop) {
1890                mCodec->mSentFormat = false;
1891            } else {
1892                LOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx",
1893                     mCodec->mComponentName.c_str(), data2);
1894            }
1895
1896            return true;
1897        }
1898
1899        case OMX_EventBufferFlag:
1900        {
1901            return true;
1902        }
1903
1904        default:
1905            return BaseState::onOMXEvent(event, data1, data2);
1906    }
1907}
1908
1909////////////////////////////////////////////////////////////////////////////////
1910
1911ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState(
1912        ACodec *codec)
1913    : BaseState(codec) {
1914}
1915
1916ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode(
1917        OMX_U32 portIndex) {
1918    if (portIndex == kPortIndexOutput) {
1919        return FREE_BUFFERS;
1920    }
1921
1922    CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput);
1923
1924    return RESUBMIT_BUFFERS;
1925}
1926
1927bool ACodec::OutputPortSettingsChangedState::onMessageReceived(
1928        const sp<AMessage> &msg) {
1929    bool handled = false;
1930
1931    switch (msg->what()) {
1932        case kWhatFlush:
1933        case kWhatShutdown:
1934        case kWhatResume:
1935        {
1936            if (msg->what() == kWhatResume) {
1937                LOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
1938            }
1939
1940            mCodec->deferMessage(msg);
1941            handled = true;
1942            break;
1943        }
1944
1945        default:
1946            handled = BaseState::onMessageReceived(msg);
1947            break;
1948    }
1949
1950    return handled;
1951}
1952
1953void ACodec::OutputPortSettingsChangedState::stateEntered() {
1954    LOGV("[%s] Now handling output port settings change",
1955         mCodec->mComponentName.c_str());
1956}
1957
1958bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
1959        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1960    switch (event) {
1961        case OMX_EventCmdComplete:
1962        {
1963            if (data1 == (OMX_U32)OMX_CommandPortDisable) {
1964                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
1965
1966                LOGV("[%s] Output port now disabled.",
1967                        mCodec->mComponentName.c_str());
1968
1969                CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty());
1970                mCodec->mDealer[kPortIndexOutput].clear();
1971
1972                CHECK_EQ(mCodec->mOMX->sendCommand(
1973                            mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput),
1974                         (status_t)OK);
1975
1976                CHECK_EQ(mCodec->allocateBuffersOnPort(kPortIndexOutput),
1977                         (status_t)OK);
1978
1979                return true;
1980            } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
1981                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
1982
1983                mCodec->mSentFormat = false;
1984
1985                LOGV("[%s] Output port now reenabled.",
1986                        mCodec->mComponentName.c_str());
1987
1988                if (mCodec->mExecutingState->active()) {
1989                    mCodec->mExecutingState->submitOutputBuffers();
1990                }
1991
1992                mCodec->changeState(mCodec->mExecutingState);
1993
1994                return true;
1995            }
1996
1997            return false;
1998        }
1999
2000        default:
2001            return false;
2002    }
2003}
2004
2005////////////////////////////////////////////////////////////////////////////////
2006
2007ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec)
2008    : BaseState(codec) {
2009}
2010
2011bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) {
2012    bool handled = false;
2013
2014    switch (msg->what()) {
2015        case kWhatFlush:
2016        {
2017            // Don't send me a flush request if you previously wanted me
2018            // to shutdown.
2019            TRESPASS();
2020            break;
2021        }
2022
2023        case kWhatShutdown:
2024        {
2025            // We're already doing that...
2026
2027            handled = true;
2028            break;
2029        }
2030
2031        default:
2032            handled = BaseState::onMessageReceived(msg);
2033            break;
2034    }
2035
2036    return handled;
2037}
2038
2039void ACodec::ExecutingToIdleState::stateEntered() {
2040    LOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
2041
2042    mCodec->mSentFormat = false;
2043}
2044
2045bool ACodec::ExecutingToIdleState::onOMXEvent(
2046        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2047    switch (event) {
2048        case OMX_EventCmdComplete:
2049        {
2050            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
2051            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
2052
2053            changeStateIfWeOwnAllBuffers();
2054
2055            return true;
2056        }
2057
2058        case OMX_EventPortSettingsChanged:
2059        case OMX_EventBufferFlag:
2060        {
2061            // We're shutting down and don't care about this anymore.
2062            return true;
2063        }
2064
2065        default:
2066            return BaseState::onOMXEvent(event, data1, data2);
2067    }
2068}
2069void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
2070    if (mCodec->allYourBuffersAreBelongToUs()) {
2071        CHECK_EQ(mCodec->mOMX->sendCommand(
2072                    mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded),
2073                 (status_t)OK);
2074
2075        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK);
2076        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK);
2077
2078        mCodec->changeState(mCodec->mIdleToLoadedState);
2079    }
2080}
2081
2082void ACodec::ExecutingToIdleState::onInputBufferFilled(
2083        const sp<AMessage> &msg) {
2084    BaseState::onInputBufferFilled(msg);
2085
2086    changeStateIfWeOwnAllBuffers();
2087}
2088
2089void ACodec::ExecutingToIdleState::onOutputBufferDrained(
2090        const sp<AMessage> &msg) {
2091    BaseState::onOutputBufferDrained(msg);
2092
2093    changeStateIfWeOwnAllBuffers();
2094}
2095
2096////////////////////////////////////////////////////////////////////////////////
2097
2098ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec)
2099    : BaseState(codec) {
2100}
2101
2102bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) {
2103    bool handled = false;
2104
2105    switch (msg->what()) {
2106        case kWhatShutdown:
2107        {
2108            // We're already doing that...
2109
2110            handled = true;
2111            break;
2112        }
2113
2114        case kWhatFlush:
2115        {
2116            // Don't send me a flush request if you previously wanted me
2117            // to shutdown.
2118            TRESPASS();
2119            break;
2120        }
2121
2122        default:
2123            handled = BaseState::onMessageReceived(msg);
2124            break;
2125    }
2126
2127    return handled;
2128}
2129
2130void ACodec::IdleToLoadedState::stateEntered() {
2131    LOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
2132}
2133
2134bool ACodec::IdleToLoadedState::onOMXEvent(
2135        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2136    switch (event) {
2137        case OMX_EventCmdComplete:
2138        {
2139            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
2140            CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded);
2141
2142            LOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
2143
2144            CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
2145
2146            mCodec->mNativeWindow.clear();
2147            mCodec->mNode = NULL;
2148            mCodec->mOMX.clear();
2149            mCodec->mComponentName.clear();
2150
2151            mCodec->changeState(mCodec->mUninitializedState);
2152
2153            sp<AMessage> notify = mCodec->mNotify->dup();
2154            notify->setInt32("what", ACodec::kWhatShutdownCompleted);
2155            notify->post();
2156
2157            return true;
2158        }
2159
2160        default:
2161            return BaseState::onOMXEvent(event, data1, data2);
2162    }
2163}
2164
2165////////////////////////////////////////////////////////////////////////////////
2166
2167ACodec::ErrorState::ErrorState(ACodec *codec)
2168    : BaseState(codec) {
2169}
2170
2171bool ACodec::ErrorState::onMessageReceived(const sp<AMessage> &msg) {
2172    return BaseState::onMessageReceived(msg);
2173}
2174
2175void ACodec::ErrorState::stateEntered() {
2176    LOGV("[%s] Now in ErrorState", mCodec->mComponentName.c_str());
2177}
2178
2179bool ACodec::ErrorState::onOMXEvent(
2180        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2181    LOGV("EVENT(%d, 0x%08lx, 0x%08lx)", event, data1, data2);
2182    return true;
2183}
2184
2185////////////////////////////////////////////////////////////////////////////////
2186
2187ACodec::FlushingState::FlushingState(ACodec *codec)
2188    : BaseState(codec) {
2189}
2190
2191void ACodec::FlushingState::stateEntered() {
2192    LOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());
2193
2194    mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
2195}
2196
2197bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) {
2198    bool handled = false;
2199
2200    switch (msg->what()) {
2201        case kWhatShutdown:
2202        {
2203            mCodec->deferMessage(msg);
2204            break;
2205        }
2206
2207        case kWhatFlush:
2208        {
2209            // We're already doing this right now.
2210            handled = true;
2211            break;
2212        }
2213
2214        default:
2215            handled = BaseState::onMessageReceived(msg);
2216            break;
2217    }
2218
2219    return handled;
2220}
2221
2222bool ACodec::FlushingState::onOMXEvent(
2223        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2224    switch (event) {
2225        case OMX_EventCmdComplete:
2226        {
2227            CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush);
2228
2229            if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
2230                CHECK(!mFlushComplete[data2]);
2231                mFlushComplete[data2] = true;
2232            } else {
2233                CHECK_EQ(data2, OMX_ALL);
2234                CHECK(mFlushComplete[kPortIndexInput]);
2235                CHECK(mFlushComplete[kPortIndexOutput]);
2236
2237                changeStateIfWeOwnAllBuffers();
2238            }
2239
2240            return true;
2241        }
2242
2243        case OMX_EventPortSettingsChanged:
2244        {
2245            sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id());
2246            msg->setInt32("type", omx_message::EVENT);
2247            msg->setPointer("node", mCodec->mNode);
2248            msg->setInt32("event", event);
2249            msg->setInt32("data1", data1);
2250            msg->setInt32("data2", data2);
2251
2252            LOGV("[%s] Deferring OMX_EventPortSettingsChanged",
2253                 mCodec->mComponentName.c_str());
2254
2255            mCodec->deferMessage(msg);
2256
2257            return true;
2258        }
2259
2260        default:
2261            return BaseState::onOMXEvent(event, data1, data2);
2262    }
2263
2264    return true;
2265}
2266
2267void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) {
2268    BaseState::onOutputBufferDrained(msg);
2269
2270    changeStateIfWeOwnAllBuffers();
2271}
2272
2273void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) {
2274    BaseState::onInputBufferFilled(msg);
2275
2276    changeStateIfWeOwnAllBuffers();
2277}
2278
2279void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() {
2280    if (mFlushComplete[kPortIndexInput]
2281            && mFlushComplete[kPortIndexOutput]
2282            && mCodec->allYourBuffersAreBelongToUs()) {
2283        sp<AMessage> notify = mCodec->mNotify->dup();
2284        notify->setInt32("what", ACodec::kWhatFlushCompleted);
2285        notify->post();
2286
2287        mCodec->mPortEOS[kPortIndexInput] =
2288            mCodec->mPortEOS[kPortIndexOutput] = false;
2289
2290        mCodec->changeState(mCodec->mExecutingState);
2291    }
2292}
2293
2294}  // namespace android
2295