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