ACodec.cpp revision cb67cd1b51ff9ab221e3124cf7e546515fef3c87
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    status_t err;
1742    if ((err = allocateBuffers()) != OK) {
1743        LOGE("Failed to allocate buffers after transitioning to IDLE state "
1744             "(error 0x%08x)",
1745             err);
1746
1747        sp<AMessage> notify = mCodec->mNotify->dup();
1748        notify->setInt32("what", ACodec::kWhatError);
1749        notify->setInt32("omx-error", OMX_ErrorUndefined);
1750        notify->post();
1751    }
1752}
1753
1754status_t ACodec::LoadedToIdleState::allocateBuffers() {
1755    status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput);
1756
1757    if (err != OK) {
1758        return err;
1759    }
1760
1761    return mCodec->allocateBuffersOnPort(kPortIndexOutput);
1762}
1763
1764bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
1765    switch (msg->what()) {
1766        case kWhatShutdown:
1767        {
1768            mCodec->deferMessage(msg);
1769            return true;
1770        }
1771
1772        default:
1773            return BaseState::onMessageReceived(msg);
1774    }
1775}
1776
1777bool ACodec::LoadedToIdleState::onOMXEvent(
1778        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1779    switch (event) {
1780        case OMX_EventCmdComplete:
1781        {
1782            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
1783            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
1784
1785            CHECK_EQ(mCodec->mOMX->sendCommand(
1786                        mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting),
1787                     (status_t)OK);
1788
1789            mCodec->changeState(mCodec->mIdleToExecutingState);
1790
1791            return true;
1792        }
1793
1794        default:
1795            return BaseState::onOMXEvent(event, data1, data2);
1796    }
1797}
1798
1799////////////////////////////////////////////////////////////////////////////////
1800
1801ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec)
1802    : BaseState(codec) {
1803}
1804
1805void ACodec::IdleToExecutingState::stateEntered() {
1806    LOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
1807}
1808
1809bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
1810    switch (msg->what()) {
1811        case kWhatShutdown:
1812        {
1813            mCodec->deferMessage(msg);
1814            return true;
1815        }
1816
1817        default:
1818            return BaseState::onMessageReceived(msg);
1819    }
1820}
1821
1822bool ACodec::IdleToExecutingState::onOMXEvent(
1823        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1824    switch (event) {
1825        case OMX_EventCmdComplete:
1826        {
1827            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
1828            CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting);
1829
1830            mCodec->mExecutingState->resume();
1831            mCodec->changeState(mCodec->mExecutingState);
1832
1833            return true;
1834        }
1835
1836        default:
1837            return BaseState::onOMXEvent(event, data1, data2);
1838    }
1839}
1840
1841////////////////////////////////////////////////////////////////////////////////
1842
1843ACodec::ExecutingState::ExecutingState(ACodec *codec)
1844    : BaseState(codec),
1845      mActive(false) {
1846}
1847
1848ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode(
1849        OMX_U32 portIndex) {
1850    return RESUBMIT_BUFFERS;
1851}
1852
1853void ACodec::ExecutingState::submitOutputBuffers() {
1854    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
1855        BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
1856
1857        if (mCodec->mNativeWindow != NULL) {
1858            CHECK(info->mStatus == BufferInfo::OWNED_BY_US
1859                    || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
1860
1861            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
1862                continue;
1863            }
1864
1865            status_t err = mCodec->mNativeWindow->lockBuffer(
1866                    mCodec->mNativeWindow.get(),
1867                    info->mGraphicBuffer.get());
1868            CHECK_EQ(err, (status_t)OK);
1869        } else {
1870            CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
1871        }
1872
1873        LOGV("[%s] calling fillBuffer %p",
1874             mCodec->mComponentName.c_str(), info->mBufferID);
1875
1876        CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
1877                 (status_t)OK);
1878
1879        info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1880    }
1881}
1882
1883void ACodec::ExecutingState::resume() {
1884    if (mActive) {
1885        LOGV("[%s] We're already active, no need to resume.",
1886             mCodec->mComponentName.c_str());
1887
1888        return;
1889    }
1890
1891    submitOutputBuffers();
1892
1893    // Post the first input buffer.
1894    CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u);
1895    BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(0);
1896
1897    postFillThisBuffer(info);
1898
1899    mActive = true;
1900}
1901
1902void ACodec::ExecutingState::stateEntered() {
1903    LOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
1904
1905    mCodec->processDeferredMessages();
1906}
1907
1908bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) {
1909    bool handled = false;
1910
1911    switch (msg->what()) {
1912        case kWhatShutdown:
1913        {
1914            mActive = false;
1915
1916            CHECK_EQ(mCodec->mOMX->sendCommand(
1917                        mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
1918                     (status_t)OK);
1919
1920            mCodec->changeState(mCodec->mExecutingToIdleState);
1921
1922            handled = true;
1923            break;
1924        }
1925
1926        case kWhatFlush:
1927        {
1928            mActive = false;
1929
1930            CHECK_EQ(mCodec->mOMX->sendCommand(
1931                        mCodec->mNode, OMX_CommandFlush, OMX_ALL),
1932                     (status_t)OK);
1933
1934            mCodec->changeState(mCodec->mFlushingState);
1935
1936            handled = true;
1937            break;
1938        }
1939
1940        case kWhatResume:
1941        {
1942            resume();
1943
1944            handled = true;
1945            break;
1946        }
1947
1948        default:
1949            handled = BaseState::onMessageReceived(msg);
1950            break;
1951    }
1952
1953    return handled;
1954}
1955
1956bool ACodec::ExecutingState::onOMXEvent(
1957        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1958    switch (event) {
1959        case OMX_EventPortSettingsChanged:
1960        {
1961            CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
1962
1963            if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
1964                CHECK_EQ(mCodec->mOMX->sendCommand(
1965                            mCodec->mNode,
1966                            OMX_CommandPortDisable, kPortIndexOutput),
1967                         (status_t)OK);
1968
1969                mCodec->freeOutputBuffersNotOwnedByComponent();
1970
1971                mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
1972            } else if (data2 == OMX_IndexConfigCommonOutputCrop) {
1973                mCodec->mSentFormat = false;
1974            } else {
1975                LOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx",
1976                     mCodec->mComponentName.c_str(), data2);
1977            }
1978
1979            return true;
1980        }
1981
1982        case OMX_EventBufferFlag:
1983        {
1984            return true;
1985        }
1986
1987        default:
1988            return BaseState::onOMXEvent(event, data1, data2);
1989    }
1990}
1991
1992////////////////////////////////////////////////////////////////////////////////
1993
1994ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState(
1995        ACodec *codec)
1996    : BaseState(codec) {
1997}
1998
1999ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode(
2000        OMX_U32 portIndex) {
2001    if (portIndex == kPortIndexOutput) {
2002        return FREE_BUFFERS;
2003    }
2004
2005    CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput);
2006
2007    return RESUBMIT_BUFFERS;
2008}
2009
2010bool ACodec::OutputPortSettingsChangedState::onMessageReceived(
2011        const sp<AMessage> &msg) {
2012    bool handled = false;
2013
2014    switch (msg->what()) {
2015        case kWhatFlush:
2016        case kWhatShutdown:
2017        case kWhatResume:
2018        {
2019            if (msg->what() == kWhatResume) {
2020                LOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
2021            }
2022
2023            mCodec->deferMessage(msg);
2024            handled = true;
2025            break;
2026        }
2027
2028        default:
2029            handled = BaseState::onMessageReceived(msg);
2030            break;
2031    }
2032
2033    return handled;
2034}
2035
2036void ACodec::OutputPortSettingsChangedState::stateEntered() {
2037    LOGV("[%s] Now handling output port settings change",
2038         mCodec->mComponentName.c_str());
2039}
2040
2041bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
2042        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2043    switch (event) {
2044        case OMX_EventCmdComplete:
2045        {
2046            if (data1 == (OMX_U32)OMX_CommandPortDisable) {
2047                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
2048
2049                LOGV("[%s] Output port now disabled.",
2050                        mCodec->mComponentName.c_str());
2051
2052                CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty());
2053                mCodec->mDealer[kPortIndexOutput].clear();
2054
2055                CHECK_EQ(mCodec->mOMX->sendCommand(
2056                            mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput),
2057                         (status_t)OK);
2058
2059                status_t err;
2060                if ((err = mCodec->allocateBuffersOnPort(
2061                                kPortIndexOutput)) != OK) {
2062                    LOGE("Failed to allocate output port buffers after "
2063                         "port reconfiguration (error 0x%08x)",
2064                         err);
2065
2066                    sp<AMessage> notify = mCodec->mNotify->dup();
2067                    notify->setInt32("what", ACodec::kWhatError);
2068                    notify->setInt32("omx-error", OMX_ErrorUndefined);
2069                    notify->post();
2070                }
2071
2072                return true;
2073            } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
2074                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
2075
2076                mCodec->mSentFormat = false;
2077
2078                LOGV("[%s] Output port now reenabled.",
2079                        mCodec->mComponentName.c_str());
2080
2081                if (mCodec->mExecutingState->active()) {
2082                    mCodec->mExecutingState->submitOutputBuffers();
2083                }
2084
2085                mCodec->changeState(mCodec->mExecutingState);
2086
2087                return true;
2088            }
2089
2090            return false;
2091        }
2092
2093        default:
2094            return false;
2095    }
2096}
2097
2098////////////////////////////////////////////////////////////////////////////////
2099
2100ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec)
2101    : BaseState(codec) {
2102}
2103
2104bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) {
2105    bool handled = false;
2106
2107    switch (msg->what()) {
2108        case kWhatFlush:
2109        {
2110            // Don't send me a flush request if you previously wanted me
2111            // to shutdown.
2112            TRESPASS();
2113            break;
2114        }
2115
2116        case kWhatShutdown:
2117        {
2118            // We're already doing that...
2119
2120            handled = true;
2121            break;
2122        }
2123
2124        default:
2125            handled = BaseState::onMessageReceived(msg);
2126            break;
2127    }
2128
2129    return handled;
2130}
2131
2132void ACodec::ExecutingToIdleState::stateEntered() {
2133    LOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
2134
2135    mCodec->mSentFormat = false;
2136}
2137
2138bool ACodec::ExecutingToIdleState::onOMXEvent(
2139        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2140    switch (event) {
2141        case OMX_EventCmdComplete:
2142        {
2143            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
2144            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
2145
2146            changeStateIfWeOwnAllBuffers();
2147
2148            return true;
2149        }
2150
2151        case OMX_EventPortSettingsChanged:
2152        case OMX_EventBufferFlag:
2153        {
2154            // We're shutting down and don't care about this anymore.
2155            return true;
2156        }
2157
2158        default:
2159            return BaseState::onOMXEvent(event, data1, data2);
2160    }
2161}
2162
2163void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
2164    if (mCodec->allYourBuffersAreBelongToUs()) {
2165        CHECK_EQ(mCodec->mOMX->sendCommand(
2166                    mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded),
2167                 (status_t)OK);
2168
2169        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK);
2170        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK);
2171
2172        mCodec->changeState(mCodec->mIdleToLoadedState);
2173    }
2174}
2175
2176void ACodec::ExecutingToIdleState::onInputBufferFilled(
2177        const sp<AMessage> &msg) {
2178    BaseState::onInputBufferFilled(msg);
2179
2180    changeStateIfWeOwnAllBuffers();
2181}
2182
2183void ACodec::ExecutingToIdleState::onOutputBufferDrained(
2184        const sp<AMessage> &msg) {
2185    BaseState::onOutputBufferDrained(msg);
2186
2187    changeStateIfWeOwnAllBuffers();
2188}
2189
2190////////////////////////////////////////////////////////////////////////////////
2191
2192ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec)
2193    : BaseState(codec) {
2194}
2195
2196bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) {
2197    bool handled = false;
2198
2199    switch (msg->what()) {
2200        case kWhatShutdown:
2201        {
2202            // We're already doing that...
2203
2204            handled = true;
2205            break;
2206        }
2207
2208        case kWhatFlush:
2209        {
2210            // Don't send me a flush request if you previously wanted me
2211            // to shutdown.
2212            TRESPASS();
2213            break;
2214        }
2215
2216        default:
2217            handled = BaseState::onMessageReceived(msg);
2218            break;
2219    }
2220
2221    return handled;
2222}
2223
2224void ACodec::IdleToLoadedState::stateEntered() {
2225    LOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
2226}
2227
2228bool ACodec::IdleToLoadedState::onOMXEvent(
2229        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2230    switch (event) {
2231        case OMX_EventCmdComplete:
2232        {
2233            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
2234            CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded);
2235
2236            LOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
2237
2238            CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
2239
2240            mCodec->mNativeWindow.clear();
2241            mCodec->mNode = NULL;
2242            mCodec->mOMX.clear();
2243            mCodec->mComponentName.clear();
2244
2245            mCodec->changeState(mCodec->mUninitializedState);
2246
2247            sp<AMessage> notify = mCodec->mNotify->dup();
2248            notify->setInt32("what", ACodec::kWhatShutdownCompleted);
2249            notify->post();
2250
2251            return true;
2252        }
2253
2254        default:
2255            return BaseState::onOMXEvent(event, data1, data2);
2256    }
2257}
2258
2259////////////////////////////////////////////////////////////////////////////////
2260
2261ACodec::FlushingState::FlushingState(ACodec *codec)
2262    : BaseState(codec) {
2263}
2264
2265void ACodec::FlushingState::stateEntered() {
2266    LOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());
2267
2268    mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
2269}
2270
2271bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) {
2272    bool handled = false;
2273
2274    switch (msg->what()) {
2275        case kWhatShutdown:
2276        {
2277            mCodec->deferMessage(msg);
2278            break;
2279        }
2280
2281        case kWhatFlush:
2282        {
2283            // We're already doing this right now.
2284            handled = true;
2285            break;
2286        }
2287
2288        default:
2289            handled = BaseState::onMessageReceived(msg);
2290            break;
2291    }
2292
2293    return handled;
2294}
2295
2296bool ACodec::FlushingState::onOMXEvent(
2297        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2298    switch (event) {
2299        case OMX_EventCmdComplete:
2300        {
2301            CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush);
2302
2303            if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
2304                CHECK(!mFlushComplete[data2]);
2305                mFlushComplete[data2] = true;
2306
2307                if (mFlushComplete[kPortIndexInput]
2308                        && mFlushComplete[kPortIndexOutput]) {
2309                    changeStateIfWeOwnAllBuffers();
2310                }
2311            } else {
2312                CHECK_EQ(data2, OMX_ALL);
2313                CHECK(mFlushComplete[kPortIndexInput]);
2314                CHECK(mFlushComplete[kPortIndexOutput]);
2315
2316                changeStateIfWeOwnAllBuffers();
2317            }
2318
2319            return true;
2320        }
2321
2322        case OMX_EventPortSettingsChanged:
2323        {
2324            sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id());
2325            msg->setInt32("type", omx_message::EVENT);
2326            msg->setPointer("node", mCodec->mNode);
2327            msg->setInt32("event", event);
2328            msg->setInt32("data1", data1);
2329            msg->setInt32("data2", data2);
2330
2331            LOGV("[%s] Deferring OMX_EventPortSettingsChanged",
2332                 mCodec->mComponentName.c_str());
2333
2334            mCodec->deferMessage(msg);
2335
2336            return true;
2337        }
2338
2339        default:
2340            return BaseState::onOMXEvent(event, data1, data2);
2341    }
2342
2343    return true;
2344}
2345
2346void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) {
2347    BaseState::onOutputBufferDrained(msg);
2348
2349    changeStateIfWeOwnAllBuffers();
2350}
2351
2352void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) {
2353    BaseState::onInputBufferFilled(msg);
2354
2355    changeStateIfWeOwnAllBuffers();
2356}
2357
2358void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() {
2359    if (mFlushComplete[kPortIndexInput]
2360            && mFlushComplete[kPortIndexOutput]
2361            && mCodec->allYourBuffersAreBelongToUs()) {
2362        sp<AMessage> notify = mCodec->mNotify->dup();
2363        notify->setInt32("what", ACodec::kWhatFlushCompleted);
2364        notify->post();
2365
2366        mCodec->mPortEOS[kPortIndexInput] =
2367            mCodec->mPortEOS[kPortIndexOutput] = false;
2368
2369        mCodec->changeState(mCodec->mExecutingState);
2370    }
2371}
2372
2373}  // namespace android
2374