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