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