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