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