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