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