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