ACodec.cpp revision 729de186450f78c099637e1fce743fe531862c52
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_AMR_NB,
685            "audio_decoder.amrnb", "audio_encoder.amrnb" },
686        { MEDIA_MIMETYPE_AUDIO_AMR_WB,
687            "audio_decoder.amrwb", "audio_encoder.amrwb" },
688        { MEDIA_MIMETYPE_AUDIO_AAC,
689            "audio_decoder.aac", "audio_encoder.aac" },
690        { MEDIA_MIMETYPE_AUDIO_VORBIS,
691            "audio_decoder.vorbis", "audio_encoder.vorbis" },
692        { MEDIA_MIMETYPE_VIDEO_AVC,
693            "video_decoder.avc", "video_encoder.avc" },
694        { MEDIA_MIMETYPE_VIDEO_MPEG4,
695            "video_decoder.mpeg4", "video_encoder.mpeg4" },
696        { MEDIA_MIMETYPE_VIDEO_H263,
697            "video_decoder.h263", "video_encoder.h263" },
698    };
699
700    static const size_t kNumMimeToRole =
701        sizeof(kMimeToRole) / sizeof(kMimeToRole[0]);
702
703    size_t i;
704    for (i = 0; i < kNumMimeToRole; ++i) {
705        if (!strcasecmp(mime, kMimeToRole[i].mime)) {
706            break;
707        }
708    }
709
710    if (i == kNumMimeToRole) {
711        return;
712    }
713
714    const char *role =
715        isEncoder ? kMimeToRole[i].encoderRole
716                  : kMimeToRole[i].decoderRole;
717
718    if (role != NULL) {
719        OMX_PARAM_COMPONENTROLETYPE roleParams;
720        InitOMXParams(&roleParams);
721
722        strncpy((char *)roleParams.cRole,
723                role, OMX_MAX_STRINGNAME_SIZE - 1);
724
725        roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
726
727        status_t err = mOMX->setParameter(
728                mNode, OMX_IndexParamStandardComponentRole,
729                &roleParams, sizeof(roleParams));
730
731        if (err != OK) {
732            LOGW("[%s] Failed to set standard component role '%s'.",
733                 mComponentName.c_str(), role);
734        }
735    }
736}
737
738void ACodec::configureCodec(
739        const char *mime, const sp<AMessage> &msg) {
740    setComponentRole(false /* isEncoder */, mime);
741
742    if (!strncasecmp(mime, "video/", 6)) {
743        int32_t width, height;
744        CHECK(msg->findInt32("width", &width));
745        CHECK(msg->findInt32("height", &height));
746
747        CHECK_EQ(setupVideoDecoder(mime, width, height),
748                 (status_t)OK);
749    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
750        int32_t numChannels, sampleRate;
751        CHECK(msg->findInt32("channel-count", &numChannels));
752        CHECK(msg->findInt32("sample-rate", &sampleRate));
753
754        CHECK_EQ(setupAACDecoder(numChannels, sampleRate), (status_t)OK);
755    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) {
756        CHECK_EQ(setupAMRDecoder(false /* isWAMR */), (status_t)OK);
757    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
758        CHECK_EQ(setupAMRDecoder(true /* isWAMR */), (status_t)OK);
759    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW)
760            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) {
761        // These are PCM-like formats with a fixed sample rate but
762        // a variable number of channels.
763
764        int32_t numChannels;
765        CHECK(msg->findInt32("channel-count", &numChannels));
766
767        CHECK_EQ(setupG711Decoder(numChannels), (status_t)OK);
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::setupAMRDecoder(bool isWAMR) {
840    OMX_AUDIO_PARAM_AMRTYPE def;
841    InitOMXParams(&def);
842    def.nPortIndex = kPortIndexInput;
843
844    status_t err =
845        mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
846
847    if (err != OK) {
848        return err;
849    }
850
851    def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
852
853    def.eAMRBandMode =
854        isWAMR ? OMX_AUDIO_AMRBandModeWB0 : OMX_AUDIO_AMRBandModeNB0;
855
856    return mOMX->setParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
857}
858
859status_t ACodec::setupG711Decoder(int32_t numChannels) {
860    return setupRawAudioFormat(
861            kPortIndexInput, 8000 /* sampleRate */, numChannels);
862}
863
864status_t ACodec::setupRawAudioFormat(
865        OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) {
866    OMX_PARAM_PORTDEFINITIONTYPE def;
867    InitOMXParams(&def);
868    def.nPortIndex = portIndex;
869
870    status_t err = mOMX->getParameter(
871            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
872
873    if (err != OK) {
874        return err;
875    }
876
877    def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
878
879    err = mOMX->setParameter(
880            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
881
882    if (err != OK) {
883        return err;
884    }
885
886    OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
887    InitOMXParams(&pcmParams);
888    pcmParams.nPortIndex = portIndex;
889
890    err = mOMX->getParameter(
891            mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
892
893    if (err != OK) {
894        return err;
895    }
896
897    pcmParams.nChannels = numChannels;
898    pcmParams.eNumData = OMX_NumericalDataSigned;
899    pcmParams.bInterleaved = OMX_TRUE;
900    pcmParams.nBitPerSample = 16;
901    pcmParams.nSamplingRate = sampleRate;
902    pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
903
904    if (numChannels == 1) {
905        pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelCF;
906    } else {
907        CHECK_EQ(numChannels, 2);
908
909        pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
910        pcmParams.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
911    }
912
913    return mOMX->setParameter(
914            mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
915}
916
917status_t ACodec::setVideoPortFormatType(
918        OMX_U32 portIndex,
919        OMX_VIDEO_CODINGTYPE compressionFormat,
920        OMX_COLOR_FORMATTYPE colorFormat) {
921    OMX_VIDEO_PARAM_PORTFORMATTYPE format;
922    InitOMXParams(&format);
923    format.nPortIndex = portIndex;
924    format.nIndex = 0;
925    bool found = false;
926
927    OMX_U32 index = 0;
928    for (;;) {
929        format.nIndex = index;
930        status_t err = mOMX->getParameter(
931                mNode, OMX_IndexParamVideoPortFormat,
932                &format, sizeof(format));
933
934        if (err != OK) {
935            return err;
936        }
937
938        // The following assertion is violated by TI's video decoder.
939        // CHECK_EQ(format.nIndex, index);
940
941        if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) {
942            if (portIndex == kPortIndexInput
943                    && colorFormat == format.eColorFormat) {
944                // eCompressionFormat does not seem right.
945                found = true;
946                break;
947            }
948            if (portIndex == kPortIndexOutput
949                    && compressionFormat == format.eCompressionFormat) {
950                // eColorFormat does not seem right.
951                found = true;
952                break;
953            }
954        }
955
956        if (format.eCompressionFormat == compressionFormat
957            && format.eColorFormat == colorFormat) {
958            found = true;
959            break;
960        }
961
962        ++index;
963    }
964
965    if (!found) {
966        return UNKNOWN_ERROR;
967    }
968
969    status_t err = mOMX->setParameter(
970            mNode, OMX_IndexParamVideoPortFormat,
971            &format, sizeof(format));
972
973    return err;
974}
975
976status_t ACodec::setSupportedOutputFormat() {
977    OMX_VIDEO_PARAM_PORTFORMATTYPE format;
978    InitOMXParams(&format);
979    format.nPortIndex = kPortIndexOutput;
980    format.nIndex = 0;
981
982    status_t err = mOMX->getParameter(
983            mNode, OMX_IndexParamVideoPortFormat,
984            &format, sizeof(format));
985    CHECK_EQ(err, (status_t)OK);
986    CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused);
987
988    CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar
989           || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
990           || format.eColorFormat == OMX_COLOR_FormatCbYCrY
991           || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar
992           || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar);
993
994    return mOMX->setParameter(
995            mNode, OMX_IndexParamVideoPortFormat,
996            &format, sizeof(format));
997}
998
999status_t ACodec::setupVideoDecoder(
1000        const char *mime, int32_t width, int32_t height) {
1001    OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused;
1002    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
1003        compressionFormat = OMX_VIDEO_CodingAVC;
1004    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
1005        compressionFormat = OMX_VIDEO_CodingMPEG4;
1006    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
1007        compressionFormat = OMX_VIDEO_CodingH263;
1008    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG2, mime)) {
1009        compressionFormat = OMX_VIDEO_CodingMPEG2;
1010    } else {
1011        TRESPASS();
1012    }
1013
1014    status_t err = setVideoPortFormatType(
1015            kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
1016
1017    if (err != OK) {
1018        return err;
1019    }
1020
1021    err = setSupportedOutputFormat();
1022
1023    if (err != OK) {
1024        return err;
1025    }
1026
1027    err = setVideoFormatOnPort(
1028            kPortIndexInput, width, height, compressionFormat);
1029
1030    if (err != OK) {
1031        return err;
1032    }
1033
1034    err = setVideoFormatOnPort(
1035            kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused);
1036
1037    if (err != OK) {
1038        return err;
1039    }
1040
1041    return OK;
1042}
1043
1044status_t ACodec::setVideoFormatOnPort(
1045        OMX_U32 portIndex,
1046        int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat) {
1047    OMX_PARAM_PORTDEFINITIONTYPE def;
1048    InitOMXParams(&def);
1049    def.nPortIndex = portIndex;
1050
1051    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
1052
1053    status_t err = mOMX->getParameter(
1054            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1055
1056    CHECK_EQ(err, (status_t)OK);
1057
1058    if (portIndex == kPortIndexInput) {
1059        // XXX Need a (much) better heuristic to compute input buffer sizes.
1060        const size_t X = 64 * 1024;
1061        if (def.nBufferSize < X) {
1062            def.nBufferSize = X;
1063        }
1064    }
1065
1066    CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
1067
1068    video_def->nFrameWidth = width;
1069    video_def->nFrameHeight = height;
1070
1071    if (portIndex == kPortIndexInput) {
1072        video_def->eCompressionFormat = compressionFormat;
1073        video_def->eColorFormat = OMX_COLOR_FormatUnused;
1074    }
1075
1076    err = mOMX->setParameter(
1077            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1078
1079    return err;
1080}
1081
1082status_t ACodec::initNativeWindow() {
1083    if (mNativeWindow != NULL) {
1084        return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE);
1085    }
1086
1087    mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE);
1088    return OK;
1089}
1090
1091bool ACodec::allYourBuffersAreBelongToUs(
1092        OMX_U32 portIndex) {
1093    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
1094        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
1095
1096        if (info->mStatus != BufferInfo::OWNED_BY_US
1097                && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
1098            LOGV("[%s] Buffer %p on port %ld still has status %d",
1099                    mComponentName.c_str(),
1100                    info->mBufferID, portIndex, info->mStatus);
1101            return false;
1102        }
1103    }
1104
1105    return true;
1106}
1107
1108bool ACodec::allYourBuffersAreBelongToUs() {
1109    return allYourBuffersAreBelongToUs(kPortIndexInput)
1110        && allYourBuffersAreBelongToUs(kPortIndexOutput);
1111}
1112
1113void ACodec::deferMessage(const sp<AMessage> &msg) {
1114    bool wasEmptyBefore = mDeferredQueue.empty();
1115    mDeferredQueue.push_back(msg);
1116}
1117
1118void ACodec::processDeferredMessages() {
1119    List<sp<AMessage> > queue = mDeferredQueue;
1120    mDeferredQueue.clear();
1121
1122    List<sp<AMessage> >::iterator it = queue.begin();
1123    while (it != queue.end()) {
1124        onMessageReceived(*it++);
1125    }
1126}
1127
1128void ACodec::sendFormatChange() {
1129    sp<AMessage> notify = mNotify->dup();
1130    notify->setInt32("what", kWhatOutputFormatChanged);
1131
1132    OMX_PARAM_PORTDEFINITIONTYPE def;
1133    InitOMXParams(&def);
1134    def.nPortIndex = kPortIndexOutput;
1135
1136    CHECK_EQ(mOMX->getParameter(
1137                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)),
1138             (status_t)OK);
1139
1140    CHECK_EQ((int)def.eDir, (int)OMX_DirOutput);
1141
1142    switch (def.eDomain) {
1143        case OMX_PortDomainVideo:
1144        {
1145            OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
1146
1147            notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW);
1148            notify->setInt32("width", videoDef->nFrameWidth);
1149            notify->setInt32("height", videoDef->nFrameHeight);
1150
1151            OMX_CONFIG_RECTTYPE rect;
1152            InitOMXParams(&rect);
1153            rect.nPortIndex = kPortIndexOutput;
1154
1155            if (mOMX->getConfig(
1156                        mNode, OMX_IndexConfigCommonOutputCrop,
1157                        &rect, sizeof(rect)) != OK) {
1158                rect.nLeft = 0;
1159                rect.nTop = 0;
1160                rect.nWidth = videoDef->nFrameWidth;
1161                rect.nHeight = videoDef->nFrameHeight;
1162            }
1163
1164            CHECK_GE(rect.nLeft, 0);
1165            CHECK_GE(rect.nTop, 0);
1166            CHECK_GE(rect.nWidth, 0u);
1167            CHECK_GE(rect.nHeight, 0u);
1168            CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth);
1169            CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight);
1170
1171            notify->setRect(
1172                    "crop",
1173                    rect.nLeft,
1174                    rect.nTop,
1175                    rect.nLeft + rect.nWidth - 1,
1176                    rect.nTop + rect.nHeight - 1);
1177
1178            if (mNativeWindow != NULL) {
1179                android_native_rect_t crop;
1180                crop.left = rect.nLeft;
1181                crop.top = rect.nTop;
1182                crop.right = rect.nLeft + rect.nWidth;
1183                crop.bottom = rect.nTop + rect.nHeight;
1184
1185                CHECK_EQ(0, native_window_set_crop(
1186                            mNativeWindow.get(), &crop));
1187            }
1188            break;
1189        }
1190
1191        case OMX_PortDomainAudio:
1192        {
1193            OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
1194            CHECK_EQ((int)audioDef->eEncoding, (int)OMX_AUDIO_CodingPCM);
1195
1196            OMX_AUDIO_PARAM_PCMMODETYPE params;
1197            InitOMXParams(&params);
1198            params.nPortIndex = kPortIndexOutput;
1199
1200            CHECK_EQ(mOMX->getParameter(
1201                        mNode, OMX_IndexParamAudioPcm,
1202                        &params, sizeof(params)),
1203                     (status_t)OK);
1204
1205            CHECK(params.nChannels == 1 || params.bInterleaved);
1206            CHECK_EQ(params.nBitPerSample, 16u);
1207            CHECK_EQ((int)params.eNumData, (int)OMX_NumericalDataSigned);
1208            CHECK_EQ((int)params.ePCMMode, (int)OMX_AUDIO_PCMModeLinear);
1209
1210            notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
1211            notify->setInt32("channel-count", params.nChannels);
1212            notify->setInt32("sample-rate", params.nSamplingRate);
1213            break;
1214        }
1215
1216        default:
1217            TRESPASS();
1218    }
1219
1220    notify->post();
1221
1222    mSentFormat = true;
1223}
1224
1225void ACodec::signalError(OMX_ERRORTYPE error) {
1226    sp<AMessage> notify = mNotify->dup();
1227    notify->setInt32("what", ACodec::kWhatError);
1228    notify->setInt32("omx-error", error);
1229    notify->post();
1230}
1231
1232////////////////////////////////////////////////////////////////////////////////
1233
1234ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
1235    : AState(parentState),
1236      mCodec(codec) {
1237}
1238
1239ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(OMX_U32 portIndex) {
1240    return KEEP_BUFFERS;
1241}
1242
1243bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) {
1244    switch (msg->what()) {
1245        case kWhatInputBufferFilled:
1246        {
1247            onInputBufferFilled(msg);
1248            break;
1249        }
1250
1251        case kWhatOutputBufferDrained:
1252        {
1253            onOutputBufferDrained(msg);
1254            break;
1255        }
1256
1257        case ACodec::kWhatOMXMessage:
1258        {
1259            return onOMXMessage(msg);
1260        }
1261
1262        default:
1263            return false;
1264    }
1265
1266    return true;
1267}
1268
1269bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) {
1270    int32_t type;
1271    CHECK(msg->findInt32("type", &type));
1272
1273    IOMX::node_id nodeID;
1274    CHECK(msg->findPointer("node", &nodeID));
1275    CHECK_EQ(nodeID, mCodec->mNode);
1276
1277    switch (type) {
1278        case omx_message::EVENT:
1279        {
1280            int32_t event, data1, data2;
1281            CHECK(msg->findInt32("event", &event));
1282            CHECK(msg->findInt32("data1", &data1));
1283            CHECK(msg->findInt32("data2", &data2));
1284
1285            if (event == OMX_EventCmdComplete
1286                    && data1 == OMX_CommandFlush
1287                    && data2 == (int32_t)OMX_ALL) {
1288                // Use of this notification is not consistent across
1289                // implementations. We'll drop this notification and rely
1290                // on flush-complete notifications on the individual port
1291                // indices instead.
1292
1293                return true;
1294            }
1295
1296            return onOMXEvent(
1297                    static_cast<OMX_EVENTTYPE>(event),
1298                    static_cast<OMX_U32>(data1),
1299                    static_cast<OMX_U32>(data2));
1300        }
1301
1302        case omx_message::EMPTY_BUFFER_DONE:
1303        {
1304            IOMX::buffer_id bufferID;
1305            CHECK(msg->findPointer("buffer", &bufferID));
1306
1307            return onOMXEmptyBufferDone(bufferID);
1308        }
1309
1310        case omx_message::FILL_BUFFER_DONE:
1311        {
1312            IOMX::buffer_id bufferID;
1313            CHECK(msg->findPointer("buffer", &bufferID));
1314
1315            int32_t rangeOffset, rangeLength, flags;
1316            int64_t timeUs;
1317            void *platformPrivate;
1318            void *dataPtr;
1319
1320            CHECK(msg->findInt32("range_offset", &rangeOffset));
1321            CHECK(msg->findInt32("range_length", &rangeLength));
1322            CHECK(msg->findInt32("flags", &flags));
1323            CHECK(msg->findInt64("timestamp", &timeUs));
1324            CHECK(msg->findPointer("platform_private", &platformPrivate));
1325            CHECK(msg->findPointer("data_ptr", &dataPtr));
1326
1327            return onOMXFillBufferDone(
1328                    bufferID,
1329                    (size_t)rangeOffset, (size_t)rangeLength,
1330                    (OMX_U32)flags,
1331                    timeUs,
1332                    platformPrivate,
1333                    dataPtr);
1334        }
1335
1336        default:
1337            TRESPASS();
1338            break;
1339    }
1340}
1341
1342bool ACodec::BaseState::onOMXEvent(
1343        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1344    if (event != OMX_EventError) {
1345        LOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)",
1346             mCodec->mComponentName.c_str(), event, data1, data2);
1347
1348        return false;
1349    }
1350
1351    LOGE("[%s] ERROR(0x%08lx)", mCodec->mComponentName.c_str(), data1);
1352
1353    mCodec->signalError((OMX_ERRORTYPE)data1);
1354
1355    return true;
1356}
1357
1358bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) {
1359    LOGV("[%s] onOMXEmptyBufferDone %p",
1360         mCodec->mComponentName.c_str(), bufferID);
1361
1362    BufferInfo *info =
1363        mCodec->findBufferByID(kPortIndexInput, bufferID);
1364
1365    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
1366    info->mStatus = BufferInfo::OWNED_BY_US;
1367
1368    PortMode mode = getPortMode(kPortIndexInput);
1369
1370    switch (mode) {
1371        case KEEP_BUFFERS:
1372            break;
1373
1374        case RESUBMIT_BUFFERS:
1375            postFillThisBuffer(info);
1376            break;
1377
1378        default:
1379        {
1380            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
1381            TRESPASS();  // Not currently used
1382            break;
1383        }
1384    }
1385
1386    return true;
1387}
1388
1389void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) {
1390    if (mCodec->mPortEOS[kPortIndexInput]) {
1391        return;
1392    }
1393
1394    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
1395
1396    sp<AMessage> notify = mCodec->mNotify->dup();
1397    notify->setInt32("what", ACodec::kWhatFillThisBuffer);
1398    notify->setPointer("buffer-id", info->mBufferID);
1399
1400    info->mData->meta()->clear();
1401    notify->setObject("buffer", info->mData);
1402
1403    sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id());
1404    reply->setPointer("buffer-id", info->mBufferID);
1405
1406    notify->setMessage("reply", reply);
1407
1408    notify->post();
1409
1410    info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
1411}
1412
1413void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
1414    IOMX::buffer_id bufferID;
1415    CHECK(msg->findPointer("buffer-id", &bufferID));
1416
1417    sp<RefBase> obj;
1418    int32_t err = OK;
1419    if (!msg->findObject("buffer", &obj)) {
1420        CHECK(msg->findInt32("err", &err));
1421
1422        LOGV("[%s] saw error %d instead of an input buffer",
1423             mCodec->mComponentName.c_str(), err);
1424
1425        obj.clear();
1426    }
1427
1428    sp<ABuffer> buffer = static_cast<ABuffer *>(obj.get());
1429
1430    BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
1431    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM);
1432
1433    info->mStatus = BufferInfo::OWNED_BY_US;
1434
1435    PortMode mode = getPortMode(kPortIndexInput);
1436
1437    switch (mode) {
1438        case KEEP_BUFFERS:
1439        {
1440            if (buffer == NULL) {
1441                if (!mCodec->mPortEOS[kPortIndexInput]) {
1442                    mCodec->mPortEOS[kPortIndexInput] = true;
1443                    mCodec->mInputEOSResult = err;
1444                }
1445            }
1446            break;
1447        }
1448
1449        case RESUBMIT_BUFFERS:
1450        {
1451            if (buffer != NULL) {
1452                CHECK(!mCodec->mPortEOS[kPortIndexInput]);
1453
1454                int64_t timeUs;
1455                CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
1456
1457                OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
1458
1459                int32_t isCSD;
1460                if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) {
1461                    flags |= OMX_BUFFERFLAG_CODECCONFIG;
1462                }
1463
1464                if (buffer != info->mData) {
1465                    if (0 && !(flags & OMX_BUFFERFLAG_CODECCONFIG)) {
1466                        LOGV("[%s] Needs to copy input data.",
1467                             mCodec->mComponentName.c_str());
1468                    }
1469
1470                    CHECK_LE(buffer->size(), info->mData->capacity());
1471                    memcpy(info->mData->data(), buffer->data(), buffer->size());
1472                }
1473
1474                if (flags & OMX_BUFFERFLAG_CODECCONFIG) {
1475                    LOGV("[%s] calling emptyBuffer %p w/ codec specific data",
1476                         mCodec->mComponentName.c_str(), bufferID);
1477                } else {
1478                    LOGV("[%s] calling emptyBuffer %p w/ time %lld us",
1479                         mCodec->mComponentName.c_str(), bufferID, timeUs);
1480                }
1481
1482                CHECK_EQ(mCodec->mOMX->emptyBuffer(
1483                            mCodec->mNode,
1484                            bufferID,
1485                            0,
1486                            buffer->size(),
1487                            flags,
1488                            timeUs),
1489                         (status_t)OK);
1490
1491                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1492
1493                getMoreInputDataIfPossible();
1494            } else if (!mCodec->mPortEOS[kPortIndexInput]) {
1495                if (err != ERROR_END_OF_STREAM) {
1496                    LOGV("[%s] Signalling EOS on the input port "
1497                         "due to error %d",
1498                         mCodec->mComponentName.c_str(), err);
1499                } else {
1500                    LOGV("[%s] Signalling EOS on the input port",
1501                         mCodec->mComponentName.c_str());
1502                }
1503
1504                LOGV("[%s] calling emptyBuffer %p signalling EOS",
1505                     mCodec->mComponentName.c_str(), bufferID);
1506
1507                CHECK_EQ(mCodec->mOMX->emptyBuffer(
1508                            mCodec->mNode,
1509                            bufferID,
1510                            0,
1511                            0,
1512                            OMX_BUFFERFLAG_EOS,
1513                            0),
1514                         (status_t)OK);
1515
1516                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1517
1518                mCodec->mPortEOS[kPortIndexInput] = true;
1519                mCodec->mInputEOSResult = err;
1520            }
1521            break;
1522
1523            default:
1524                CHECK_EQ((int)mode, (int)FREE_BUFFERS);
1525                break;
1526        }
1527    }
1528}
1529
1530void ACodec::BaseState::getMoreInputDataIfPossible() {
1531    if (mCodec->mPortEOS[kPortIndexInput]) {
1532        return;
1533    }
1534
1535    BufferInfo *eligible = NULL;
1536
1537    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
1538        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
1539
1540#if 0
1541        if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) {
1542            // There's already a "read" pending.
1543            return;
1544        }
1545#endif
1546
1547        if (info->mStatus == BufferInfo::OWNED_BY_US) {
1548            eligible = info;
1549        }
1550    }
1551
1552    if (eligible == NULL) {
1553        return;
1554    }
1555
1556    postFillThisBuffer(eligible);
1557}
1558
1559bool ACodec::BaseState::onOMXFillBufferDone(
1560        IOMX::buffer_id bufferID,
1561        size_t rangeOffset, size_t rangeLength,
1562        OMX_U32 flags,
1563        int64_t timeUs,
1564        void *platformPrivate,
1565        void *dataPtr) {
1566    LOGV("[%s] onOMXFillBufferDone %p time %lld us",
1567         mCodec->mComponentName.c_str(), bufferID, timeUs);
1568
1569    ssize_t index;
1570    BufferInfo *info =
1571        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
1572
1573    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
1574
1575    info->mStatus = BufferInfo::OWNED_BY_US;
1576
1577    PortMode mode = getPortMode(kPortIndexOutput);
1578
1579    switch (mode) {
1580        case KEEP_BUFFERS:
1581            break;
1582
1583        case RESUBMIT_BUFFERS:
1584        {
1585            if (rangeLength == 0) {
1586                if (!(flags & OMX_BUFFERFLAG_EOS)) {
1587                    LOGV("[%s] calling fillBuffer %p",
1588                         mCodec->mComponentName.c_str(), info->mBufferID);
1589
1590                    CHECK_EQ(mCodec->mOMX->fillBuffer(
1591                                mCodec->mNode, info->mBufferID),
1592                             (status_t)OK);
1593
1594                    info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1595                }
1596            } else {
1597                if (!mCodec->mSentFormat) {
1598                    mCodec->sendFormatChange();
1599                }
1600
1601                if (mCodec->mNativeWindow == NULL) {
1602                    info->mData->setRange(rangeOffset, rangeLength);
1603                }
1604
1605                info->mData->meta()->setInt64("timeUs", timeUs);
1606
1607                sp<AMessage> notify = mCodec->mNotify->dup();
1608                notify->setInt32("what", ACodec::kWhatDrainThisBuffer);
1609                notify->setPointer("buffer-id", info->mBufferID);
1610                notify->setObject("buffer", info->mData);
1611
1612                sp<AMessage> reply =
1613                    new AMessage(kWhatOutputBufferDrained, mCodec->id());
1614
1615                reply->setPointer("buffer-id", info->mBufferID);
1616
1617                notify->setMessage("reply", reply);
1618
1619                notify->post();
1620
1621                info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;
1622            }
1623
1624            if (flags & OMX_BUFFERFLAG_EOS) {
1625                sp<AMessage> notify = mCodec->mNotify->dup();
1626                notify->setInt32("what", ACodec::kWhatEOS);
1627                notify->setInt32("err", mCodec->mInputEOSResult);
1628                notify->post();
1629
1630                mCodec->mPortEOS[kPortIndexOutput] = true;
1631            }
1632            break;
1633        }
1634
1635        default:
1636        {
1637            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
1638
1639            CHECK_EQ((status_t)OK,
1640                     mCodec->freeBuffer(kPortIndexOutput, index));
1641            break;
1642        }
1643    }
1644
1645    return true;
1646}
1647
1648void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
1649    IOMX::buffer_id bufferID;
1650    CHECK(msg->findPointer("buffer-id", &bufferID));
1651
1652    ssize_t index;
1653    BufferInfo *info =
1654        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
1655    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
1656
1657    int32_t render;
1658    if (mCodec->mNativeWindow != NULL
1659            && msg->findInt32("render", &render) && render != 0) {
1660        // The client wants this buffer to be rendered.
1661
1662        if (mCodec->mNativeWindow->queueBuffer(
1663                    mCodec->mNativeWindow.get(),
1664                    info->mGraphicBuffer.get()) == OK) {
1665            info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
1666        } else {
1667            mCodec->signalError();
1668            info->mStatus = BufferInfo::OWNED_BY_US;
1669        }
1670    } else {
1671        info->mStatus = BufferInfo::OWNED_BY_US;
1672    }
1673
1674    PortMode mode = getPortMode(kPortIndexOutput);
1675
1676    switch (mode) {
1677        case KEEP_BUFFERS:
1678        {
1679            // XXX fishy, revisit!!! What about the FREE_BUFFERS case below?
1680
1681            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
1682                // We cannot resubmit the buffer we just rendered, dequeue
1683                // the spare instead.
1684
1685                info = mCodec->dequeueBufferFromNativeWindow();
1686            }
1687            break;
1688        }
1689
1690        case RESUBMIT_BUFFERS:
1691        {
1692            if (!mCodec->mPortEOS[kPortIndexOutput]) {
1693                if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
1694                    // We cannot resubmit the buffer we just rendered, dequeue
1695                    // the spare instead.
1696
1697                    info = mCodec->dequeueBufferFromNativeWindow();
1698                }
1699
1700                if (info != NULL) {
1701                    LOGV("[%s] calling fillBuffer %p",
1702                         mCodec->mComponentName.c_str(), info->mBufferID);
1703
1704                    CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
1705                             (status_t)OK);
1706
1707                    info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1708                }
1709            }
1710            break;
1711        }
1712
1713        default:
1714        {
1715            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
1716
1717            CHECK_EQ((status_t)OK,
1718                     mCodec->freeBuffer(kPortIndexOutput, index));
1719            break;
1720        }
1721    }
1722}
1723
1724////////////////////////////////////////////////////////////////////////////////
1725
1726ACodec::UninitializedState::UninitializedState(ACodec *codec)
1727    : BaseState(codec) {
1728}
1729
1730bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
1731    bool handled = false;
1732
1733    switch (msg->what()) {
1734        case ACodec::kWhatSetup:
1735        {
1736            onSetup(msg);
1737
1738            handled = true;
1739            break;
1740        }
1741
1742        case ACodec::kWhatShutdown:
1743        {
1744            sp<AMessage> notify = mCodec->mNotify->dup();
1745            notify->setInt32("what", ACodec::kWhatShutdownCompleted);
1746            notify->post();
1747
1748            handled = true;
1749            break;
1750        }
1751
1752        case ACodec::kWhatFlush:
1753        {
1754            sp<AMessage> notify = mCodec->mNotify->dup();
1755            notify->setInt32("what", ACodec::kWhatFlushCompleted);
1756            notify->post();
1757
1758            handled = true;
1759            break;
1760        }
1761
1762        default:
1763            return BaseState::onMessageReceived(msg);
1764    }
1765
1766    return handled;
1767}
1768
1769void ACodec::UninitializedState::onSetup(
1770        const sp<AMessage> &msg) {
1771    OMXClient client;
1772    CHECK_EQ(client.connect(), (status_t)OK);
1773
1774    sp<IOMX> omx = client.interface();
1775
1776    AString mime;
1777    CHECK(msg->findString("mime", &mime));
1778
1779    Vector<String8> matchingCodecs;
1780    OMXCodec::findMatchingCodecs(
1781            mime.c_str(),
1782            false, // createEncoder
1783            NULL,  // matchComponentName
1784            0,     // flags
1785            &matchingCodecs);
1786
1787    sp<CodecObserver> observer = new CodecObserver;
1788    IOMX::node_id node = NULL;
1789
1790    AString componentName;
1791
1792    for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
1793            ++matchIndex) {
1794        componentName = matchingCodecs.itemAt(matchIndex).string();
1795
1796        pid_t tid = androidGetTid();
1797        int prevPriority = androidGetThreadPriority(tid);
1798        androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
1799        status_t err = omx->allocateNode(componentName.c_str(), observer, &node);
1800        androidSetThreadPriority(tid, prevPriority);
1801
1802        if (err == OK) {
1803            break;
1804        }
1805
1806        node = NULL;
1807    }
1808
1809    if (node == NULL) {
1810        LOGE("Unable to instantiate a decoder for type '%s'.", mime.c_str());
1811
1812        mCodec->signalError(OMX_ErrorComponentNotFound);
1813        return;
1814    }
1815
1816    sp<AMessage> notify = new AMessage(kWhatOMXMessage, mCodec->id());
1817    observer->setNotificationMessage(notify);
1818
1819    mCodec->mComponentName = componentName;
1820    mCodec->mOMX = omx;
1821    mCodec->mNode = node;
1822
1823    mCodec->mPortEOS[kPortIndexInput] =
1824        mCodec->mPortEOS[kPortIndexOutput] = false;
1825
1826    mCodec->mInputEOSResult = OK;
1827
1828    mCodec->configureCodec(mime.c_str(), msg);
1829
1830    sp<RefBase> obj;
1831    if (msg->findObject("native-window", &obj)
1832            && strncmp("OMX.google.", componentName.c_str(), 11)) {
1833        sp<NativeWindowWrapper> nativeWindow(
1834                static_cast<NativeWindowWrapper *>(obj.get()));
1835        CHECK(nativeWindow != NULL);
1836        mCodec->mNativeWindow = nativeWindow->getNativeWindow();
1837    }
1838
1839    CHECK_EQ((status_t)OK, mCodec->initNativeWindow());
1840
1841    CHECK_EQ(omx->sendCommand(node, OMX_CommandStateSet, OMX_StateIdle),
1842             (status_t)OK);
1843
1844    mCodec->changeState(mCodec->mLoadedToIdleState);
1845}
1846
1847////////////////////////////////////////////////////////////////////////////////
1848
1849ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec)
1850    : BaseState(codec) {
1851}
1852
1853void ACodec::LoadedToIdleState::stateEntered() {
1854    LOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
1855
1856    status_t err;
1857    if ((err = allocateBuffers()) != OK) {
1858        LOGE("Failed to allocate buffers after transitioning to IDLE state "
1859             "(error 0x%08x)",
1860             err);
1861
1862        mCodec->signalError();
1863    }
1864}
1865
1866status_t ACodec::LoadedToIdleState::allocateBuffers() {
1867    status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput);
1868
1869    if (err != OK) {
1870        return err;
1871    }
1872
1873    return mCodec->allocateBuffersOnPort(kPortIndexOutput);
1874}
1875
1876bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
1877    switch (msg->what()) {
1878        case kWhatShutdown:
1879        {
1880            mCodec->deferMessage(msg);
1881            return true;
1882        }
1883
1884        default:
1885            return BaseState::onMessageReceived(msg);
1886    }
1887}
1888
1889bool ACodec::LoadedToIdleState::onOMXEvent(
1890        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1891    switch (event) {
1892        case OMX_EventCmdComplete:
1893        {
1894            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
1895            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
1896
1897            CHECK_EQ(mCodec->mOMX->sendCommand(
1898                        mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting),
1899                     (status_t)OK);
1900
1901            mCodec->changeState(mCodec->mIdleToExecutingState);
1902
1903            return true;
1904        }
1905
1906        default:
1907            return BaseState::onOMXEvent(event, data1, data2);
1908    }
1909}
1910
1911////////////////////////////////////////////////////////////////////////////////
1912
1913ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec)
1914    : BaseState(codec) {
1915}
1916
1917void ACodec::IdleToExecutingState::stateEntered() {
1918    LOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
1919}
1920
1921bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
1922    switch (msg->what()) {
1923        case kWhatShutdown:
1924        {
1925            mCodec->deferMessage(msg);
1926            return true;
1927        }
1928
1929        default:
1930            return BaseState::onMessageReceived(msg);
1931    }
1932}
1933
1934bool ACodec::IdleToExecutingState::onOMXEvent(
1935        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1936    switch (event) {
1937        case OMX_EventCmdComplete:
1938        {
1939            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
1940            CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting);
1941
1942            mCodec->mExecutingState->resume();
1943            mCodec->changeState(mCodec->mExecutingState);
1944
1945            return true;
1946        }
1947
1948        default:
1949            return BaseState::onOMXEvent(event, data1, data2);
1950    }
1951}
1952
1953////////////////////////////////////////////////////////////////////////////////
1954
1955ACodec::ExecutingState::ExecutingState(ACodec *codec)
1956    : BaseState(codec),
1957      mActive(false) {
1958}
1959
1960ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode(
1961        OMX_U32 portIndex) {
1962    return RESUBMIT_BUFFERS;
1963}
1964
1965void ACodec::ExecutingState::submitOutputBuffers() {
1966    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
1967        BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
1968
1969        if (mCodec->mNativeWindow != NULL) {
1970            CHECK(info->mStatus == BufferInfo::OWNED_BY_US
1971                    || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
1972
1973            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
1974                continue;
1975            }
1976
1977            status_t err = mCodec->mNativeWindow->lockBuffer(
1978                    mCodec->mNativeWindow.get(),
1979                    info->mGraphicBuffer.get());
1980            CHECK_EQ(err, (status_t)OK);
1981        } else {
1982            CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
1983        }
1984
1985        LOGV("[%s] calling fillBuffer %p",
1986             mCodec->mComponentName.c_str(), info->mBufferID);
1987
1988        CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
1989                 (status_t)OK);
1990
1991        info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1992    }
1993}
1994
1995void ACodec::ExecutingState::resume() {
1996    if (mActive) {
1997        LOGV("[%s] We're already active, no need to resume.",
1998             mCodec->mComponentName.c_str());
1999
2000        return;
2001    }
2002
2003    submitOutputBuffers();
2004
2005    // Post the first input buffer.
2006    CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u);
2007    BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(0);
2008
2009    postFillThisBuffer(info);
2010
2011    mActive = true;
2012}
2013
2014void ACodec::ExecutingState::stateEntered() {
2015    LOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
2016
2017    mCodec->processDeferredMessages();
2018}
2019
2020bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) {
2021    bool handled = false;
2022
2023    switch (msg->what()) {
2024        case kWhatShutdown:
2025        {
2026            mActive = false;
2027
2028            CHECK_EQ(mCodec->mOMX->sendCommand(
2029                        mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
2030                     (status_t)OK);
2031
2032            mCodec->changeState(mCodec->mExecutingToIdleState);
2033
2034            handled = true;
2035            break;
2036        }
2037
2038        case kWhatFlush:
2039        {
2040            mActive = false;
2041
2042            CHECK_EQ(mCodec->mOMX->sendCommand(
2043                        mCodec->mNode, OMX_CommandFlush, OMX_ALL),
2044                     (status_t)OK);
2045
2046            mCodec->changeState(mCodec->mFlushingState);
2047
2048            handled = true;
2049            break;
2050        }
2051
2052        case kWhatResume:
2053        {
2054            resume();
2055
2056            handled = true;
2057            break;
2058        }
2059
2060        default:
2061            handled = BaseState::onMessageReceived(msg);
2062            break;
2063    }
2064
2065    return handled;
2066}
2067
2068bool ACodec::ExecutingState::onOMXEvent(
2069        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2070    switch (event) {
2071        case OMX_EventPortSettingsChanged:
2072        {
2073            CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
2074
2075            if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
2076                CHECK_EQ(mCodec->mOMX->sendCommand(
2077                            mCodec->mNode,
2078                            OMX_CommandPortDisable, kPortIndexOutput),
2079                         (status_t)OK);
2080
2081                mCodec->freeOutputBuffersNotOwnedByComponent();
2082
2083                mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
2084            } else if (data2 == OMX_IndexConfigCommonOutputCrop) {
2085                mCodec->mSentFormat = false;
2086            } else {
2087                LOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx",
2088                     mCodec->mComponentName.c_str(), data2);
2089            }
2090
2091            return true;
2092        }
2093
2094        case OMX_EventBufferFlag:
2095        {
2096            return true;
2097        }
2098
2099        default:
2100            return BaseState::onOMXEvent(event, data1, data2);
2101    }
2102}
2103
2104////////////////////////////////////////////////////////////////////////////////
2105
2106ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState(
2107        ACodec *codec)
2108    : BaseState(codec) {
2109}
2110
2111ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode(
2112        OMX_U32 portIndex) {
2113    if (portIndex == kPortIndexOutput) {
2114        return FREE_BUFFERS;
2115    }
2116
2117    CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput);
2118
2119    return RESUBMIT_BUFFERS;
2120}
2121
2122bool ACodec::OutputPortSettingsChangedState::onMessageReceived(
2123        const sp<AMessage> &msg) {
2124    bool handled = false;
2125
2126    switch (msg->what()) {
2127        case kWhatFlush:
2128        case kWhatShutdown:
2129        case kWhatResume:
2130        {
2131            if (msg->what() == kWhatResume) {
2132                LOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
2133            }
2134
2135            mCodec->deferMessage(msg);
2136            handled = true;
2137            break;
2138        }
2139
2140        default:
2141            handled = BaseState::onMessageReceived(msg);
2142            break;
2143    }
2144
2145    return handled;
2146}
2147
2148void ACodec::OutputPortSettingsChangedState::stateEntered() {
2149    LOGV("[%s] Now handling output port settings change",
2150         mCodec->mComponentName.c_str());
2151}
2152
2153bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
2154        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2155    switch (event) {
2156        case OMX_EventCmdComplete:
2157        {
2158            if (data1 == (OMX_U32)OMX_CommandPortDisable) {
2159                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
2160
2161                LOGV("[%s] Output port now disabled.",
2162                        mCodec->mComponentName.c_str());
2163
2164                CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty());
2165                mCodec->mDealer[kPortIndexOutput].clear();
2166
2167                CHECK_EQ(mCodec->mOMX->sendCommand(
2168                            mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput),
2169                         (status_t)OK);
2170
2171                status_t err;
2172                if ((err = mCodec->allocateBuffersOnPort(
2173                                kPortIndexOutput)) != OK) {
2174                    LOGE("Failed to allocate output port buffers after "
2175                         "port reconfiguration (error 0x%08x)",
2176                         err);
2177
2178                    mCodec->signalError();
2179                }
2180
2181                return true;
2182            } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
2183                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
2184
2185                mCodec->mSentFormat = false;
2186
2187                LOGV("[%s] Output port now reenabled.",
2188                        mCodec->mComponentName.c_str());
2189
2190                if (mCodec->mExecutingState->active()) {
2191                    mCodec->mExecutingState->submitOutputBuffers();
2192                }
2193
2194                mCodec->changeState(mCodec->mExecutingState);
2195
2196                return true;
2197            }
2198
2199            return false;
2200        }
2201
2202        default:
2203            return false;
2204    }
2205}
2206
2207////////////////////////////////////////////////////////////////////////////////
2208
2209ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec)
2210    : BaseState(codec) {
2211}
2212
2213bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) {
2214    bool handled = false;
2215
2216    switch (msg->what()) {
2217        case kWhatFlush:
2218        {
2219            // Don't send me a flush request if you previously wanted me
2220            // to shutdown.
2221            TRESPASS();
2222            break;
2223        }
2224
2225        case kWhatShutdown:
2226        {
2227            // We're already doing that...
2228
2229            handled = true;
2230            break;
2231        }
2232
2233        default:
2234            handled = BaseState::onMessageReceived(msg);
2235            break;
2236    }
2237
2238    return handled;
2239}
2240
2241void ACodec::ExecutingToIdleState::stateEntered() {
2242    LOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
2243
2244    mCodec->mSentFormat = false;
2245}
2246
2247bool ACodec::ExecutingToIdleState::onOMXEvent(
2248        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2249    switch (event) {
2250        case OMX_EventCmdComplete:
2251        {
2252            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
2253            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
2254
2255            changeStateIfWeOwnAllBuffers();
2256
2257            return true;
2258        }
2259
2260        case OMX_EventPortSettingsChanged:
2261        case OMX_EventBufferFlag:
2262        {
2263            // We're shutting down and don't care about this anymore.
2264            return true;
2265        }
2266
2267        default:
2268            return BaseState::onOMXEvent(event, data1, data2);
2269    }
2270}
2271
2272void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
2273    if (mCodec->allYourBuffersAreBelongToUs()) {
2274        CHECK_EQ(mCodec->mOMX->sendCommand(
2275                    mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded),
2276                 (status_t)OK);
2277
2278        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK);
2279        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK);
2280
2281        mCodec->changeState(mCodec->mIdleToLoadedState);
2282    }
2283}
2284
2285void ACodec::ExecutingToIdleState::onInputBufferFilled(
2286        const sp<AMessage> &msg) {
2287    BaseState::onInputBufferFilled(msg);
2288
2289    changeStateIfWeOwnAllBuffers();
2290}
2291
2292void ACodec::ExecutingToIdleState::onOutputBufferDrained(
2293        const sp<AMessage> &msg) {
2294    BaseState::onOutputBufferDrained(msg);
2295
2296    changeStateIfWeOwnAllBuffers();
2297}
2298
2299////////////////////////////////////////////////////////////////////////////////
2300
2301ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec)
2302    : BaseState(codec) {
2303}
2304
2305bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) {
2306    bool handled = false;
2307
2308    switch (msg->what()) {
2309        case kWhatShutdown:
2310        {
2311            // We're already doing that...
2312
2313            handled = true;
2314            break;
2315        }
2316
2317        case kWhatFlush:
2318        {
2319            // Don't send me a flush request if you previously wanted me
2320            // to shutdown.
2321            TRESPASS();
2322            break;
2323        }
2324
2325        default:
2326            handled = BaseState::onMessageReceived(msg);
2327            break;
2328    }
2329
2330    return handled;
2331}
2332
2333void ACodec::IdleToLoadedState::stateEntered() {
2334    LOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
2335}
2336
2337bool ACodec::IdleToLoadedState::onOMXEvent(
2338        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2339    switch (event) {
2340        case OMX_EventCmdComplete:
2341        {
2342            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
2343            CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded);
2344
2345            LOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
2346
2347            CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
2348
2349            mCodec->mNativeWindow.clear();
2350            mCodec->mNode = NULL;
2351            mCodec->mOMX.clear();
2352            mCodec->mComponentName.clear();
2353
2354            mCodec->changeState(mCodec->mUninitializedState);
2355
2356            sp<AMessage> notify = mCodec->mNotify->dup();
2357            notify->setInt32("what", ACodec::kWhatShutdownCompleted);
2358            notify->post();
2359
2360            return true;
2361        }
2362
2363        default:
2364            return BaseState::onOMXEvent(event, data1, data2);
2365    }
2366}
2367
2368////////////////////////////////////////////////////////////////////////////////
2369
2370ACodec::FlushingState::FlushingState(ACodec *codec)
2371    : BaseState(codec) {
2372}
2373
2374void ACodec::FlushingState::stateEntered() {
2375    LOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());
2376
2377    mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
2378}
2379
2380bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) {
2381    bool handled = false;
2382
2383    switch (msg->what()) {
2384        case kWhatShutdown:
2385        {
2386            mCodec->deferMessage(msg);
2387            break;
2388        }
2389
2390        case kWhatFlush:
2391        {
2392            // We're already doing this right now.
2393            handled = true;
2394            break;
2395        }
2396
2397        default:
2398            handled = BaseState::onMessageReceived(msg);
2399            break;
2400    }
2401
2402    return handled;
2403}
2404
2405bool ACodec::FlushingState::onOMXEvent(
2406        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2407    switch (event) {
2408        case OMX_EventCmdComplete:
2409        {
2410            CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush);
2411
2412            if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
2413                CHECK(!mFlushComplete[data2]);
2414                mFlushComplete[data2] = true;
2415
2416                if (mFlushComplete[kPortIndexInput]
2417                        && mFlushComplete[kPortIndexOutput]) {
2418                    changeStateIfWeOwnAllBuffers();
2419                }
2420            } else {
2421                CHECK_EQ(data2, OMX_ALL);
2422                CHECK(mFlushComplete[kPortIndexInput]);
2423                CHECK(mFlushComplete[kPortIndexOutput]);
2424
2425                changeStateIfWeOwnAllBuffers();
2426            }
2427
2428            return true;
2429        }
2430
2431        case OMX_EventPortSettingsChanged:
2432        {
2433            sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id());
2434            msg->setInt32("type", omx_message::EVENT);
2435            msg->setPointer("node", mCodec->mNode);
2436            msg->setInt32("event", event);
2437            msg->setInt32("data1", data1);
2438            msg->setInt32("data2", data2);
2439
2440            LOGV("[%s] Deferring OMX_EventPortSettingsChanged",
2441                 mCodec->mComponentName.c_str());
2442
2443            mCodec->deferMessage(msg);
2444
2445            return true;
2446        }
2447
2448        default:
2449            return BaseState::onOMXEvent(event, data1, data2);
2450    }
2451
2452    return true;
2453}
2454
2455void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) {
2456    BaseState::onOutputBufferDrained(msg);
2457
2458    changeStateIfWeOwnAllBuffers();
2459}
2460
2461void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) {
2462    BaseState::onInputBufferFilled(msg);
2463
2464    changeStateIfWeOwnAllBuffers();
2465}
2466
2467void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() {
2468    if (mFlushComplete[kPortIndexInput]
2469            && mFlushComplete[kPortIndexOutput]
2470            && mCodec->allYourBuffersAreBelongToUs()) {
2471        sp<AMessage> notify = mCodec->mNotify->dup();
2472        notify->setInt32("what", ACodec::kWhatFlushCompleted);
2473        notify->post();
2474
2475        mCodec->mPortEOS[kPortIndexInput] =
2476            mCodec->mPortEOS[kPortIndexOutput] = false;
2477
2478        mCodec->mInputEOSResult = OK;
2479
2480        mCodec->changeState(mCodec->mExecutingState);
2481    }
2482}
2483
2484}  // namespace android
2485