ACodec.cpp revision 386d609dc513e838c7e7c4c46c604493ccd560be
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 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG2, mime)) {
913        compressionFormat = OMX_VIDEO_CodingMPEG2;
914    } else {
915        TRESPASS();
916    }
917
918    status_t err = setVideoPortFormatType(
919            kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
920
921    if (err != OK) {
922        return err;
923    }
924
925    err = setSupportedOutputFormat();
926
927    if (err != OK) {
928        return err;
929    }
930
931    err = setVideoFormatOnPort(
932            kPortIndexInput, width, height, compressionFormat);
933
934    if (err != OK) {
935        return err;
936    }
937
938    err = setVideoFormatOnPort(
939            kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused);
940
941    if (err != OK) {
942        return err;
943    }
944
945    return OK;
946}
947
948status_t ACodec::setVideoFormatOnPort(
949        OMX_U32 portIndex,
950        int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat) {
951    OMX_PARAM_PORTDEFINITIONTYPE def;
952    InitOMXParams(&def);
953    def.nPortIndex = portIndex;
954
955    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
956
957    status_t err = mOMX->getParameter(
958            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
959
960    CHECK_EQ(err, (status_t)OK);
961
962    if (portIndex == kPortIndexInput) {
963        // XXX Need a (much) better heuristic to compute input buffer sizes.
964        const size_t X = 64 * 1024;
965        if (def.nBufferSize < X) {
966            def.nBufferSize = X;
967        }
968    }
969
970    CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
971
972    video_def->nFrameWidth = width;
973    video_def->nFrameHeight = height;
974
975    if (portIndex == kPortIndexInput) {
976        video_def->eCompressionFormat = compressionFormat;
977        video_def->eColorFormat = OMX_COLOR_FormatUnused;
978    }
979
980    err = mOMX->setParameter(
981            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
982
983    return err;
984}
985
986status_t ACodec::initNativeWindow() {
987    if (mNativeWindow != NULL) {
988        return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE);
989    }
990
991    mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE);
992    return OK;
993}
994
995bool ACodec::allYourBuffersAreBelongToUs(
996        OMX_U32 portIndex) {
997    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
998        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
999
1000        if (info->mStatus != BufferInfo::OWNED_BY_US
1001                && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
1002            LOGV("[%s] Buffer %p on port %ld still has status %d",
1003                    mComponentName.c_str(),
1004                    info->mBufferID, portIndex, info->mStatus);
1005            return false;
1006        }
1007    }
1008
1009    return true;
1010}
1011
1012bool ACodec::allYourBuffersAreBelongToUs() {
1013    return allYourBuffersAreBelongToUs(kPortIndexInput)
1014        && allYourBuffersAreBelongToUs(kPortIndexOutput);
1015}
1016
1017void ACodec::deferMessage(const sp<AMessage> &msg) {
1018    bool wasEmptyBefore = mDeferredQueue.empty();
1019    mDeferredQueue.push_back(msg);
1020}
1021
1022void ACodec::processDeferredMessages() {
1023    List<sp<AMessage> > queue = mDeferredQueue;
1024    mDeferredQueue.clear();
1025
1026    List<sp<AMessage> >::iterator it = queue.begin();
1027    while (it != queue.end()) {
1028        onMessageReceived(*it++);
1029    }
1030}
1031
1032void ACodec::sendFormatChange() {
1033    sp<AMessage> notify = mNotify->dup();
1034    notify->setInt32("what", kWhatOutputFormatChanged);
1035
1036    OMX_PARAM_PORTDEFINITIONTYPE def;
1037    InitOMXParams(&def);
1038    def.nPortIndex = kPortIndexOutput;
1039
1040    CHECK_EQ(mOMX->getParameter(
1041                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)),
1042             (status_t)OK);
1043
1044    CHECK_EQ((int)def.eDir, (int)OMX_DirOutput);
1045
1046    switch (def.eDomain) {
1047        case OMX_PortDomainVideo:
1048        {
1049            OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
1050
1051            notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW);
1052            notify->setInt32("width", videoDef->nFrameWidth);
1053            notify->setInt32("height", videoDef->nFrameHeight);
1054
1055            OMX_CONFIG_RECTTYPE rect;
1056            InitOMXParams(&rect);
1057            rect.nPortIndex = kPortIndexOutput;
1058
1059            if (mOMX->getConfig(
1060                        mNode, OMX_IndexConfigCommonOutputCrop,
1061                        &rect, sizeof(rect)) != OK) {
1062                rect.nLeft = 0;
1063                rect.nTop = 0;
1064                rect.nWidth = videoDef->nFrameWidth;
1065                rect.nHeight = videoDef->nFrameHeight;
1066            }
1067
1068            CHECK_GE(rect.nLeft, 0);
1069            CHECK_GE(rect.nTop, 0);
1070            CHECK_GE(rect.nWidth, 0u);
1071            CHECK_GE(rect.nHeight, 0u);
1072            CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth);
1073            CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight);
1074
1075            notify->setRect(
1076                    "crop",
1077                    rect.nLeft,
1078                    rect.nTop,
1079                    rect.nLeft + rect.nWidth - 1,
1080                    rect.nTop + rect.nHeight - 1);
1081
1082            if (mNativeWindow != NULL) {
1083                android_native_rect_t crop;
1084                crop.left = rect.nLeft;
1085                crop.top = rect.nTop;
1086                crop.right = rect.nLeft + rect.nWidth;
1087                crop.bottom = rect.nTop + rect.nHeight;
1088
1089                CHECK_EQ(0, native_window_set_crop(
1090                            mNativeWindow.get(), &crop));
1091            }
1092            break;
1093        }
1094
1095        case OMX_PortDomainAudio:
1096        {
1097            OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
1098            CHECK_EQ((int)audioDef->eEncoding, (int)OMX_AUDIO_CodingPCM);
1099
1100            OMX_AUDIO_PARAM_PCMMODETYPE params;
1101            InitOMXParams(&params);
1102            params.nPortIndex = kPortIndexOutput;
1103
1104            CHECK_EQ(mOMX->getParameter(
1105                        mNode, OMX_IndexParamAudioPcm,
1106                        &params, sizeof(params)),
1107                     (status_t)OK);
1108
1109            CHECK(params.nChannels == 1 || params.bInterleaved);
1110            CHECK_EQ(params.nBitPerSample, 16u);
1111            CHECK_EQ((int)params.eNumData, (int)OMX_NumericalDataSigned);
1112            CHECK_EQ((int)params.ePCMMode, (int)OMX_AUDIO_PCMModeLinear);
1113
1114            notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
1115            notify->setInt32("channel-count", params.nChannels);
1116            notify->setInt32("sample-rate", params.nSamplingRate);
1117            break;
1118        }
1119
1120        default:
1121            TRESPASS();
1122    }
1123
1124    notify->post();
1125
1126    mSentFormat = true;
1127}
1128
1129////////////////////////////////////////////////////////////////////////////////
1130
1131ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
1132    : AState(parentState),
1133      mCodec(codec) {
1134}
1135
1136ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(OMX_U32 portIndex) {
1137    return KEEP_BUFFERS;
1138}
1139
1140bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) {
1141    switch (msg->what()) {
1142        case kWhatInputBufferFilled:
1143        {
1144            onInputBufferFilled(msg);
1145            break;
1146        }
1147
1148        case kWhatOutputBufferDrained:
1149        {
1150            onOutputBufferDrained(msg);
1151            break;
1152        }
1153
1154        case ACodec::kWhatOMXMessage:
1155        {
1156            return onOMXMessage(msg);
1157        }
1158
1159        default:
1160            return false;
1161    }
1162
1163    return true;
1164}
1165
1166bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) {
1167    int32_t type;
1168    CHECK(msg->findInt32("type", &type));
1169
1170    IOMX::node_id nodeID;
1171    CHECK(msg->findPointer("node", &nodeID));
1172    CHECK_EQ(nodeID, mCodec->mNode);
1173
1174    switch (type) {
1175        case omx_message::EVENT:
1176        {
1177            int32_t event, data1, data2;
1178            CHECK(msg->findInt32("event", &event));
1179            CHECK(msg->findInt32("data1", &data1));
1180            CHECK(msg->findInt32("data2", &data2));
1181
1182            return onOMXEvent(
1183                    static_cast<OMX_EVENTTYPE>(event),
1184                    static_cast<OMX_U32>(data1),
1185                    static_cast<OMX_U32>(data2));
1186        }
1187
1188        case omx_message::EMPTY_BUFFER_DONE:
1189        {
1190            IOMX::buffer_id bufferID;
1191            CHECK(msg->findPointer("buffer", &bufferID));
1192
1193            return onOMXEmptyBufferDone(bufferID);
1194        }
1195
1196        case omx_message::FILL_BUFFER_DONE:
1197        {
1198            IOMX::buffer_id bufferID;
1199            CHECK(msg->findPointer("buffer", &bufferID));
1200
1201            int32_t rangeOffset, rangeLength, flags;
1202            int64_t timeUs;
1203            void *platformPrivate;
1204            void *dataPtr;
1205
1206            CHECK(msg->findInt32("range_offset", &rangeOffset));
1207            CHECK(msg->findInt32("range_length", &rangeLength));
1208            CHECK(msg->findInt32("flags", &flags));
1209            CHECK(msg->findInt64("timestamp", &timeUs));
1210            CHECK(msg->findPointer("platform_private", &platformPrivate));
1211            CHECK(msg->findPointer("data_ptr", &dataPtr));
1212
1213            return onOMXFillBufferDone(
1214                    bufferID,
1215                    (size_t)rangeOffset, (size_t)rangeLength,
1216                    (OMX_U32)flags,
1217                    timeUs,
1218                    platformPrivate,
1219                    dataPtr);
1220        }
1221
1222        default:
1223            TRESPASS();
1224            break;
1225    }
1226}
1227
1228bool ACodec::BaseState::onOMXEvent(
1229        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1230    if (event != OMX_EventError) {
1231        LOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)",
1232             mCodec->mComponentName.c_str(), event, data1, data2);
1233
1234        return false;
1235    }
1236
1237    LOGE("[%s] ERROR(0x%08lx, 0x%08lx)",
1238         mCodec->mComponentName.c_str(), data1, data2);
1239
1240    mCodec->changeState(mCodec->mErrorState);
1241
1242    return true;
1243}
1244
1245bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) {
1246    LOGV("[%s] onOMXEmptyBufferDone %p",
1247         mCodec->mComponentName.c_str(), bufferID);
1248
1249    BufferInfo *info =
1250        mCodec->findBufferByID(kPortIndexInput, bufferID);
1251
1252    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
1253    info->mStatus = BufferInfo::OWNED_BY_US;
1254
1255    PortMode mode = getPortMode(kPortIndexInput);
1256
1257    switch (mode) {
1258        case KEEP_BUFFERS:
1259            break;
1260
1261        case RESUBMIT_BUFFERS:
1262            postFillThisBuffer(info);
1263            break;
1264
1265        default:
1266        {
1267            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
1268            TRESPASS();  // Not currently used
1269            break;
1270        }
1271    }
1272
1273    return true;
1274}
1275
1276void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) {
1277    if (mCodec->mPortEOS[kPortIndexInput]) {
1278        return;
1279    }
1280
1281    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
1282
1283    sp<AMessage> notify = mCodec->mNotify->dup();
1284    notify->setInt32("what", ACodec::kWhatFillThisBuffer);
1285    notify->setPointer("buffer-id", info->mBufferID);
1286
1287    info->mData->meta()->clear();
1288    notify->setObject("buffer", info->mData);
1289
1290    sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id());
1291    reply->setPointer("buffer-id", info->mBufferID);
1292
1293    notify->setMessage("reply", reply);
1294
1295    notify->post();
1296
1297    info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
1298}
1299
1300void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
1301    IOMX::buffer_id bufferID;
1302    CHECK(msg->findPointer("buffer-id", &bufferID));
1303
1304    sp<RefBase> obj;
1305    int32_t err = OK;
1306    if (!msg->findObject("buffer", &obj)) {
1307        CHECK(msg->findInt32("err", &err));
1308
1309        LOGV("[%s] saw error %d instead of an input buffer",
1310             mCodec->mComponentName.c_str(), err);
1311
1312        obj.clear();
1313    }
1314
1315    sp<ABuffer> buffer = static_cast<ABuffer *>(obj.get());
1316
1317    BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
1318    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM);
1319
1320    info->mStatus = BufferInfo::OWNED_BY_US;
1321
1322    PortMode mode = getPortMode(kPortIndexInput);
1323
1324    switch (mode) {
1325        case KEEP_BUFFERS:
1326        {
1327            if (buffer == NULL) {
1328                mCodec->mPortEOS[kPortIndexInput] = true;
1329            }
1330            break;
1331        }
1332
1333        case RESUBMIT_BUFFERS:
1334        {
1335            if (buffer != NULL) {
1336                CHECK(!mCodec->mPortEOS[kPortIndexInput]);
1337
1338                int64_t timeUs;
1339                CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
1340
1341                OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
1342
1343                int32_t isCSD;
1344                if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) {
1345                    flags |= OMX_BUFFERFLAG_CODECCONFIG;
1346                }
1347
1348                if (buffer != info->mData) {
1349                    if (0 && !(flags & OMX_BUFFERFLAG_CODECCONFIG)) {
1350                        LOGV("[%s] Needs to copy input data.",
1351                             mCodec->mComponentName.c_str());
1352                    }
1353
1354                    CHECK_LE(buffer->size(), info->mData->capacity());
1355                    memcpy(info->mData->data(), buffer->data(), buffer->size());
1356                }
1357
1358                LOGV("[%s] calling emptyBuffer %p",
1359                     mCodec->mComponentName.c_str(), bufferID);
1360
1361                CHECK_EQ(mCodec->mOMX->emptyBuffer(
1362                            mCodec->mNode,
1363                            bufferID,
1364                            0,
1365                            buffer->size(),
1366                            flags,
1367                            timeUs),
1368                         (status_t)OK);
1369
1370                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1371
1372                getMoreInputDataIfPossible();
1373            } else if (!mCodec->mPortEOS[kPortIndexInput]) {
1374                LOGV("[%s] Signalling EOS on the input port",
1375                     mCodec->mComponentName.c_str());
1376
1377                LOGV("[%s] calling emptyBuffer %p",
1378                     mCodec->mComponentName.c_str(), bufferID);
1379
1380                CHECK_EQ(mCodec->mOMX->emptyBuffer(
1381                            mCodec->mNode,
1382                            bufferID,
1383                            0,
1384                            0,
1385                            OMX_BUFFERFLAG_EOS,
1386                            0),
1387                         (status_t)OK);
1388
1389                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1390
1391                mCodec->mPortEOS[kPortIndexInput] = true;
1392            }
1393            break;
1394
1395            default:
1396                CHECK_EQ((int)mode, (int)FREE_BUFFERS);
1397                break;
1398        }
1399    }
1400}
1401
1402void ACodec::BaseState::getMoreInputDataIfPossible() {
1403    if (mCodec->mPortEOS[kPortIndexInput]) {
1404        return;
1405    }
1406
1407    BufferInfo *eligible = NULL;
1408
1409    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
1410        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
1411
1412#if 0
1413        if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) {
1414            // There's already a "read" pending.
1415            return;
1416        }
1417#endif
1418
1419        if (info->mStatus == BufferInfo::OWNED_BY_US) {
1420            eligible = info;
1421        }
1422    }
1423
1424    if (eligible == NULL) {
1425        return;
1426    }
1427
1428    postFillThisBuffer(eligible);
1429}
1430
1431bool ACodec::BaseState::onOMXFillBufferDone(
1432        IOMX::buffer_id bufferID,
1433        size_t rangeOffset, size_t rangeLength,
1434        OMX_U32 flags,
1435        int64_t timeUs,
1436        void *platformPrivate,
1437        void *dataPtr) {
1438    LOGV("[%s] onOMXFillBufferDone %p",
1439         mCodec->mComponentName.c_str(), bufferID);
1440
1441    ssize_t index;
1442    BufferInfo *info =
1443        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
1444
1445    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
1446
1447    info->mStatus = BufferInfo::OWNED_BY_US;
1448
1449    PortMode mode = getPortMode(kPortIndexOutput);
1450
1451    switch (mode) {
1452        case KEEP_BUFFERS:
1453            break;
1454
1455        case RESUBMIT_BUFFERS:
1456        {
1457            if (rangeLength == 0) {
1458                if (!(flags & OMX_BUFFERFLAG_EOS)) {
1459                    LOGV("[%s] calling fillBuffer %p",
1460                         mCodec->mComponentName.c_str(), info->mBufferID);
1461
1462                    CHECK_EQ(mCodec->mOMX->fillBuffer(
1463                                mCodec->mNode, info->mBufferID),
1464                             (status_t)OK);
1465
1466                    info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1467                }
1468            } else {
1469                if (!mCodec->mSentFormat) {
1470                    mCodec->sendFormatChange();
1471                }
1472
1473                if (mCodec->mNativeWindow == NULL) {
1474                    info->mData->setRange(rangeOffset, rangeLength);
1475                }
1476
1477                info->mData->meta()->setInt64("timeUs", timeUs);
1478
1479                sp<AMessage> notify = mCodec->mNotify->dup();
1480                notify->setInt32("what", ACodec::kWhatDrainThisBuffer);
1481                notify->setPointer("buffer-id", info->mBufferID);
1482                notify->setObject("buffer", info->mData);
1483
1484                sp<AMessage> reply =
1485                    new AMessage(kWhatOutputBufferDrained, mCodec->id());
1486
1487                reply->setPointer("buffer-id", info->mBufferID);
1488
1489                notify->setMessage("reply", reply);
1490
1491                notify->post();
1492
1493                info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;
1494            }
1495
1496            if (flags & OMX_BUFFERFLAG_EOS) {
1497                sp<AMessage> notify = mCodec->mNotify->dup();
1498                notify->setInt32("what", ACodec::kWhatEOS);
1499                notify->post();
1500
1501                mCodec->mPortEOS[kPortIndexOutput] = true;
1502            }
1503            break;
1504        }
1505
1506        default:
1507        {
1508            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
1509
1510            CHECK_EQ((status_t)OK,
1511                     mCodec->freeBuffer(kPortIndexOutput, index));
1512            break;
1513        }
1514    }
1515
1516    return true;
1517}
1518
1519void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
1520    IOMX::buffer_id bufferID;
1521    CHECK(msg->findPointer("buffer-id", &bufferID));
1522
1523    ssize_t index;
1524    BufferInfo *info =
1525        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
1526    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
1527
1528    int32_t render;
1529    if (mCodec->mNativeWindow != NULL
1530            && msg->findInt32("render", &render) && render != 0) {
1531        // The client wants this buffer to be rendered.
1532
1533        CHECK_EQ(mCodec->mNativeWindow->queueBuffer(
1534                    mCodec->mNativeWindow.get(),
1535                    info->mGraphicBuffer.get()),
1536                 0);
1537
1538        info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
1539    } else {
1540        info->mStatus = BufferInfo::OWNED_BY_US;
1541    }
1542
1543    PortMode mode = getPortMode(kPortIndexOutput);
1544
1545    switch (mode) {
1546        case KEEP_BUFFERS:
1547        {
1548            // XXX fishy, revisit!!! What about the FREE_BUFFERS case below?
1549
1550            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
1551                // We cannot resubmit the buffer we just rendered, dequeue
1552                // the spare instead.
1553
1554                info = mCodec->dequeueBufferFromNativeWindow();
1555            }
1556            break;
1557        }
1558
1559        case RESUBMIT_BUFFERS:
1560        {
1561            if (!mCodec->mPortEOS[kPortIndexOutput]) {
1562                if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
1563                    // We cannot resubmit the buffer we just rendered, dequeue
1564                    // the spare instead.
1565
1566                    info = mCodec->dequeueBufferFromNativeWindow();
1567                }
1568
1569                LOGV("[%s] calling fillBuffer %p",
1570                     mCodec->mComponentName.c_str(), info->mBufferID);
1571
1572                CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
1573                         (status_t)OK);
1574
1575                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1576            }
1577            break;
1578        }
1579
1580        default:
1581        {
1582            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
1583
1584            CHECK_EQ((status_t)OK,
1585                     mCodec->freeBuffer(kPortIndexOutput, index));
1586            break;
1587        }
1588    }
1589}
1590
1591////////////////////////////////////////////////////////////////////////////////
1592
1593ACodec::UninitializedState::UninitializedState(ACodec *codec)
1594    : BaseState(codec) {
1595}
1596
1597bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
1598    bool handled = false;
1599
1600    switch (msg->what()) {
1601        case ACodec::kWhatSetup:
1602        {
1603            onSetup(msg);
1604
1605            handled = true;
1606            break;
1607        }
1608
1609        case ACodec::kWhatShutdown:
1610        {
1611            sp<AMessage> notify = mCodec->mNotify->dup();
1612            notify->setInt32("what", ACodec::kWhatShutdownCompleted);
1613            notify->post();
1614
1615            handled = true;
1616        }
1617
1618        case ACodec::kWhatFlush:
1619        {
1620            sp<AMessage> notify = mCodec->mNotify->dup();
1621            notify->setInt32("what", ACodec::kWhatFlushCompleted);
1622            notify->post();
1623
1624            handled = true;
1625        }
1626
1627        default:
1628            return BaseState::onMessageReceived(msg);
1629    }
1630
1631    return handled;
1632}
1633
1634void ACodec::UninitializedState::onSetup(
1635        const sp<AMessage> &msg) {
1636    OMXClient client;
1637    CHECK_EQ(client.connect(), (status_t)OK);
1638
1639    sp<IOMX> omx = client.interface();
1640
1641    AString mime;
1642    CHECK(msg->findString("mime", &mime));
1643
1644    AString componentName;
1645
1646    if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) {
1647        componentName = "OMX.Nvidia.h264.decode";
1648    } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) {
1649        componentName = "OMX.google.aac.decoder";
1650    } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_MPEG)) {
1651        componentName = "OMX.Nvidia.mp3.decoder";
1652    } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_MPEG2)) {
1653        componentName = "OMX.Nvidia.mpeg2v.decode";
1654    } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_MPEG4)) {
1655        componentName = "OMX.google.mpeg4.decoder";
1656    } else {
1657        TRESPASS();
1658    }
1659
1660    sp<CodecObserver> observer = new CodecObserver;
1661
1662    IOMX::node_id node;
1663    CHECK_EQ(omx->allocateNode(componentName.c_str(), observer, &node),
1664             (status_t)OK);
1665
1666    sp<AMessage> notify = new AMessage(kWhatOMXMessage, mCodec->id());
1667    observer->setNotificationMessage(notify);
1668
1669    mCodec->mComponentName = componentName;
1670    mCodec->mOMX = omx;
1671    mCodec->mNode = node;
1672
1673    mCodec->mPortEOS[kPortIndexInput] =
1674        mCodec->mPortEOS[kPortIndexOutput] = false;
1675
1676    mCodec->configureCodec(mime.c_str(), msg);
1677
1678    sp<RefBase> obj;
1679    if (msg->findObject("native-window", &obj)
1680            && strncmp("OMX.google.", componentName.c_str(), 11)) {
1681        sp<NativeWindowWrapper> nativeWindow(
1682                static_cast<NativeWindowWrapper *>(obj.get()));
1683        CHECK(nativeWindow != NULL);
1684        mCodec->mNativeWindow = nativeWindow->getNativeWindow();
1685    }
1686
1687    CHECK_EQ((status_t)OK, mCodec->initNativeWindow());
1688
1689    CHECK_EQ(omx->sendCommand(node, OMX_CommandStateSet, OMX_StateIdle),
1690             (status_t)OK);
1691
1692    mCodec->changeState(mCodec->mLoadedToIdleState);
1693}
1694
1695////////////////////////////////////////////////////////////////////////////////
1696
1697ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec)
1698    : BaseState(codec) {
1699}
1700
1701void ACodec::LoadedToIdleState::stateEntered() {
1702    LOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
1703
1704    CHECK_EQ(allocateBuffers(), (status_t)OK);
1705}
1706
1707status_t ACodec::LoadedToIdleState::allocateBuffers() {
1708    status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput);
1709
1710    if (err != OK) {
1711        return err;
1712    }
1713
1714    return mCodec->allocateBuffersOnPort(kPortIndexOutput);
1715}
1716
1717bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
1718    switch (msg->what()) {
1719        case kWhatShutdown:
1720        {
1721            mCodec->deferMessage(msg);
1722            return true;
1723        }
1724
1725        default:
1726            return BaseState::onMessageReceived(msg);
1727    }
1728}
1729
1730bool ACodec::LoadedToIdleState::onOMXEvent(
1731        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1732    switch (event) {
1733        case OMX_EventCmdComplete:
1734        {
1735            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
1736            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
1737
1738            CHECK_EQ(mCodec->mOMX->sendCommand(
1739                        mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting),
1740                     (status_t)OK);
1741
1742            mCodec->changeState(mCodec->mIdleToExecutingState);
1743
1744            return true;
1745        }
1746
1747        default:
1748            return BaseState::onOMXEvent(event, data1, data2);
1749    }
1750}
1751
1752////////////////////////////////////////////////////////////////////////////////
1753
1754ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec)
1755    : BaseState(codec) {
1756}
1757
1758void ACodec::IdleToExecutingState::stateEntered() {
1759    LOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
1760}
1761
1762bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
1763    switch (msg->what()) {
1764        case kWhatShutdown:
1765        {
1766            mCodec->deferMessage(msg);
1767            return true;
1768        }
1769
1770        default:
1771            return BaseState::onMessageReceived(msg);
1772    }
1773}
1774
1775bool ACodec::IdleToExecutingState::onOMXEvent(
1776        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1777    switch (event) {
1778        case OMX_EventCmdComplete:
1779        {
1780            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
1781            CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting);
1782
1783            mCodec->mExecutingState->resume();
1784            mCodec->changeState(mCodec->mExecutingState);
1785
1786            return true;
1787        }
1788
1789        default:
1790            return BaseState::onOMXEvent(event, data1, data2);
1791    }
1792}
1793
1794////////////////////////////////////////////////////////////////////////////////
1795
1796ACodec::ExecutingState::ExecutingState(ACodec *codec)
1797    : BaseState(codec),
1798      mActive(false) {
1799}
1800
1801ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode(
1802        OMX_U32 portIndex) {
1803    return RESUBMIT_BUFFERS;
1804}
1805
1806void ACodec::ExecutingState::submitOutputBuffers() {
1807    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
1808        BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
1809
1810        if (mCodec->mNativeWindow != NULL) {
1811            CHECK(info->mStatus == BufferInfo::OWNED_BY_US
1812                    || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
1813
1814            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
1815                continue;
1816            }
1817
1818            status_t err = mCodec->mNativeWindow->lockBuffer(
1819                    mCodec->mNativeWindow.get(),
1820                    info->mGraphicBuffer.get());
1821            CHECK_EQ(err, (status_t)OK);
1822        } else {
1823            CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
1824        }
1825
1826        LOGV("[%s] calling fillBuffer %p",
1827             mCodec->mComponentName.c_str(), info->mBufferID);
1828
1829        CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
1830                 (status_t)OK);
1831
1832        info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1833    }
1834}
1835
1836void ACodec::ExecutingState::resume() {
1837    if (mActive) {
1838        LOGV("[%s] We're already active, no need to resume.",
1839             mCodec->mComponentName.c_str());
1840
1841        return;
1842    }
1843
1844    submitOutputBuffers();
1845
1846    // Post the first input buffer.
1847    CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u);
1848    BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(0);
1849
1850    postFillThisBuffer(info);
1851
1852    mActive = true;
1853}
1854
1855void ACodec::ExecutingState::stateEntered() {
1856    LOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
1857
1858    mCodec->processDeferredMessages();
1859}
1860
1861bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) {
1862    bool handled = false;
1863
1864    switch (msg->what()) {
1865        case kWhatShutdown:
1866        {
1867            mActive = false;
1868
1869            CHECK_EQ(mCodec->mOMX->sendCommand(
1870                        mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
1871                     (status_t)OK);
1872
1873            mCodec->changeState(mCodec->mExecutingToIdleState);
1874
1875            handled = true;
1876            break;
1877        }
1878
1879        case kWhatFlush:
1880        {
1881            mActive = false;
1882
1883            CHECK_EQ(mCodec->mOMX->sendCommand(
1884                        mCodec->mNode, OMX_CommandFlush, OMX_ALL),
1885                     (status_t)OK);
1886
1887            mCodec->changeState(mCodec->mFlushingState);
1888
1889            handled = true;
1890            break;
1891        }
1892
1893        case kWhatResume:
1894        {
1895            resume();
1896
1897            handled = true;
1898            break;
1899        }
1900
1901        default:
1902            handled = BaseState::onMessageReceived(msg);
1903            break;
1904    }
1905
1906    return handled;
1907}
1908
1909bool ACodec::ExecutingState::onOMXEvent(
1910        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1911    switch (event) {
1912        case OMX_EventPortSettingsChanged:
1913        {
1914            CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
1915
1916            if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
1917                CHECK_EQ(mCodec->mOMX->sendCommand(
1918                            mCodec->mNode,
1919                            OMX_CommandPortDisable, kPortIndexOutput),
1920                         (status_t)OK);
1921
1922                mCodec->freeOutputBuffersNotOwnedByComponent();
1923
1924                mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
1925            } else if (data2 == OMX_IndexConfigCommonOutputCrop) {
1926                mCodec->mSentFormat = false;
1927            } else {
1928                LOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx",
1929                     mCodec->mComponentName.c_str(), data2);
1930            }
1931
1932            return true;
1933        }
1934
1935        case OMX_EventBufferFlag:
1936        {
1937            return true;
1938        }
1939
1940        default:
1941            return BaseState::onOMXEvent(event, data1, data2);
1942    }
1943}
1944
1945////////////////////////////////////////////////////////////////////////////////
1946
1947ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState(
1948        ACodec *codec)
1949    : BaseState(codec) {
1950}
1951
1952ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode(
1953        OMX_U32 portIndex) {
1954    if (portIndex == kPortIndexOutput) {
1955        return FREE_BUFFERS;
1956    }
1957
1958    CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput);
1959
1960    return RESUBMIT_BUFFERS;
1961}
1962
1963bool ACodec::OutputPortSettingsChangedState::onMessageReceived(
1964        const sp<AMessage> &msg) {
1965    bool handled = false;
1966
1967    switch (msg->what()) {
1968        case kWhatFlush:
1969        case kWhatShutdown:
1970        case kWhatResume:
1971        {
1972            if (msg->what() == kWhatResume) {
1973                LOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
1974            }
1975
1976            mCodec->deferMessage(msg);
1977            handled = true;
1978            break;
1979        }
1980
1981        default:
1982            handled = BaseState::onMessageReceived(msg);
1983            break;
1984    }
1985
1986    return handled;
1987}
1988
1989void ACodec::OutputPortSettingsChangedState::stateEntered() {
1990    LOGV("[%s] Now handling output port settings change",
1991         mCodec->mComponentName.c_str());
1992}
1993
1994bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
1995        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1996    switch (event) {
1997        case OMX_EventCmdComplete:
1998        {
1999            if (data1 == (OMX_U32)OMX_CommandPortDisable) {
2000                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
2001
2002                LOGV("[%s] Output port now disabled.",
2003                        mCodec->mComponentName.c_str());
2004
2005                CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty());
2006                mCodec->mDealer[kPortIndexOutput].clear();
2007
2008                CHECK_EQ(mCodec->mOMX->sendCommand(
2009                            mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput),
2010                         (status_t)OK);
2011
2012                CHECK_EQ(mCodec->allocateBuffersOnPort(kPortIndexOutput),
2013                         (status_t)OK);
2014
2015                return true;
2016            } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
2017                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
2018
2019                mCodec->mSentFormat = false;
2020
2021                LOGV("[%s] Output port now reenabled.",
2022                        mCodec->mComponentName.c_str());
2023
2024                if (mCodec->mExecutingState->active()) {
2025                    mCodec->mExecutingState->submitOutputBuffers();
2026                }
2027
2028                mCodec->changeState(mCodec->mExecutingState);
2029
2030                return true;
2031            }
2032
2033            return false;
2034        }
2035
2036        default:
2037            return false;
2038    }
2039}
2040
2041////////////////////////////////////////////////////////////////////////////////
2042
2043ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec)
2044    : BaseState(codec) {
2045}
2046
2047bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) {
2048    bool handled = false;
2049
2050    switch (msg->what()) {
2051        case kWhatFlush:
2052        {
2053            // Don't send me a flush request if you previously wanted me
2054            // to shutdown.
2055            TRESPASS();
2056            break;
2057        }
2058
2059        case kWhatShutdown:
2060        {
2061            // We're already doing that...
2062
2063            handled = true;
2064            break;
2065        }
2066
2067        default:
2068            handled = BaseState::onMessageReceived(msg);
2069            break;
2070    }
2071
2072    return handled;
2073}
2074
2075void ACodec::ExecutingToIdleState::stateEntered() {
2076    LOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
2077
2078    mCodec->mSentFormat = false;
2079}
2080
2081bool ACodec::ExecutingToIdleState::onOMXEvent(
2082        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2083    switch (event) {
2084        case OMX_EventCmdComplete:
2085        {
2086            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
2087            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
2088
2089            changeStateIfWeOwnAllBuffers();
2090
2091            return true;
2092        }
2093
2094        case OMX_EventPortSettingsChanged:
2095        case OMX_EventBufferFlag:
2096        {
2097            // We're shutting down and don't care about this anymore.
2098            return true;
2099        }
2100
2101        default:
2102            return BaseState::onOMXEvent(event, data1, data2);
2103    }
2104}
2105void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
2106    if (mCodec->allYourBuffersAreBelongToUs()) {
2107        CHECK_EQ(mCodec->mOMX->sendCommand(
2108                    mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded),
2109                 (status_t)OK);
2110
2111        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK);
2112        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK);
2113
2114        mCodec->changeState(mCodec->mIdleToLoadedState);
2115    }
2116}
2117
2118void ACodec::ExecutingToIdleState::onInputBufferFilled(
2119        const sp<AMessage> &msg) {
2120    BaseState::onInputBufferFilled(msg);
2121
2122    changeStateIfWeOwnAllBuffers();
2123}
2124
2125void ACodec::ExecutingToIdleState::onOutputBufferDrained(
2126        const sp<AMessage> &msg) {
2127    BaseState::onOutputBufferDrained(msg);
2128
2129    changeStateIfWeOwnAllBuffers();
2130}
2131
2132////////////////////////////////////////////////////////////////////////////////
2133
2134ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec)
2135    : BaseState(codec) {
2136}
2137
2138bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) {
2139    bool handled = false;
2140
2141    switch (msg->what()) {
2142        case kWhatShutdown:
2143        {
2144            // We're already doing that...
2145
2146            handled = true;
2147            break;
2148        }
2149
2150        case kWhatFlush:
2151        {
2152            // Don't send me a flush request if you previously wanted me
2153            // to shutdown.
2154            TRESPASS();
2155            break;
2156        }
2157
2158        default:
2159            handled = BaseState::onMessageReceived(msg);
2160            break;
2161    }
2162
2163    return handled;
2164}
2165
2166void ACodec::IdleToLoadedState::stateEntered() {
2167    LOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
2168}
2169
2170bool ACodec::IdleToLoadedState::onOMXEvent(
2171        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2172    switch (event) {
2173        case OMX_EventCmdComplete:
2174        {
2175            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
2176            CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded);
2177
2178            LOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
2179
2180            CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
2181
2182            mCodec->mNativeWindow.clear();
2183            mCodec->mNode = NULL;
2184            mCodec->mOMX.clear();
2185            mCodec->mComponentName.clear();
2186
2187            mCodec->changeState(mCodec->mUninitializedState);
2188
2189            sp<AMessage> notify = mCodec->mNotify->dup();
2190            notify->setInt32("what", ACodec::kWhatShutdownCompleted);
2191            notify->post();
2192
2193            return true;
2194        }
2195
2196        default:
2197            return BaseState::onOMXEvent(event, data1, data2);
2198    }
2199}
2200
2201////////////////////////////////////////////////////////////////////////////////
2202
2203ACodec::ErrorState::ErrorState(ACodec *codec)
2204    : BaseState(codec) {
2205}
2206
2207bool ACodec::ErrorState::onMessageReceived(const sp<AMessage> &msg) {
2208    return BaseState::onMessageReceived(msg);
2209}
2210
2211void ACodec::ErrorState::stateEntered() {
2212    LOGV("[%s] Now in ErrorState", mCodec->mComponentName.c_str());
2213}
2214
2215bool ACodec::ErrorState::onOMXEvent(
2216        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2217    LOGV("EVENT(%d, 0x%08lx, 0x%08lx)", event, data1, data2);
2218    return true;
2219}
2220
2221////////////////////////////////////////////////////////////////////////////////
2222
2223ACodec::FlushingState::FlushingState(ACodec *codec)
2224    : BaseState(codec) {
2225}
2226
2227void ACodec::FlushingState::stateEntered() {
2228    LOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());
2229
2230    mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
2231}
2232
2233bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) {
2234    bool handled = false;
2235
2236    switch (msg->what()) {
2237        case kWhatShutdown:
2238        {
2239            mCodec->deferMessage(msg);
2240            break;
2241        }
2242
2243        case kWhatFlush:
2244        {
2245            // We're already doing this right now.
2246            handled = true;
2247            break;
2248        }
2249
2250        default:
2251            handled = BaseState::onMessageReceived(msg);
2252            break;
2253    }
2254
2255    return handled;
2256}
2257
2258bool ACodec::FlushingState::onOMXEvent(
2259        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2260    switch (event) {
2261        case OMX_EventCmdComplete:
2262        {
2263            CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush);
2264
2265            if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
2266                CHECK(!mFlushComplete[data2]);
2267                mFlushComplete[data2] = true;
2268            } else {
2269                CHECK_EQ(data2, OMX_ALL);
2270                CHECK(mFlushComplete[kPortIndexInput]);
2271                CHECK(mFlushComplete[kPortIndexOutput]);
2272
2273                changeStateIfWeOwnAllBuffers();
2274            }
2275
2276            return true;
2277        }
2278
2279        case OMX_EventPortSettingsChanged:
2280        {
2281            sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id());
2282            msg->setInt32("type", omx_message::EVENT);
2283            msg->setPointer("node", mCodec->mNode);
2284            msg->setInt32("event", event);
2285            msg->setInt32("data1", data1);
2286            msg->setInt32("data2", data2);
2287
2288            LOGV("[%s] Deferring OMX_EventPortSettingsChanged",
2289                 mCodec->mComponentName.c_str());
2290
2291            mCodec->deferMessage(msg);
2292
2293            return true;
2294        }
2295
2296        default:
2297            return BaseState::onOMXEvent(event, data1, data2);
2298    }
2299
2300    return true;
2301}
2302
2303void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) {
2304    BaseState::onOutputBufferDrained(msg);
2305
2306    changeStateIfWeOwnAllBuffers();
2307}
2308
2309void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) {
2310    BaseState::onInputBufferFilled(msg);
2311
2312    changeStateIfWeOwnAllBuffers();
2313}
2314
2315void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() {
2316    if (mFlushComplete[kPortIndexInput]
2317            && mFlushComplete[kPortIndexOutput]
2318            && mCodec->allYourBuffersAreBelongToUs()) {
2319        sp<AMessage> notify = mCodec->mNotify->dup();
2320        notify->setInt32("what", ACodec::kWhatFlushCompleted);
2321        notify->post();
2322
2323        mCodec->mPortEOS[kPortIndexInput] =
2324            mCodec->mPortEOS[kPortIndexOutput] = false;
2325
2326        mCodec->changeState(mCodec->mExecutingState);
2327    }
2328}
2329
2330}  // namespace android
2331