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