ACodec.cpp revision 3831a066bcf1019864a94d2bc7b4c9241efc5c22
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        LOGV("[%s] saw error %d instead of an input buffer",
1161             mCodec->mComponentName.c_str(), err);
1162
1163        obj.clear();
1164    }
1165
1166    sp<ABuffer> buffer = static_cast<ABuffer *>(obj.get());
1167
1168    BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
1169    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM);
1170
1171    info->mStatus = BufferInfo::OWNED_BY_US;
1172
1173    PortMode mode = getPortMode(kPortIndexInput);
1174
1175    switch (mode) {
1176        case KEEP_BUFFERS:
1177        {
1178            if (buffer == NULL) {
1179                mCodec->mPortEOS[kPortIndexInput] = true;
1180            }
1181            break;
1182        }
1183
1184        case RESUBMIT_BUFFERS:
1185        {
1186            if (buffer != NULL) {
1187                CHECK(!mCodec->mPortEOS[kPortIndexInput]);
1188
1189                int64_t timeUs;
1190                CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
1191
1192                OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
1193
1194                int32_t isCSD;
1195                if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) {
1196                    flags |= OMX_BUFFERFLAG_CODECCONFIG;
1197                }
1198
1199                if (buffer != info->mData) {
1200                    if (!(flags & OMX_BUFFERFLAG_CODECCONFIG)) {
1201                        LOGV("[%s] Needs to copy input data.",
1202                             mCodec->mComponentName.c_str());
1203                    }
1204
1205                    CHECK_LE(buffer->size(), info->mData->capacity());
1206                    memcpy(info->mData->data(), buffer->data(), buffer->size());
1207                }
1208
1209                CHECK_EQ(mCodec->mOMX->emptyBuffer(
1210                            mCodec->mNode,
1211                            bufferID,
1212                            0,
1213                            buffer->size(),
1214                            flags,
1215                            timeUs),
1216                         (status_t)OK);
1217
1218                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1219
1220                getMoreInputDataIfPossible();
1221            } else if (!mCodec->mPortEOS[kPortIndexInput]) {
1222                LOGV("[%s] Signalling EOS on the input port",
1223                     mCodec->mComponentName.c_str());
1224
1225                CHECK_EQ(mCodec->mOMX->emptyBuffer(
1226                            mCodec->mNode,
1227                            bufferID,
1228                            0,
1229                            0,
1230                            OMX_BUFFERFLAG_EOS,
1231                            0),
1232                         (status_t)OK);
1233
1234                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1235
1236                mCodec->mPortEOS[kPortIndexInput] = true;
1237            }
1238            break;
1239
1240            default:
1241                CHECK_EQ((int)mode, (int)FREE_BUFFERS);
1242                break;
1243        }
1244    }
1245}
1246
1247void ACodec::BaseState::getMoreInputDataIfPossible() {
1248    if (mCodec->mPortEOS[kPortIndexInput]) {
1249        return;
1250    }
1251
1252    BufferInfo *eligible = NULL;
1253
1254    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
1255        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
1256
1257#if 0
1258        if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) {
1259            // There's already a "read" pending.
1260            return;
1261        }
1262#endif
1263
1264        if (info->mStatus == BufferInfo::OWNED_BY_US) {
1265            eligible = info;
1266        }
1267    }
1268
1269    if (eligible == NULL) {
1270        return;
1271    }
1272
1273    postFillThisBuffer(eligible);
1274}
1275
1276bool ACodec::BaseState::onOMXFillBufferDone(
1277        IOMX::buffer_id bufferID,
1278        size_t rangeOffset, size_t rangeLength,
1279        OMX_U32 flags,
1280        int64_t timeUs,
1281        void *platformPrivate,
1282        void *dataPtr) {
1283    ssize_t index;
1284    BufferInfo *info =
1285        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
1286
1287    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
1288
1289    info->mStatus = BufferInfo::OWNED_BY_US;
1290
1291    PortMode mode = getPortMode(kPortIndexOutput);
1292
1293    switch (mode) {
1294        case KEEP_BUFFERS:
1295            break;
1296
1297        case RESUBMIT_BUFFERS:
1298        {
1299            if (rangeLength == 0) {
1300                if (!(flags & OMX_BUFFERFLAG_EOS)) {
1301                    CHECK_EQ(mCodec->mOMX->fillBuffer(
1302                                mCodec->mNode, info->mBufferID),
1303                             (status_t)OK);
1304
1305                    info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1306                }
1307            } else {
1308                if (mCodec->mNativeWindow == NULL) {
1309                    info->mData->setRange(rangeOffset, rangeLength);
1310                }
1311
1312                info->mData->meta()->setInt64("timeUs", timeUs);
1313
1314                sp<AMessage> notify = mCodec->mNotify->dup();
1315                notify->setInt32("what", ACodec::kWhatDrainThisBuffer);
1316                notify->setPointer("buffer-id", info->mBufferID);
1317                notify->setObject("buffer", info->mData);
1318
1319                sp<AMessage> reply =
1320                    new AMessage(kWhatOutputBufferDrained, mCodec->id());
1321
1322                reply->setPointer("buffer-id", info->mBufferID);
1323
1324                notify->setMessage("reply", reply);
1325
1326                notify->post();
1327
1328                info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;
1329            }
1330
1331            if (flags & OMX_BUFFERFLAG_EOS) {
1332                sp<AMessage> notify = mCodec->mNotify->dup();
1333                notify->setInt32("what", ACodec::kWhatEOS);
1334                notify->post();
1335
1336                mCodec->mPortEOS[kPortIndexOutput] = true;
1337            }
1338            break;
1339        }
1340
1341        default:
1342        {
1343            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
1344
1345            CHECK_EQ((status_t)OK,
1346                     mCodec->freeBuffer(kPortIndexOutput, index));
1347            break;
1348        }
1349    }
1350
1351    return true;
1352}
1353
1354void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
1355    IOMX::buffer_id bufferID;
1356    CHECK(msg->findPointer("buffer-id", &bufferID));
1357
1358    ssize_t index;
1359    BufferInfo *info =
1360        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
1361    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
1362
1363    int32_t render;
1364    if (mCodec->mNativeWindow != NULL
1365            && msg->findInt32("render", &render) && render != 0) {
1366        // The client wants this buffer to be rendered.
1367
1368        CHECK_EQ(mCodec->mNativeWindow->queueBuffer(
1369                    mCodec->mNativeWindow.get(),
1370                    info->mGraphicBuffer.get()),
1371                 0);
1372
1373        info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
1374    } else {
1375        info->mStatus = BufferInfo::OWNED_BY_US;
1376    }
1377
1378    PortMode mode = getPortMode(kPortIndexOutput);
1379
1380    switch (mode) {
1381        case KEEP_BUFFERS:
1382        {
1383            // XXX fishy, revisit!!! What about the FREE_BUFFERS case below?
1384
1385            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
1386                // We cannot resubmit the buffer we just rendered, dequeue
1387                // the spare instead.
1388
1389                info = mCodec->dequeueBufferFromNativeWindow();
1390            }
1391            break;
1392        }
1393
1394        case RESUBMIT_BUFFERS:
1395        {
1396            if (!mCodec->mPortEOS[kPortIndexOutput]) {
1397                if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
1398                    // We cannot resubmit the buffer we just rendered, dequeue
1399                    // the spare instead.
1400
1401                    info = mCodec->dequeueBufferFromNativeWindow();
1402                }
1403
1404                CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
1405                         (status_t)OK);
1406
1407                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1408            }
1409            break;
1410        }
1411
1412        default:
1413        {
1414            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
1415
1416            CHECK_EQ((status_t)OK,
1417                     mCodec->freeBuffer(kPortIndexOutput, index));
1418            break;
1419        }
1420    }
1421}
1422
1423////////////////////////////////////////////////////////////////////////////////
1424
1425ACodec::UninitializedState::UninitializedState(ACodec *codec)
1426    : BaseState(codec) {
1427}
1428
1429bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
1430    bool handled = false;
1431
1432    switch (msg->what()) {
1433        case ACodec::kWhatSetup:
1434        {
1435            onSetup(msg);
1436
1437            handled = true;
1438            break;
1439        }
1440
1441        case ACodec::kWhatShutdown:
1442        {
1443            sp<AMessage> notify = mCodec->mNotify->dup();
1444            notify->setInt32("what", ACodec::kWhatShutdownCompleted);
1445            notify->post();
1446
1447            handled = true;
1448        }
1449
1450        case ACodec::kWhatFlush:
1451        {
1452            sp<AMessage> notify = mCodec->mNotify->dup();
1453            notify->setInt32("what", ACodec::kWhatFlushCompleted);
1454            notify->post();
1455
1456            handled = true;
1457        }
1458
1459        default:
1460            return BaseState::onMessageReceived(msg);
1461    }
1462
1463    return handled;
1464}
1465
1466void ACodec::UninitializedState::onSetup(
1467        const sp<AMessage> &msg) {
1468    OMXClient client;
1469    CHECK_EQ(client.connect(), (status_t)OK);
1470
1471    sp<IOMX> omx = client.interface();
1472
1473    AString mime;
1474    CHECK(msg->findString("mime", &mime));
1475
1476    AString componentName;
1477
1478    if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) {
1479        componentName = "OMX.Nvidia.h264.decode";
1480    } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) {
1481        componentName = "OMX.Nvidia.aac.decoder";
1482    } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_MPEG)) {
1483        componentName = "OMX.Nvidia.mp3.decoder";
1484    } else {
1485        TRESPASS();
1486    }
1487
1488    sp<CodecObserver> observer = new CodecObserver;
1489
1490    IOMX::node_id node;
1491    CHECK_EQ(omx->allocateNode(componentName.c_str(), observer, &node),
1492             (status_t)OK);
1493
1494    sp<AMessage> notify = new AMessage(kWhatOMXMessage, mCodec->id());
1495    observer->setNotificationMessage(notify);
1496
1497    mCodec->mComponentName = componentName;
1498    mCodec->mOMX = omx;
1499    mCodec->mNode = node;
1500
1501    mCodec->configureCodec(mime.c_str(), msg);
1502
1503    sp<RefBase> obj;
1504    if (msg->findObject("surface", &obj)) {
1505        mCodec->mNativeWindow = static_cast<Surface *>(obj.get());
1506    }
1507
1508    CHECK_EQ((status_t)OK, mCodec->initNativeWindow());
1509
1510    CHECK_EQ(omx->sendCommand(node, OMX_CommandStateSet, OMX_StateIdle),
1511             (status_t)OK);
1512
1513    mCodec->changeState(mCodec->mLoadedToIdleState);
1514}
1515
1516////////////////////////////////////////////////////////////////////////////////
1517
1518ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec)
1519    : BaseState(codec) {
1520}
1521
1522void ACodec::LoadedToIdleState::stateEntered() {
1523    LOGI("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
1524
1525    CHECK_EQ(allocateBuffers(), (status_t)OK);
1526}
1527
1528status_t ACodec::LoadedToIdleState::allocateBuffers() {
1529    status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput);
1530
1531    if (err != OK) {
1532        return err;
1533    }
1534
1535    return mCodec->allocateBuffersOnPort(kPortIndexOutput);
1536}
1537
1538bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
1539    switch (msg->what()) {
1540        case kWhatShutdown:
1541        {
1542            mCodec->deferMessage(msg);
1543            return true;
1544        }
1545
1546        default:
1547            return BaseState::onMessageReceived(msg);
1548    }
1549}
1550
1551bool ACodec::LoadedToIdleState::onOMXEvent(
1552        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1553    switch (event) {
1554        case OMX_EventCmdComplete:
1555        {
1556            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
1557            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
1558
1559            CHECK_EQ(mCodec->mOMX->sendCommand(
1560                        mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting),
1561                     (status_t)OK);
1562
1563            mCodec->changeState(mCodec->mIdleToExecutingState);
1564
1565            return true;
1566        }
1567
1568        default:
1569            return BaseState::onOMXEvent(event, data1, data2);
1570    }
1571}
1572
1573////////////////////////////////////////////////////////////////////////////////
1574
1575ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec)
1576    : BaseState(codec) {
1577}
1578
1579void ACodec::IdleToExecutingState::stateEntered() {
1580    LOGI("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
1581}
1582
1583bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
1584    switch (msg->what()) {
1585        case kWhatShutdown:
1586        {
1587            mCodec->deferMessage(msg);
1588            return true;
1589        }
1590
1591        default:
1592            return BaseState::onMessageReceived(msg);
1593    }
1594}
1595
1596bool ACodec::IdleToExecutingState::onOMXEvent(
1597        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1598    switch (event) {
1599        case OMX_EventCmdComplete:
1600        {
1601            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
1602            CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting);
1603
1604            mCodec->mExecutingState->resume();
1605            mCodec->changeState(mCodec->mExecutingState);
1606
1607            return true;
1608        }
1609
1610        default:
1611            return BaseState::onOMXEvent(event, data1, data2);
1612    }
1613}
1614
1615////////////////////////////////////////////////////////////////////////////////
1616
1617ACodec::ExecutingState::ExecutingState(ACodec *codec)
1618    : BaseState(codec) {
1619}
1620
1621ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode(
1622        OMX_U32 portIndex) {
1623    return RESUBMIT_BUFFERS;
1624}
1625
1626void ACodec::ExecutingState::submitOutputBuffers() {
1627    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
1628        BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
1629
1630        if (mCodec->mNativeWindow != NULL) {
1631            CHECK(info->mStatus == BufferInfo::OWNED_BY_US
1632                    || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
1633
1634            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
1635                continue;
1636            }
1637
1638            status_t err = mCodec->mNativeWindow->lockBuffer(
1639                    mCodec->mNativeWindow.get(),
1640                    info->mGraphicBuffer.get());
1641            CHECK_EQ(err, (status_t)OK);
1642        } else {
1643            CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
1644        }
1645
1646        CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
1647                 (status_t)OK);
1648
1649        info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1650    }
1651}
1652
1653void ACodec::ExecutingState::resume() {
1654    submitOutputBuffers();
1655
1656    // Post the first input buffer.
1657    CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u);
1658    BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(0);
1659
1660    postFillThisBuffer(info);
1661}
1662
1663void ACodec::ExecutingState::stateEntered() {
1664    LOGI("[%s] Now Executing", mCodec->mComponentName.c_str());
1665
1666    mCodec->processDeferredMessages();
1667}
1668
1669bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) {
1670    bool handled = false;
1671
1672    switch (msg->what()) {
1673        case kWhatShutdown:
1674        {
1675            CHECK_EQ(mCodec->mOMX->sendCommand(
1676                        mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
1677                     (status_t)OK);
1678
1679            mCodec->changeState(mCodec->mExecutingToIdleState);
1680
1681            handled = true;
1682            break;
1683        }
1684
1685        case kWhatFlush:
1686        {
1687            CHECK_EQ(mCodec->mOMX->sendCommand(
1688                        mCodec->mNode, OMX_CommandFlush, OMX_ALL),
1689                     (status_t)OK);
1690
1691            mCodec->changeState(mCodec->mFlushingState);
1692
1693            handled = true;
1694            break;
1695        }
1696
1697        case kWhatResume:
1698        {
1699            resume();
1700
1701            handled = true;
1702            break;
1703        }
1704
1705        default:
1706            handled = BaseState::onMessageReceived(msg);
1707            break;
1708    }
1709
1710    return handled;
1711}
1712
1713bool ACodec::ExecutingState::onOMXEvent(
1714        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1715    switch (event) {
1716        case OMX_EventPortSettingsChanged:
1717        {
1718            CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
1719
1720            if (data2 == OMX_IndexParamPortDefinition) {
1721                CHECK_EQ(mCodec->mOMX->sendCommand(
1722                            mCodec->mNode,
1723                            OMX_CommandPortDisable, kPortIndexOutput),
1724                         (status_t)OK);
1725
1726                if (mCodec->mNativeWindow != NULL) {
1727                    CHECK_EQ((status_t)OK,
1728                             mCodec->freeOutputBuffersOwnedByNativeWindow());
1729                }
1730
1731                mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
1732            } else {
1733                LOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx",
1734                     mCodec->mComponentName.c_str(), data2);
1735            }
1736
1737            return true;
1738        }
1739
1740        case OMX_EventBufferFlag:
1741        {
1742            return true;
1743        }
1744
1745        default:
1746            return BaseState::onOMXEvent(event, data1, data2);
1747    }
1748}
1749
1750////////////////////////////////////////////////////////////////////////////////
1751
1752ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState(
1753        ACodec *codec)
1754    : BaseState(codec) {
1755}
1756
1757ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode(
1758        OMX_U32 portIndex) {
1759    if (portIndex == kPortIndexOutput) {
1760        return FREE_BUFFERS;
1761    }
1762
1763    CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput);
1764
1765    return RESUBMIT_BUFFERS;
1766}
1767
1768bool ACodec::OutputPortSettingsChangedState::onMessageReceived(
1769        const sp<AMessage> &msg) {
1770    bool handled = false;
1771
1772    switch (msg->what()) {
1773        case kWhatFlush:
1774        case kWhatShutdown:
1775        {
1776            mCodec->deferMessage(msg);
1777            handled = true;
1778            break;
1779        }
1780
1781        default:
1782            handled = BaseState::onMessageReceived(msg);
1783            break;
1784    }
1785
1786    return handled;
1787}
1788
1789void ACodec::OutputPortSettingsChangedState::stateEntered() {
1790    LOGI("[%s] Now handling output port settings change",
1791         mCodec->mComponentName.c_str());
1792}
1793
1794bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
1795        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1796    switch (event) {
1797        case OMX_EventCmdComplete:
1798        {
1799            if (data1 == (OMX_U32)OMX_CommandPortDisable) {
1800                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
1801
1802                LOGV("[%s] Output port now disabled.",
1803                        mCodec->mComponentName.c_str());
1804
1805                CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty());
1806                mCodec->mDealer[kPortIndexOutput].clear();
1807
1808                CHECK_EQ(mCodec->mOMX->sendCommand(
1809                            mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput),
1810                         (status_t)OK);
1811
1812                CHECK_EQ(mCodec->allocateBuffersOnPort(kPortIndexOutput),
1813                         (status_t)OK);
1814
1815                return true;
1816            } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
1817                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
1818
1819                LOGV("[%s] Output port now reenabled.",
1820                        mCodec->mComponentName.c_str());
1821
1822                mCodec->mExecutingState->submitOutputBuffers();
1823                mCodec->changeState(mCodec->mExecutingState);
1824
1825                return true;
1826            }
1827
1828            return false;
1829        }
1830
1831        default:
1832            return false;
1833    }
1834}
1835
1836////////////////////////////////////////////////////////////////////////////////
1837
1838ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec)
1839    : BaseState(codec) {
1840}
1841
1842bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) {
1843    bool handled = false;
1844
1845    switch (msg->what()) {
1846        case kWhatFlush:
1847        {
1848            // Don't send me a flush request if you previously wanted me
1849            // to shutdown.
1850            TRESPASS();
1851            break;
1852        }
1853
1854        case kWhatShutdown:
1855        {
1856            // We're already doing that...
1857
1858            handled = true;
1859            break;
1860        }
1861
1862        default:
1863            handled = BaseState::onMessageReceived(msg);
1864            break;
1865    }
1866
1867    return handled;
1868}
1869
1870void ACodec::ExecutingToIdleState::stateEntered() {
1871    LOGI("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
1872}
1873
1874bool ACodec::ExecutingToIdleState::onOMXEvent(
1875        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1876    switch (event) {
1877        case OMX_EventCmdComplete:
1878        {
1879            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
1880            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
1881
1882            changeStateIfWeOwnAllBuffers();
1883
1884            return true;
1885        }
1886
1887        default:
1888            return BaseState::onOMXEvent(event, data1, data2);
1889    }
1890}
1891void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
1892    if (mCodec->allYourBuffersAreBelongToUs()) {
1893        CHECK_EQ(mCodec->mOMX->sendCommand(
1894                    mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded),
1895                 (status_t)OK);
1896
1897        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK);
1898        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK);
1899
1900        mCodec->changeState(mCodec->mIdleToLoadedState);
1901    }
1902}
1903
1904void ACodec::ExecutingToIdleState::onInputBufferFilled(
1905        const sp<AMessage> &msg) {
1906    BaseState::onInputBufferFilled(msg);
1907
1908    changeStateIfWeOwnAllBuffers();
1909}
1910
1911void ACodec::ExecutingToIdleState::onOutputBufferDrained(
1912        const sp<AMessage> &msg) {
1913    BaseState::onOutputBufferDrained(msg);
1914
1915    changeStateIfWeOwnAllBuffers();
1916}
1917
1918////////////////////////////////////////////////////////////////////////////////
1919
1920ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec)
1921    : BaseState(codec) {
1922}
1923
1924bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) {
1925    bool handled = false;
1926
1927    switch (msg->what()) {
1928        case kWhatShutdown:
1929        {
1930            // We're already doing that...
1931
1932            handled = true;
1933            break;
1934        }
1935
1936        case kWhatFlush:
1937        {
1938            // Don't send me a flush request if you previously wanted me
1939            // to shutdown.
1940            TRESPASS();
1941            break;
1942        }
1943
1944        default:
1945            handled = BaseState::onMessageReceived(msg);
1946            break;
1947    }
1948
1949    return handled;
1950}
1951
1952void ACodec::IdleToLoadedState::stateEntered() {
1953    LOGI("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
1954}
1955
1956bool ACodec::IdleToLoadedState::onOMXEvent(
1957        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1958    switch (event) {
1959        case OMX_EventCmdComplete:
1960        {
1961            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
1962            CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded);
1963
1964            LOGI("[%s] Now Loaded", mCodec->mComponentName.c_str());
1965
1966            CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
1967
1968            mCodec->mNativeWindow.clear();
1969            mCodec->mNode = NULL;
1970            mCodec->mOMX.clear();
1971            mCodec->mComponentName.clear();
1972
1973            mCodec->changeState(mCodec->mUninitializedState);
1974
1975            sp<AMessage> notify = mCodec->mNotify->dup();
1976            notify->setInt32("what", ACodec::kWhatShutdownCompleted);
1977            notify->post();
1978
1979            return true;
1980        }
1981
1982        default:
1983            return BaseState::onOMXEvent(event, data1, data2);
1984    }
1985}
1986
1987////////////////////////////////////////////////////////////////////////////////
1988
1989ACodec::ErrorState::ErrorState(ACodec *codec)
1990    : BaseState(codec) {
1991}
1992
1993bool ACodec::ErrorState::onMessageReceived(const sp<AMessage> &msg) {
1994    return BaseState::onMessageReceived(msg);
1995}
1996
1997void ACodec::ErrorState::stateEntered() {
1998    LOGI("[%s] Now in ErrorState", mCodec->mComponentName.c_str());
1999}
2000
2001bool ACodec::ErrorState::onOMXEvent(
2002        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2003    LOGI("EVENT(%d, 0x%08lx, 0x%08lx)", event, data1, data2);
2004    return true;
2005}
2006
2007////////////////////////////////////////////////////////////////////////////////
2008
2009ACodec::FlushingState::FlushingState(ACodec *codec)
2010    : BaseState(codec) {
2011}
2012
2013void ACodec::FlushingState::stateEntered() {
2014    LOGI("[%s] Now Flushing", mCodec->mComponentName.c_str());
2015
2016    mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
2017}
2018
2019bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) {
2020    bool handled = false;
2021
2022    switch (msg->what()) {
2023        case kWhatShutdown:
2024        {
2025            mCodec->deferMessage(msg);
2026            break;
2027        }
2028
2029        case kWhatFlush:
2030        {
2031            // We're already doing this right now.
2032            handled = true;
2033            break;
2034        }
2035
2036        default:
2037            handled = BaseState::onMessageReceived(msg);
2038            break;
2039    }
2040
2041    return handled;
2042}
2043
2044bool ACodec::FlushingState::onOMXEvent(
2045        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2046    switch (event) {
2047        case OMX_EventCmdComplete:
2048        {
2049            CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush);
2050
2051            if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
2052                CHECK(!mFlushComplete[data2]);
2053                mFlushComplete[data2] = true;
2054            } else {
2055                CHECK_EQ(data2, OMX_ALL);
2056                CHECK(mFlushComplete[kPortIndexInput]);
2057                CHECK(mFlushComplete[kPortIndexOutput]);
2058
2059                changeStateIfWeOwnAllBuffers();
2060            }
2061
2062            return true;
2063        }
2064
2065        default:
2066            return BaseState::onOMXEvent(event, data1, data2);
2067    }
2068
2069    return true;
2070}
2071
2072void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) {
2073    BaseState::onOutputBufferDrained(msg);
2074
2075    changeStateIfWeOwnAllBuffers();
2076}
2077
2078void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) {
2079    BaseState::onInputBufferFilled(msg);
2080
2081    changeStateIfWeOwnAllBuffers();
2082}
2083
2084void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() {
2085    if (mFlushComplete[kPortIndexInput]
2086            && mFlushComplete[kPortIndexOutput]
2087            && mCodec->allYourBuffersAreBelongToUs()) {
2088        sp<AMessage> notify = mCodec->mNotify->dup();
2089        notify->setInt32("what", ACodec::kWhatFlushCompleted);
2090        notify->post();
2091
2092        mCodec->mPortEOS[kPortIndexInput] =
2093            mCodec->mPortEOS[kPortIndexOutput] = false;
2094
2095        mCodec->changeState(mCodec->mExecutingState);
2096    }
2097}
2098
2099}  // namespace android
2100
2101