ACodec.cpp revision c92fd24c10a6bf80b346d7e261325434d9c6964b
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
1134////////////////////////////////////////////////////////////////////////////////
1135
1136ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
1137    : AState(parentState),
1138      mCodec(codec) {
1139}
1140
1141ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(OMX_U32 portIndex) {
1142    return KEEP_BUFFERS;
1143}
1144
1145bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) {
1146    switch (msg->what()) {
1147        case kWhatInputBufferFilled:
1148        {
1149            onInputBufferFilled(msg);
1150            break;
1151        }
1152
1153        case kWhatOutputBufferDrained:
1154        {
1155            onOutputBufferDrained(msg);
1156            break;
1157        }
1158
1159        case ACodec::kWhatOMXMessage:
1160        {
1161            return onOMXMessage(msg);
1162        }
1163
1164        default:
1165            return false;
1166    }
1167
1168    return true;
1169}
1170
1171bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) {
1172    int32_t type;
1173    CHECK(msg->findInt32("type", &type));
1174
1175    IOMX::node_id nodeID;
1176    CHECK(msg->findPointer("node", &nodeID));
1177    CHECK_EQ(nodeID, mCodec->mNode);
1178
1179    switch (type) {
1180        case omx_message::EVENT:
1181        {
1182            int32_t event, data1, data2;
1183            CHECK(msg->findInt32("event", &event));
1184            CHECK(msg->findInt32("data1", &data1));
1185            CHECK(msg->findInt32("data2", &data2));
1186
1187            if (event == OMX_EventCmdComplete
1188                    && data1 == OMX_CommandFlush
1189                    && data2 == (int32_t)OMX_ALL) {
1190                // Use of this notification is not consistent across
1191                // implementations. We'll drop this notification and rely
1192                // on flush-complete notifications on the individual port
1193                // indices instead.
1194
1195                return true;
1196            }
1197
1198            return onOMXEvent(
1199                    static_cast<OMX_EVENTTYPE>(event),
1200                    static_cast<OMX_U32>(data1),
1201                    static_cast<OMX_U32>(data2));
1202        }
1203
1204        case omx_message::EMPTY_BUFFER_DONE:
1205        {
1206            IOMX::buffer_id bufferID;
1207            CHECK(msg->findPointer("buffer", &bufferID));
1208
1209            return onOMXEmptyBufferDone(bufferID);
1210        }
1211
1212        case omx_message::FILL_BUFFER_DONE:
1213        {
1214            IOMX::buffer_id bufferID;
1215            CHECK(msg->findPointer("buffer", &bufferID));
1216
1217            int32_t rangeOffset, rangeLength, flags;
1218            int64_t timeUs;
1219            void *platformPrivate;
1220            void *dataPtr;
1221
1222            CHECK(msg->findInt32("range_offset", &rangeOffset));
1223            CHECK(msg->findInt32("range_length", &rangeLength));
1224            CHECK(msg->findInt32("flags", &flags));
1225            CHECK(msg->findInt64("timestamp", &timeUs));
1226            CHECK(msg->findPointer("platform_private", &platformPrivate));
1227            CHECK(msg->findPointer("data_ptr", &dataPtr));
1228
1229            return onOMXFillBufferDone(
1230                    bufferID,
1231                    (size_t)rangeOffset, (size_t)rangeLength,
1232                    (OMX_U32)flags,
1233                    timeUs,
1234                    platformPrivate,
1235                    dataPtr);
1236        }
1237
1238        default:
1239            TRESPASS();
1240            break;
1241    }
1242}
1243
1244bool ACodec::BaseState::onOMXEvent(
1245        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1246    if (event != OMX_EventError) {
1247        LOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)",
1248             mCodec->mComponentName.c_str(), event, data1, data2);
1249
1250        return false;
1251    }
1252
1253    LOGE("[%s] ERROR(0x%08lx)", mCodec->mComponentName.c_str(), data1);
1254
1255    sp<AMessage> notify = mCodec->mNotify->dup();
1256    notify->setInt32("what", ACodec::kWhatError);
1257    notify->setInt32("omx-error", data1);
1258    notify->post();
1259
1260    return true;
1261}
1262
1263bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) {
1264    LOGV("[%s] onOMXEmptyBufferDone %p",
1265         mCodec->mComponentName.c_str(), bufferID);
1266
1267    BufferInfo *info =
1268        mCodec->findBufferByID(kPortIndexInput, bufferID);
1269
1270    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
1271    info->mStatus = BufferInfo::OWNED_BY_US;
1272
1273    PortMode mode = getPortMode(kPortIndexInput);
1274
1275    switch (mode) {
1276        case KEEP_BUFFERS:
1277            break;
1278
1279        case RESUBMIT_BUFFERS:
1280            postFillThisBuffer(info);
1281            break;
1282
1283        default:
1284        {
1285            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
1286            TRESPASS();  // Not currently used
1287            break;
1288        }
1289    }
1290
1291    return true;
1292}
1293
1294void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) {
1295    if (mCodec->mPortEOS[kPortIndexInput]) {
1296        return;
1297    }
1298
1299    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
1300
1301    sp<AMessage> notify = mCodec->mNotify->dup();
1302    notify->setInt32("what", ACodec::kWhatFillThisBuffer);
1303    notify->setPointer("buffer-id", info->mBufferID);
1304
1305    info->mData->meta()->clear();
1306    notify->setObject("buffer", info->mData);
1307
1308    sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id());
1309    reply->setPointer("buffer-id", info->mBufferID);
1310
1311    notify->setMessage("reply", reply);
1312
1313    notify->post();
1314
1315    info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
1316}
1317
1318void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
1319    IOMX::buffer_id bufferID;
1320    CHECK(msg->findPointer("buffer-id", &bufferID));
1321
1322    sp<RefBase> obj;
1323    int32_t err = OK;
1324    if (!msg->findObject("buffer", &obj)) {
1325        CHECK(msg->findInt32("err", &err));
1326
1327        LOGV("[%s] saw error %d instead of an input buffer",
1328             mCodec->mComponentName.c_str(), err);
1329
1330        obj.clear();
1331    }
1332
1333    sp<ABuffer> buffer = static_cast<ABuffer *>(obj.get());
1334
1335    BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
1336    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM);
1337
1338    info->mStatus = BufferInfo::OWNED_BY_US;
1339
1340    PortMode mode = getPortMode(kPortIndexInput);
1341
1342    switch (mode) {
1343        case KEEP_BUFFERS:
1344        {
1345            if (buffer == NULL) {
1346                mCodec->mPortEOS[kPortIndexInput] = true;
1347            }
1348            break;
1349        }
1350
1351        case RESUBMIT_BUFFERS:
1352        {
1353            if (buffer != NULL) {
1354                CHECK(!mCodec->mPortEOS[kPortIndexInput]);
1355
1356                int64_t timeUs;
1357                CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
1358
1359                OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
1360
1361                int32_t isCSD;
1362                if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) {
1363                    flags |= OMX_BUFFERFLAG_CODECCONFIG;
1364                }
1365
1366                if (buffer != info->mData) {
1367                    if (0 && !(flags & OMX_BUFFERFLAG_CODECCONFIG)) {
1368                        LOGV("[%s] Needs to copy input data.",
1369                             mCodec->mComponentName.c_str());
1370                    }
1371
1372                    CHECK_LE(buffer->size(), info->mData->capacity());
1373                    memcpy(info->mData->data(), buffer->data(), buffer->size());
1374                }
1375
1376                LOGV("[%s] calling emptyBuffer %p",
1377                     mCodec->mComponentName.c_str(), bufferID);
1378
1379                CHECK_EQ(mCodec->mOMX->emptyBuffer(
1380                            mCodec->mNode,
1381                            bufferID,
1382                            0,
1383                            buffer->size(),
1384                            flags,
1385                            timeUs),
1386                         (status_t)OK);
1387
1388                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1389
1390                getMoreInputDataIfPossible();
1391            } else if (!mCodec->mPortEOS[kPortIndexInput]) {
1392                LOGV("[%s] Signalling EOS on the input port",
1393                     mCodec->mComponentName.c_str());
1394
1395                LOGV("[%s] calling emptyBuffer %p",
1396                     mCodec->mComponentName.c_str(), bufferID);
1397
1398                CHECK_EQ(mCodec->mOMX->emptyBuffer(
1399                            mCodec->mNode,
1400                            bufferID,
1401                            0,
1402                            0,
1403                            OMX_BUFFERFLAG_EOS,
1404                            0),
1405                         (status_t)OK);
1406
1407                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1408
1409                mCodec->mPortEOS[kPortIndexInput] = true;
1410            }
1411            break;
1412
1413            default:
1414                CHECK_EQ((int)mode, (int)FREE_BUFFERS);
1415                break;
1416        }
1417    }
1418}
1419
1420void ACodec::BaseState::getMoreInputDataIfPossible() {
1421    if (mCodec->mPortEOS[kPortIndexInput]) {
1422        return;
1423    }
1424
1425    BufferInfo *eligible = NULL;
1426
1427    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
1428        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
1429
1430#if 0
1431        if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) {
1432            // There's already a "read" pending.
1433            return;
1434        }
1435#endif
1436
1437        if (info->mStatus == BufferInfo::OWNED_BY_US) {
1438            eligible = info;
1439        }
1440    }
1441
1442    if (eligible == NULL) {
1443        return;
1444    }
1445
1446    postFillThisBuffer(eligible);
1447}
1448
1449bool ACodec::BaseState::onOMXFillBufferDone(
1450        IOMX::buffer_id bufferID,
1451        size_t rangeOffset, size_t rangeLength,
1452        OMX_U32 flags,
1453        int64_t timeUs,
1454        void *platformPrivate,
1455        void *dataPtr) {
1456    LOGV("[%s] onOMXFillBufferDone %p",
1457         mCodec->mComponentName.c_str(), bufferID);
1458
1459    ssize_t index;
1460    BufferInfo *info =
1461        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
1462
1463    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
1464
1465    info->mStatus = BufferInfo::OWNED_BY_US;
1466
1467    PortMode mode = getPortMode(kPortIndexOutput);
1468
1469    switch (mode) {
1470        case KEEP_BUFFERS:
1471            break;
1472
1473        case RESUBMIT_BUFFERS:
1474        {
1475            if (rangeLength == 0) {
1476                if (!(flags & OMX_BUFFERFLAG_EOS)) {
1477                    LOGV("[%s] calling fillBuffer %p",
1478                         mCodec->mComponentName.c_str(), info->mBufferID);
1479
1480                    CHECK_EQ(mCodec->mOMX->fillBuffer(
1481                                mCodec->mNode, info->mBufferID),
1482                             (status_t)OK);
1483
1484                    info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1485                }
1486            } else {
1487                if (!mCodec->mSentFormat) {
1488                    mCodec->sendFormatChange();
1489                }
1490
1491                if (mCodec->mNativeWindow == NULL) {
1492                    info->mData->setRange(rangeOffset, rangeLength);
1493                }
1494
1495                info->mData->meta()->setInt64("timeUs", timeUs);
1496
1497                sp<AMessage> notify = mCodec->mNotify->dup();
1498                notify->setInt32("what", ACodec::kWhatDrainThisBuffer);
1499                notify->setPointer("buffer-id", info->mBufferID);
1500                notify->setObject("buffer", info->mData);
1501
1502                sp<AMessage> reply =
1503                    new AMessage(kWhatOutputBufferDrained, mCodec->id());
1504
1505                reply->setPointer("buffer-id", info->mBufferID);
1506
1507                notify->setMessage("reply", reply);
1508
1509                notify->post();
1510
1511                info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;
1512            }
1513
1514            if (flags & OMX_BUFFERFLAG_EOS) {
1515                sp<AMessage> notify = mCodec->mNotify->dup();
1516                notify->setInt32("what", ACodec::kWhatEOS);
1517                notify->post();
1518
1519                mCodec->mPortEOS[kPortIndexOutput] = true;
1520            }
1521            break;
1522        }
1523
1524        default:
1525        {
1526            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
1527
1528            CHECK_EQ((status_t)OK,
1529                     mCodec->freeBuffer(kPortIndexOutput, index));
1530            break;
1531        }
1532    }
1533
1534    return true;
1535}
1536
1537void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
1538    IOMX::buffer_id bufferID;
1539    CHECK(msg->findPointer("buffer-id", &bufferID));
1540
1541    ssize_t index;
1542    BufferInfo *info =
1543        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
1544    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
1545
1546    int32_t render;
1547    if (mCodec->mNativeWindow != NULL
1548            && msg->findInt32("render", &render) && render != 0) {
1549        // The client wants this buffer to be rendered.
1550
1551        CHECK_EQ(mCodec->mNativeWindow->queueBuffer(
1552                    mCodec->mNativeWindow.get(),
1553                    info->mGraphicBuffer.get()),
1554                 0);
1555
1556        info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
1557    } else {
1558        info->mStatus = BufferInfo::OWNED_BY_US;
1559    }
1560
1561    PortMode mode = getPortMode(kPortIndexOutput);
1562
1563    switch (mode) {
1564        case KEEP_BUFFERS:
1565        {
1566            // XXX fishy, revisit!!! What about the FREE_BUFFERS case below?
1567
1568            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
1569                // We cannot resubmit the buffer we just rendered, dequeue
1570                // the spare instead.
1571
1572                info = mCodec->dequeueBufferFromNativeWindow();
1573            }
1574            break;
1575        }
1576
1577        case RESUBMIT_BUFFERS:
1578        {
1579            if (!mCodec->mPortEOS[kPortIndexOutput]) {
1580                if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
1581                    // We cannot resubmit the buffer we just rendered, dequeue
1582                    // the spare instead.
1583
1584                    info = mCodec->dequeueBufferFromNativeWindow();
1585                }
1586
1587                if (info != NULL) {
1588                    LOGV("[%s] calling fillBuffer %p",
1589                         mCodec->mComponentName.c_str(), info->mBufferID);
1590
1591                    CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
1592                             (status_t)OK);
1593
1594                    info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1595                }
1596            }
1597            break;
1598        }
1599
1600        default:
1601        {
1602            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
1603
1604            CHECK_EQ((status_t)OK,
1605                     mCodec->freeBuffer(kPortIndexOutput, index));
1606            break;
1607        }
1608    }
1609}
1610
1611////////////////////////////////////////////////////////////////////////////////
1612
1613ACodec::UninitializedState::UninitializedState(ACodec *codec)
1614    : BaseState(codec) {
1615}
1616
1617bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
1618    bool handled = false;
1619
1620    switch (msg->what()) {
1621        case ACodec::kWhatSetup:
1622        {
1623            onSetup(msg);
1624
1625            handled = true;
1626            break;
1627        }
1628
1629        case ACodec::kWhatShutdown:
1630        {
1631            sp<AMessage> notify = mCodec->mNotify->dup();
1632            notify->setInt32("what", ACodec::kWhatShutdownCompleted);
1633            notify->post();
1634
1635            handled = true;
1636            break;
1637        }
1638
1639        case ACodec::kWhatFlush:
1640        {
1641            sp<AMessage> notify = mCodec->mNotify->dup();
1642            notify->setInt32("what", ACodec::kWhatFlushCompleted);
1643            notify->post();
1644
1645            handled = true;
1646            break;
1647        }
1648
1649        default:
1650            return BaseState::onMessageReceived(msg);
1651    }
1652
1653    return handled;
1654}
1655
1656void ACodec::UninitializedState::onSetup(
1657        const sp<AMessage> &msg) {
1658    OMXClient client;
1659    CHECK_EQ(client.connect(), (status_t)OK);
1660
1661    sp<IOMX> omx = client.interface();
1662
1663    AString mime;
1664    CHECK(msg->findString("mime", &mime));
1665
1666    Vector<String8> matchingCodecs;
1667    OMXCodec::findMatchingCodecs(
1668            mime.c_str(),
1669            false, // createEncoder
1670            NULL,  // matchComponentName
1671            0,     // flags
1672            &matchingCodecs);
1673
1674    sp<CodecObserver> observer = new CodecObserver;
1675    IOMX::node_id node = NULL;
1676
1677    AString componentName;
1678
1679    for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
1680            ++matchIndex) {
1681        componentName = matchingCodecs.itemAt(matchIndex).string();
1682
1683        status_t err = omx->allocateNode(componentName.c_str(), observer, &node);
1684
1685        if (err == OK) {
1686            break;
1687        }
1688
1689        node = NULL;
1690    }
1691
1692    if (node == NULL) {
1693        LOGE("Unable to instantiate a decoder for type '%s'.", mime.c_str());
1694
1695        sp<AMessage> notify = mCodec->mNotify->dup();
1696        notify->setInt32("what", ACodec::kWhatError);
1697        notify->setInt32("omx-error", OMX_ErrorComponentNotFound);
1698        notify->post();
1699
1700        return;
1701    }
1702
1703    sp<AMessage> notify = new AMessage(kWhatOMXMessage, mCodec->id());
1704    observer->setNotificationMessage(notify);
1705
1706    mCodec->mComponentName = componentName;
1707    mCodec->mOMX = omx;
1708    mCodec->mNode = node;
1709
1710    mCodec->mPortEOS[kPortIndexInput] =
1711        mCodec->mPortEOS[kPortIndexOutput] = false;
1712
1713    mCodec->configureCodec(mime.c_str(), msg);
1714
1715    sp<RefBase> obj;
1716    if (msg->findObject("native-window", &obj)
1717            && strncmp("OMX.google.", componentName.c_str(), 11)) {
1718        sp<NativeWindowWrapper> nativeWindow(
1719                static_cast<NativeWindowWrapper *>(obj.get()));
1720        CHECK(nativeWindow != NULL);
1721        mCodec->mNativeWindow = nativeWindow->getNativeWindow();
1722    }
1723
1724    CHECK_EQ((status_t)OK, mCodec->initNativeWindow());
1725
1726    CHECK_EQ(omx->sendCommand(node, OMX_CommandStateSet, OMX_StateIdle),
1727             (status_t)OK);
1728
1729    mCodec->changeState(mCodec->mLoadedToIdleState);
1730}
1731
1732////////////////////////////////////////////////////////////////////////////////
1733
1734ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec)
1735    : BaseState(codec) {
1736}
1737
1738void ACodec::LoadedToIdleState::stateEntered() {
1739    LOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
1740
1741    CHECK_EQ(allocateBuffers(), (status_t)OK);
1742}
1743
1744status_t ACodec::LoadedToIdleState::allocateBuffers() {
1745    status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput);
1746
1747    if (err != OK) {
1748        return err;
1749    }
1750
1751    return mCodec->allocateBuffersOnPort(kPortIndexOutput);
1752}
1753
1754bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
1755    switch (msg->what()) {
1756        case kWhatShutdown:
1757        {
1758            mCodec->deferMessage(msg);
1759            return true;
1760        }
1761
1762        default:
1763            return BaseState::onMessageReceived(msg);
1764    }
1765}
1766
1767bool ACodec::LoadedToIdleState::onOMXEvent(
1768        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1769    switch (event) {
1770        case OMX_EventCmdComplete:
1771        {
1772            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
1773            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
1774
1775            CHECK_EQ(mCodec->mOMX->sendCommand(
1776                        mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting),
1777                     (status_t)OK);
1778
1779            mCodec->changeState(mCodec->mIdleToExecutingState);
1780
1781            return true;
1782        }
1783
1784        default:
1785            return BaseState::onOMXEvent(event, data1, data2);
1786    }
1787}
1788
1789////////////////////////////////////////////////////////////////////////////////
1790
1791ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec)
1792    : BaseState(codec) {
1793}
1794
1795void ACodec::IdleToExecutingState::stateEntered() {
1796    LOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
1797}
1798
1799bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
1800    switch (msg->what()) {
1801        case kWhatShutdown:
1802        {
1803            mCodec->deferMessage(msg);
1804            return true;
1805        }
1806
1807        default:
1808            return BaseState::onMessageReceived(msg);
1809    }
1810}
1811
1812bool ACodec::IdleToExecutingState::onOMXEvent(
1813        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1814    switch (event) {
1815        case OMX_EventCmdComplete:
1816        {
1817            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
1818            CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting);
1819
1820            mCodec->mExecutingState->resume();
1821            mCodec->changeState(mCodec->mExecutingState);
1822
1823            return true;
1824        }
1825
1826        default:
1827            return BaseState::onOMXEvent(event, data1, data2);
1828    }
1829}
1830
1831////////////////////////////////////////////////////////////////////////////////
1832
1833ACodec::ExecutingState::ExecutingState(ACodec *codec)
1834    : BaseState(codec),
1835      mActive(false) {
1836}
1837
1838ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode(
1839        OMX_U32 portIndex) {
1840    return RESUBMIT_BUFFERS;
1841}
1842
1843void ACodec::ExecutingState::submitOutputBuffers() {
1844    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
1845        BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
1846
1847        if (mCodec->mNativeWindow != NULL) {
1848            CHECK(info->mStatus == BufferInfo::OWNED_BY_US
1849                    || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
1850
1851            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
1852                continue;
1853            }
1854
1855            status_t err = mCodec->mNativeWindow->lockBuffer(
1856                    mCodec->mNativeWindow.get(),
1857                    info->mGraphicBuffer.get());
1858            CHECK_EQ(err, (status_t)OK);
1859        } else {
1860            CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
1861        }
1862
1863        LOGV("[%s] calling fillBuffer %p",
1864             mCodec->mComponentName.c_str(), info->mBufferID);
1865
1866        CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
1867                 (status_t)OK);
1868
1869        info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1870    }
1871}
1872
1873void ACodec::ExecutingState::resume() {
1874    if (mActive) {
1875        LOGV("[%s] We're already active, no need to resume.",
1876             mCodec->mComponentName.c_str());
1877
1878        return;
1879    }
1880
1881    submitOutputBuffers();
1882
1883    // Post the first input buffer.
1884    CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u);
1885    BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(0);
1886
1887    postFillThisBuffer(info);
1888
1889    mActive = true;
1890}
1891
1892void ACodec::ExecutingState::stateEntered() {
1893    LOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
1894
1895    mCodec->processDeferredMessages();
1896}
1897
1898bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) {
1899    bool handled = false;
1900
1901    switch (msg->what()) {
1902        case kWhatShutdown:
1903        {
1904            mActive = false;
1905
1906            CHECK_EQ(mCodec->mOMX->sendCommand(
1907                        mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
1908                     (status_t)OK);
1909
1910            mCodec->changeState(mCodec->mExecutingToIdleState);
1911
1912            handled = true;
1913            break;
1914        }
1915
1916        case kWhatFlush:
1917        {
1918            mActive = false;
1919
1920            CHECK_EQ(mCodec->mOMX->sendCommand(
1921                        mCodec->mNode, OMX_CommandFlush, OMX_ALL),
1922                     (status_t)OK);
1923
1924            mCodec->changeState(mCodec->mFlushingState);
1925
1926            handled = true;
1927            break;
1928        }
1929
1930        case kWhatResume:
1931        {
1932            resume();
1933
1934            handled = true;
1935            break;
1936        }
1937
1938        default:
1939            handled = BaseState::onMessageReceived(msg);
1940            break;
1941    }
1942
1943    return handled;
1944}
1945
1946bool ACodec::ExecutingState::onOMXEvent(
1947        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1948    switch (event) {
1949        case OMX_EventPortSettingsChanged:
1950        {
1951            CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
1952
1953            if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
1954                CHECK_EQ(mCodec->mOMX->sendCommand(
1955                            mCodec->mNode,
1956                            OMX_CommandPortDisable, kPortIndexOutput),
1957                         (status_t)OK);
1958
1959                mCodec->freeOutputBuffersNotOwnedByComponent();
1960
1961                mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
1962            } else if (data2 == OMX_IndexConfigCommonOutputCrop) {
1963                mCodec->mSentFormat = false;
1964            } else {
1965                LOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx",
1966                     mCodec->mComponentName.c_str(), data2);
1967            }
1968
1969            return true;
1970        }
1971
1972        case OMX_EventBufferFlag:
1973        {
1974            return true;
1975        }
1976
1977        default:
1978            return BaseState::onOMXEvent(event, data1, data2);
1979    }
1980}
1981
1982////////////////////////////////////////////////////////////////////////////////
1983
1984ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState(
1985        ACodec *codec)
1986    : BaseState(codec) {
1987}
1988
1989ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode(
1990        OMX_U32 portIndex) {
1991    if (portIndex == kPortIndexOutput) {
1992        return FREE_BUFFERS;
1993    }
1994
1995    CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput);
1996
1997    return RESUBMIT_BUFFERS;
1998}
1999
2000bool ACodec::OutputPortSettingsChangedState::onMessageReceived(
2001        const sp<AMessage> &msg) {
2002    bool handled = false;
2003
2004    switch (msg->what()) {
2005        case kWhatFlush:
2006        case kWhatShutdown:
2007        case kWhatResume:
2008        {
2009            if (msg->what() == kWhatResume) {
2010                LOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
2011            }
2012
2013            mCodec->deferMessage(msg);
2014            handled = true;
2015            break;
2016        }
2017
2018        default:
2019            handled = BaseState::onMessageReceived(msg);
2020            break;
2021    }
2022
2023    return handled;
2024}
2025
2026void ACodec::OutputPortSettingsChangedState::stateEntered() {
2027    LOGV("[%s] Now handling output port settings change",
2028         mCodec->mComponentName.c_str());
2029}
2030
2031bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
2032        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2033    switch (event) {
2034        case OMX_EventCmdComplete:
2035        {
2036            if (data1 == (OMX_U32)OMX_CommandPortDisable) {
2037                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
2038
2039                LOGV("[%s] Output port now disabled.",
2040                        mCodec->mComponentName.c_str());
2041
2042                CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty());
2043                mCodec->mDealer[kPortIndexOutput].clear();
2044
2045                CHECK_EQ(mCodec->mOMX->sendCommand(
2046                            mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput),
2047                         (status_t)OK);
2048
2049                CHECK_EQ(mCodec->allocateBuffersOnPort(kPortIndexOutput),
2050                         (status_t)OK);
2051
2052                return true;
2053            } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
2054                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
2055
2056                mCodec->mSentFormat = false;
2057
2058                LOGV("[%s] Output port now reenabled.",
2059                        mCodec->mComponentName.c_str());
2060
2061                if (mCodec->mExecutingState->active()) {
2062                    mCodec->mExecutingState->submitOutputBuffers();
2063                }
2064
2065                mCodec->changeState(mCodec->mExecutingState);
2066
2067                return true;
2068            }
2069
2070            return false;
2071        }
2072
2073        default:
2074            return false;
2075    }
2076}
2077
2078////////////////////////////////////////////////////////////////////////////////
2079
2080ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec)
2081    : BaseState(codec) {
2082}
2083
2084bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) {
2085    bool handled = false;
2086
2087    switch (msg->what()) {
2088        case kWhatFlush:
2089        {
2090            // Don't send me a flush request if you previously wanted me
2091            // to shutdown.
2092            TRESPASS();
2093            break;
2094        }
2095
2096        case kWhatShutdown:
2097        {
2098            // We're already doing that...
2099
2100            handled = true;
2101            break;
2102        }
2103
2104        default:
2105            handled = BaseState::onMessageReceived(msg);
2106            break;
2107    }
2108
2109    return handled;
2110}
2111
2112void ACodec::ExecutingToIdleState::stateEntered() {
2113    LOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
2114
2115    mCodec->mSentFormat = false;
2116}
2117
2118bool ACodec::ExecutingToIdleState::onOMXEvent(
2119        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2120    switch (event) {
2121        case OMX_EventCmdComplete:
2122        {
2123            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
2124            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
2125
2126            changeStateIfWeOwnAllBuffers();
2127
2128            return true;
2129        }
2130
2131        case OMX_EventPortSettingsChanged:
2132        case OMX_EventBufferFlag:
2133        {
2134            // We're shutting down and don't care about this anymore.
2135            return true;
2136        }
2137
2138        default:
2139            return BaseState::onOMXEvent(event, data1, data2);
2140    }
2141}
2142
2143void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
2144    if (mCodec->allYourBuffersAreBelongToUs()) {
2145        CHECK_EQ(mCodec->mOMX->sendCommand(
2146                    mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded),
2147                 (status_t)OK);
2148
2149        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK);
2150        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK);
2151
2152        mCodec->changeState(mCodec->mIdleToLoadedState);
2153    }
2154}
2155
2156void ACodec::ExecutingToIdleState::onInputBufferFilled(
2157        const sp<AMessage> &msg) {
2158    BaseState::onInputBufferFilled(msg);
2159
2160    changeStateIfWeOwnAllBuffers();
2161}
2162
2163void ACodec::ExecutingToIdleState::onOutputBufferDrained(
2164        const sp<AMessage> &msg) {
2165    BaseState::onOutputBufferDrained(msg);
2166
2167    changeStateIfWeOwnAllBuffers();
2168}
2169
2170////////////////////////////////////////////////////////////////////////////////
2171
2172ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec)
2173    : BaseState(codec) {
2174}
2175
2176bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) {
2177    bool handled = false;
2178
2179    switch (msg->what()) {
2180        case kWhatShutdown:
2181        {
2182            // We're already doing that...
2183
2184            handled = true;
2185            break;
2186        }
2187
2188        case kWhatFlush:
2189        {
2190            // Don't send me a flush request if you previously wanted me
2191            // to shutdown.
2192            TRESPASS();
2193            break;
2194        }
2195
2196        default:
2197            handled = BaseState::onMessageReceived(msg);
2198            break;
2199    }
2200
2201    return handled;
2202}
2203
2204void ACodec::IdleToLoadedState::stateEntered() {
2205    LOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
2206}
2207
2208bool ACodec::IdleToLoadedState::onOMXEvent(
2209        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2210    switch (event) {
2211        case OMX_EventCmdComplete:
2212        {
2213            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
2214            CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded);
2215
2216            LOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
2217
2218            CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
2219
2220            mCodec->mNativeWindow.clear();
2221            mCodec->mNode = NULL;
2222            mCodec->mOMX.clear();
2223            mCodec->mComponentName.clear();
2224
2225            mCodec->changeState(mCodec->mUninitializedState);
2226
2227            sp<AMessage> notify = mCodec->mNotify->dup();
2228            notify->setInt32("what", ACodec::kWhatShutdownCompleted);
2229            notify->post();
2230
2231            return true;
2232        }
2233
2234        default:
2235            return BaseState::onOMXEvent(event, data1, data2);
2236    }
2237}
2238
2239////////////////////////////////////////////////////////////////////////////////
2240
2241ACodec::FlushingState::FlushingState(ACodec *codec)
2242    : BaseState(codec) {
2243}
2244
2245void ACodec::FlushingState::stateEntered() {
2246    LOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());
2247
2248    mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
2249}
2250
2251bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) {
2252    bool handled = false;
2253
2254    switch (msg->what()) {
2255        case kWhatShutdown:
2256        {
2257            mCodec->deferMessage(msg);
2258            break;
2259        }
2260
2261        case kWhatFlush:
2262        {
2263            // We're already doing this right now.
2264            handled = true;
2265            break;
2266        }
2267
2268        default:
2269            handled = BaseState::onMessageReceived(msg);
2270            break;
2271    }
2272
2273    return handled;
2274}
2275
2276bool ACodec::FlushingState::onOMXEvent(
2277        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2278    switch (event) {
2279        case OMX_EventCmdComplete:
2280        {
2281            CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush);
2282
2283            if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
2284                CHECK(!mFlushComplete[data2]);
2285                mFlushComplete[data2] = true;
2286
2287                if (mFlushComplete[kPortIndexInput]
2288                        && mFlushComplete[kPortIndexOutput]) {
2289                    changeStateIfWeOwnAllBuffers();
2290                }
2291            } else {
2292                CHECK_EQ(data2, OMX_ALL);
2293                CHECK(mFlushComplete[kPortIndexInput]);
2294                CHECK(mFlushComplete[kPortIndexOutput]);
2295
2296                changeStateIfWeOwnAllBuffers();
2297            }
2298
2299            return true;
2300        }
2301
2302        case OMX_EventPortSettingsChanged:
2303        {
2304            sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id());
2305            msg->setInt32("type", omx_message::EVENT);
2306            msg->setPointer("node", mCodec->mNode);
2307            msg->setInt32("event", event);
2308            msg->setInt32("data1", data1);
2309            msg->setInt32("data2", data2);
2310
2311            LOGV("[%s] Deferring OMX_EventPortSettingsChanged",
2312                 mCodec->mComponentName.c_str());
2313
2314            mCodec->deferMessage(msg);
2315
2316            return true;
2317        }
2318
2319        default:
2320            return BaseState::onOMXEvent(event, data1, data2);
2321    }
2322
2323    return true;
2324}
2325
2326void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) {
2327    BaseState::onOutputBufferDrained(msg);
2328
2329    changeStateIfWeOwnAllBuffers();
2330}
2331
2332void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) {
2333    BaseState::onInputBufferFilled(msg);
2334
2335    changeStateIfWeOwnAllBuffers();
2336}
2337
2338void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() {
2339    if (mFlushComplete[kPortIndexInput]
2340            && mFlushComplete[kPortIndexOutput]
2341            && mCodec->allYourBuffersAreBelongToUs()) {
2342        sp<AMessage> notify = mCodec->mNotify->dup();
2343        notify->setInt32("what", ACodec::kWhatFlushCompleted);
2344        notify->post();
2345
2346        mCodec->mPortEOS[kPortIndexInput] =
2347            mCodec->mPortEOS[kPortIndexOutput] = false;
2348
2349        mCodec->changeState(mCodec->mExecutingState);
2350    }
2351}
2352
2353}  // namespace android
2354