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