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