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