ACodec.cpp revision 9806555d3930be43e11106281dee354820ac1c88
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/MediaCodecList.h>
30#include <media/stagefright/MediaDefs.h>
31#include <media/stagefright/NativeWindowWrapper.h>
32#include <media/stagefright/OMXClient.h>
33#include <media/stagefright/OMXCodec.h>
34
35#include <OMX_Component.h>
36
37namespace android {
38
39template<class T>
40static void InitOMXParams(T *params) {
41    params->nSize = sizeof(T);
42    params->nVersion.s.nVersionMajor = 1;
43    params->nVersion.s.nVersionMinor = 0;
44    params->nVersion.s.nRevision = 0;
45    params->nVersion.s.nStep = 0;
46}
47
48struct CodecObserver : public BnOMXObserver {
49    CodecObserver() {}
50
51    void setNotificationMessage(const sp<AMessage> &msg) {
52        mNotify = msg;
53    }
54
55    // from IOMXObserver
56    virtual void onMessage(const omx_message &omx_msg) {
57        sp<AMessage> msg = mNotify->dup();
58
59        msg->setInt32("type", omx_msg.type);
60        msg->setPointer("node", omx_msg.node);
61
62        switch (omx_msg.type) {
63            case omx_message::EVENT:
64            {
65                msg->setInt32("event", omx_msg.u.event_data.event);
66                msg->setInt32("data1", omx_msg.u.event_data.data1);
67                msg->setInt32("data2", omx_msg.u.event_data.data2);
68                break;
69            }
70
71            case omx_message::EMPTY_BUFFER_DONE:
72            {
73                msg->setPointer("buffer", omx_msg.u.buffer_data.buffer);
74                break;
75            }
76
77            case omx_message::FILL_BUFFER_DONE:
78            {
79                msg->setPointer(
80                        "buffer", omx_msg.u.extended_buffer_data.buffer);
81                msg->setInt32(
82                        "range_offset",
83                        omx_msg.u.extended_buffer_data.range_offset);
84                msg->setInt32(
85                        "range_length",
86                        omx_msg.u.extended_buffer_data.range_length);
87                msg->setInt32(
88                        "flags",
89                        omx_msg.u.extended_buffer_data.flags);
90                msg->setInt64(
91                        "timestamp",
92                        omx_msg.u.extended_buffer_data.timestamp);
93                msg->setPointer(
94                        "platform_private",
95                        omx_msg.u.extended_buffer_data.platform_private);
96                msg->setPointer(
97                        "data_ptr",
98                        omx_msg.u.extended_buffer_data.data_ptr);
99                break;
100            }
101
102            default:
103                TRESPASS();
104                break;
105        }
106
107        msg->post();
108    }
109
110protected:
111    virtual ~CodecObserver() {}
112
113private:
114    sp<AMessage> mNotify;
115
116    DISALLOW_EVIL_CONSTRUCTORS(CodecObserver);
117};
118
119////////////////////////////////////////////////////////////////////////////////
120
121struct ACodec::BaseState : public AState {
122    BaseState(ACodec *codec, const sp<AState> &parentState = NULL);
123
124protected:
125    enum PortMode {
126        KEEP_BUFFERS,
127        RESUBMIT_BUFFERS,
128        FREE_BUFFERS,
129    };
130
131    ACodec *mCodec;
132
133    virtual PortMode getPortMode(OMX_U32 portIndex);
134
135    virtual bool onMessageReceived(const sp<AMessage> &msg);
136
137    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
138
139    virtual void onOutputBufferDrained(const sp<AMessage> &msg);
140    virtual void onInputBufferFilled(const sp<AMessage> &msg);
141
142    void postFillThisBuffer(BufferInfo *info);
143
144private:
145    bool onOMXMessage(const sp<AMessage> &msg);
146
147    bool onOMXEmptyBufferDone(IOMX::buffer_id bufferID);
148
149    bool onOMXFillBufferDone(
150            IOMX::buffer_id bufferID,
151            size_t rangeOffset, size_t rangeLength,
152            OMX_U32 flags,
153            int64_t timeUs,
154            void *platformPrivate,
155            void *dataPtr);
156
157    void getMoreInputDataIfPossible();
158
159    DISALLOW_EVIL_CONSTRUCTORS(BaseState);
160};
161
162////////////////////////////////////////////////////////////////////////////////
163
164struct ACodec::UninitializedState : public ACodec::BaseState {
165    UninitializedState(ACodec *codec);
166
167protected:
168    virtual bool onMessageReceived(const sp<AMessage> &msg);
169    virtual void stateEntered();
170
171private:
172    void onSetup(const sp<AMessage> &msg);
173    bool onAllocateComponent(const sp<AMessage> &msg);
174
175    DISALLOW_EVIL_CONSTRUCTORS(UninitializedState);
176};
177
178////////////////////////////////////////////////////////////////////////////////
179
180struct ACodec::LoadedState : public ACodec::BaseState {
181    LoadedState(ACodec *codec);
182
183protected:
184    virtual bool onMessageReceived(const sp<AMessage> &msg);
185    virtual void stateEntered();
186
187private:
188    friend struct ACodec::UninitializedState;
189
190    bool onConfigureComponent(const sp<AMessage> &msg);
191    void onStart();
192    void onShutdown(bool keepComponentAllocated);
193
194    DISALLOW_EVIL_CONSTRUCTORS(LoadedState);
195};
196
197////////////////////////////////////////////////////////////////////////////////
198
199struct ACodec::LoadedToIdleState : public ACodec::BaseState {
200    LoadedToIdleState(ACodec *codec);
201
202protected:
203    virtual bool onMessageReceived(const sp<AMessage> &msg);
204    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
205    virtual void stateEntered();
206
207private:
208    status_t allocateBuffers();
209
210    DISALLOW_EVIL_CONSTRUCTORS(LoadedToIdleState);
211};
212
213////////////////////////////////////////////////////////////////////////////////
214
215struct ACodec::IdleToExecutingState : public ACodec::BaseState {
216    IdleToExecutingState(ACodec *codec);
217
218protected:
219    virtual bool onMessageReceived(const sp<AMessage> &msg);
220    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
221    virtual void stateEntered();
222
223private:
224    DISALLOW_EVIL_CONSTRUCTORS(IdleToExecutingState);
225};
226
227////////////////////////////////////////////////////////////////////////////////
228
229struct ACodec::ExecutingState : public ACodec::BaseState {
230    ExecutingState(ACodec *codec);
231
232    void submitOutputBuffers();
233
234    // Submit output buffers to the decoder, submit input buffers to client
235    // to fill with data.
236    void resume();
237
238    // Returns true iff input and output buffers are in play.
239    bool active() const { return mActive; }
240
241protected:
242    virtual PortMode getPortMode(OMX_U32 portIndex);
243    virtual bool onMessageReceived(const sp<AMessage> &msg);
244    virtual void stateEntered();
245
246    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
247
248private:
249    bool mActive;
250
251    DISALLOW_EVIL_CONSTRUCTORS(ExecutingState);
252};
253
254////////////////////////////////////////////////////////////////////////////////
255
256struct ACodec::OutputPortSettingsChangedState : public ACodec::BaseState {
257    OutputPortSettingsChangedState(ACodec *codec);
258
259protected:
260    virtual PortMode getPortMode(OMX_U32 portIndex);
261    virtual bool onMessageReceived(const sp<AMessage> &msg);
262    virtual void stateEntered();
263
264    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
265
266private:
267    DISALLOW_EVIL_CONSTRUCTORS(OutputPortSettingsChangedState);
268};
269
270////////////////////////////////////////////////////////////////////////////////
271
272struct ACodec::ExecutingToIdleState : public ACodec::BaseState {
273    ExecutingToIdleState(ACodec *codec);
274
275protected:
276    virtual bool onMessageReceived(const sp<AMessage> &msg);
277    virtual void stateEntered();
278
279    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
280
281    virtual void onOutputBufferDrained(const sp<AMessage> &msg);
282    virtual void onInputBufferFilled(const sp<AMessage> &msg);
283
284private:
285    void changeStateIfWeOwnAllBuffers();
286
287    bool mComponentNowIdle;
288
289    DISALLOW_EVIL_CONSTRUCTORS(ExecutingToIdleState);
290};
291
292////////////////////////////////////////////////////////////////////////////////
293
294struct ACodec::IdleToLoadedState : public ACodec::BaseState {
295    IdleToLoadedState(ACodec *codec);
296
297protected:
298    virtual bool onMessageReceived(const sp<AMessage> &msg);
299    virtual void stateEntered();
300
301    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
302
303private:
304    DISALLOW_EVIL_CONSTRUCTORS(IdleToLoadedState);
305};
306
307////////////////////////////////////////////////////////////////////////////////
308
309struct ACodec::FlushingState : public ACodec::BaseState {
310    FlushingState(ACodec *codec);
311
312protected:
313    virtual bool onMessageReceived(const sp<AMessage> &msg);
314    virtual void stateEntered();
315
316    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
317
318    virtual void onOutputBufferDrained(const sp<AMessage> &msg);
319    virtual void onInputBufferFilled(const sp<AMessage> &msg);
320
321private:
322    bool mFlushComplete[2];
323
324    void changeStateIfWeOwnAllBuffers();
325
326    DISALLOW_EVIL_CONSTRUCTORS(FlushingState);
327};
328
329////////////////////////////////////////////////////////////////////////////////
330
331ACodec::ACodec()
332    : mQuirks(0),
333      mNode(NULL),
334      mSentFormat(false),
335      mIsEncoder(false),
336      mShutdownInProgress(false),
337      mEncoderDelay(0),
338      mEncoderPadding(0),
339      mChannelMaskPresent(false),
340      mChannelMask(0) {
341    mUninitializedState = new UninitializedState(this);
342    mLoadedState = new LoadedState(this);
343    mLoadedToIdleState = new LoadedToIdleState(this);
344    mIdleToExecutingState = new IdleToExecutingState(this);
345    mExecutingState = new ExecutingState(this);
346
347    mOutputPortSettingsChangedState =
348        new OutputPortSettingsChangedState(this);
349
350    mExecutingToIdleState = new ExecutingToIdleState(this);
351    mIdleToLoadedState = new IdleToLoadedState(this);
352    mFlushingState = new FlushingState(this);
353
354    mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false;
355    mInputEOSResult = OK;
356
357    changeState(mUninitializedState);
358}
359
360ACodec::~ACodec() {
361}
362
363void ACodec::setNotificationMessage(const sp<AMessage> &msg) {
364    mNotify = msg;
365}
366
367void ACodec::initiateSetup(const sp<AMessage> &msg) {
368    msg->setWhat(kWhatSetup);
369    msg->setTarget(id());
370    msg->post();
371}
372
373void ACodec::initiateAllocateComponent(const sp<AMessage> &msg) {
374    msg->setWhat(kWhatAllocateComponent);
375    msg->setTarget(id());
376    msg->post();
377}
378
379void ACodec::initiateConfigureComponent(const sp<AMessage> &msg) {
380    msg->setWhat(kWhatConfigureComponent);
381    msg->setTarget(id());
382    msg->post();
383}
384
385void ACodec::initiateStart() {
386    (new AMessage(kWhatStart, id()))->post();
387}
388
389void ACodec::signalFlush() {
390    ALOGV("[%s] signalFlush", mComponentName.c_str());
391    (new AMessage(kWhatFlush, id()))->post();
392}
393
394void ACodec::signalResume() {
395    (new AMessage(kWhatResume, id()))->post();
396}
397
398void ACodec::initiateShutdown(bool keepComponentAllocated) {
399    sp<AMessage> msg = new AMessage(kWhatShutdown, id());
400    msg->setInt32("keepComponentAllocated", keepComponentAllocated);
401    msg->post();
402}
403
404status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) {
405    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
406
407    CHECK(mDealer[portIndex] == NULL);
408    CHECK(mBuffers[portIndex].isEmpty());
409
410    status_t err;
411    if (mNativeWindow != NULL && portIndex == kPortIndexOutput) {
412        err = allocateOutputBuffersFromNativeWindow();
413    } else {
414        OMX_PARAM_PORTDEFINITIONTYPE def;
415        InitOMXParams(&def);
416        def.nPortIndex = portIndex;
417
418        err = mOMX->getParameter(
419                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
420
421        if (err == OK) {
422            ALOGV("[%s] Allocating %lu buffers of size %lu on %s port",
423                    mComponentName.c_str(),
424                    def.nBufferCountActual, def.nBufferSize,
425                    portIndex == kPortIndexInput ? "input" : "output");
426
427            size_t totalSize = def.nBufferCountActual * def.nBufferSize;
428            mDealer[portIndex] = new MemoryDealer(totalSize, "ACodec");
429
430            for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
431                sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
432                CHECK(mem.get() != NULL);
433
434                BufferInfo info;
435                info.mStatus = BufferInfo::OWNED_BY_US;
436
437                uint32_t requiresAllocateBufferBit =
438                    (portIndex == kPortIndexInput)
439                        ? OMXCodec::kRequiresAllocateBufferOnInputPorts
440                        : OMXCodec::kRequiresAllocateBufferOnOutputPorts;
441
442                if (portIndex == kPortIndexInput && (mFlags & kFlagIsSecure)) {
443                    mem.clear();
444
445                    void *ptr;
446                    err = mOMX->allocateBuffer(
447                            mNode, portIndex, def.nBufferSize, &info.mBufferID,
448                            &ptr);
449
450                    info.mData = new ABuffer(ptr, def.nBufferSize);
451                } else if (mQuirks & requiresAllocateBufferBit) {
452                    err = mOMX->allocateBufferWithBackup(
453                            mNode, portIndex, mem, &info.mBufferID);
454                } else {
455                    err = mOMX->useBuffer(mNode, portIndex, mem, &info.mBufferID);
456                }
457
458                if (mem != NULL) {
459                    info.mData = new ABuffer(mem->pointer(), def.nBufferSize);
460                }
461
462                mBuffers[portIndex].push(info);
463            }
464        }
465    }
466
467    if (err != OK) {
468        return err;
469    }
470
471    sp<AMessage> notify = mNotify->dup();
472    notify->setInt32("what", ACodec::kWhatBuffersAllocated);
473
474    notify->setInt32("portIndex", portIndex);
475    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
476        AString name = StringPrintf("buffer-id_%d", i);
477        notify->setPointer(name.c_str(), mBuffers[portIndex][i].mBufferID);
478
479        name = StringPrintf("data_%d", i);
480        notify->setBuffer(name.c_str(), mBuffers[portIndex][i].mData);
481    }
482
483    notify->post();
484
485    return OK;
486}
487
488status_t ACodec::allocateOutputBuffersFromNativeWindow() {
489    OMX_PARAM_PORTDEFINITIONTYPE def;
490    InitOMXParams(&def);
491    def.nPortIndex = kPortIndexOutput;
492
493    status_t err = mOMX->getParameter(
494            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
495
496    if (err != OK) {
497        return err;
498    }
499
500    err = native_window_set_scaling_mode(mNativeWindow.get(),
501            NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
502
503    if (err != OK) {
504        return err;
505    }
506
507    err = native_window_set_buffers_geometry(
508            mNativeWindow.get(),
509            def.format.video.nFrameWidth,
510            def.format.video.nFrameHeight,
511            def.format.video.eColorFormat);
512
513    if (err != 0) {
514        ALOGE("native_window_set_buffers_geometry failed: %s (%d)",
515                strerror(-err), -err);
516        return err;
517    }
518
519    // Set up the native window.
520    OMX_U32 usage = 0;
521    err = mOMX->getGraphicBufferUsage(mNode, kPortIndexOutput, &usage);
522    if (err != 0) {
523        ALOGW("querying usage flags from OMX IL component failed: %d", err);
524        // XXX: Currently this error is logged, but not fatal.
525        usage = 0;
526    }
527
528    err = native_window_set_usage(
529            mNativeWindow.get(),
530            usage | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP);
531
532    if (err != 0) {
533        ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err);
534        return err;
535    }
536
537    int minUndequeuedBufs = 0;
538    err = mNativeWindow->query(
539            mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
540            &minUndequeuedBufs);
541
542    if (err != 0) {
543        ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)",
544                strerror(-err), -err);
545        return err;
546    }
547
548    // XXX: Is this the right logic to use?  It's not clear to me what the OMX
549    // buffer counts refer to - how do they account for the renderer holding on
550    // to buffers?
551    if (def.nBufferCountActual < def.nBufferCountMin + minUndequeuedBufs) {
552        OMX_U32 newBufferCount = def.nBufferCountMin + minUndequeuedBufs;
553        def.nBufferCountActual = newBufferCount;
554        err = mOMX->setParameter(
555                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
556
557        if (err != OK) {
558            ALOGE("[%s] setting nBufferCountActual to %lu failed: %d",
559                    mComponentName.c_str(), newBufferCount, err);
560            return err;
561        }
562    }
563
564    err = native_window_set_buffer_count(
565            mNativeWindow.get(), def.nBufferCountActual);
566
567    if (err != 0) {
568        ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err),
569                -err);
570        return err;
571    }
572
573    ALOGV("[%s] Allocating %lu buffers from a native window of size %lu on "
574         "output port",
575         mComponentName.c_str(), def.nBufferCountActual, def.nBufferSize);
576
577    // Dequeue buffers and send them to OMX
578    for (OMX_U32 i = 0; i < def.nBufferCountActual; i++) {
579        ANativeWindowBuffer *buf;
580        err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf);
581        if (err != 0) {
582            ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
583            break;
584        }
585
586        sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false));
587        BufferInfo info;
588        info.mStatus = BufferInfo::OWNED_BY_US;
589        info.mData = new ABuffer(0);
590        info.mGraphicBuffer = graphicBuffer;
591        mBuffers[kPortIndexOutput].push(info);
592
593        IOMX::buffer_id bufferId;
594        err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer,
595                &bufferId);
596        if (err != 0) {
597            ALOGE("registering GraphicBuffer %lu with OMX IL component failed: "
598                 "%d", i, err);
599            break;
600        }
601
602        mBuffers[kPortIndexOutput].editItemAt(i).mBufferID = bufferId;
603
604        ALOGV("[%s] Registered graphic buffer with ID %p (pointer = %p)",
605             mComponentName.c_str(),
606             bufferId, graphicBuffer.get());
607    }
608
609    OMX_U32 cancelStart;
610    OMX_U32 cancelEnd;
611
612    if (err != 0) {
613        // If an error occurred while dequeuing we need to cancel any buffers
614        // that were dequeued.
615        cancelStart = 0;
616        cancelEnd = mBuffers[kPortIndexOutput].size();
617    } else {
618        // Return the last two buffers to the native window.
619        cancelStart = def.nBufferCountActual - minUndequeuedBufs;
620        cancelEnd = def.nBufferCountActual;
621    }
622
623    for (OMX_U32 i = cancelStart; i < cancelEnd; i++) {
624        BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
625        cancelBufferToNativeWindow(info);
626    }
627
628    return err;
629}
630
631status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) {
632    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
633
634    ALOGV("[%s] Calling cancelBuffer on buffer %p",
635         mComponentName.c_str(), info->mBufferID);
636
637    int err = mNativeWindow->cancelBuffer(
638        mNativeWindow.get(), info->mGraphicBuffer.get());
639
640    CHECK_EQ(err, 0);
641
642    info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
643
644    return OK;
645}
646
647ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() {
648    ANativeWindowBuffer *buf;
649    if (mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf) != 0) {
650        ALOGE("dequeueBuffer failed.");
651        return NULL;
652    }
653
654    for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
655        BufferInfo *info =
656            &mBuffers[kPortIndexOutput].editItemAt(i);
657
658        if (info->mGraphicBuffer->handle == buf->handle) {
659            CHECK_EQ((int)info->mStatus,
660                     (int)BufferInfo::OWNED_BY_NATIVE_WINDOW);
661
662            info->mStatus = BufferInfo::OWNED_BY_US;
663
664            return info;
665        }
666    }
667
668    TRESPASS();
669
670    return NULL;
671}
672
673status_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) {
674    for (size_t i = mBuffers[portIndex].size(); i-- > 0;) {
675        CHECK_EQ((status_t)OK, freeBuffer(portIndex, i));
676    }
677
678    mDealer[portIndex].clear();
679
680    return OK;
681}
682
683status_t ACodec::freeOutputBuffersNotOwnedByComponent() {
684    for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
685        BufferInfo *info =
686            &mBuffers[kPortIndexOutput].editItemAt(i);
687
688        if (info->mStatus !=
689                BufferInfo::OWNED_BY_COMPONENT) {
690            // We shouldn't have sent out any buffers to the client at this
691            // point.
692            CHECK_NE((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
693
694            CHECK_EQ((status_t)OK, freeBuffer(kPortIndexOutput, i));
695        }
696    }
697
698    return OK;
699}
700
701status_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) {
702    BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
703
704    CHECK(info->mStatus == BufferInfo::OWNED_BY_US
705            || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
706
707    if (portIndex == kPortIndexOutput && mNativeWindow != NULL
708            && info->mStatus == BufferInfo::OWNED_BY_US) {
709        CHECK_EQ((status_t)OK, cancelBufferToNativeWindow(info));
710    }
711
712    CHECK_EQ(mOMX->freeBuffer(
713                mNode, portIndex, info->mBufferID),
714             (status_t)OK);
715
716    mBuffers[portIndex].removeAt(i);
717
718    return OK;
719}
720
721ACodec::BufferInfo *ACodec::findBufferByID(
722        uint32_t portIndex, IOMX::buffer_id bufferID,
723        ssize_t *index) {
724    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
725        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
726
727        if (info->mBufferID == bufferID) {
728            if (index != NULL) {
729                *index = i;
730            }
731            return info;
732        }
733    }
734
735    TRESPASS();
736
737    return NULL;
738}
739
740status_t ACodec::setComponentRole(
741        bool isEncoder, const char *mime) {
742    struct MimeToRole {
743        const char *mime;
744        const char *decoderRole;
745        const char *encoderRole;
746    };
747
748    static const MimeToRole kMimeToRole[] = {
749        { MEDIA_MIMETYPE_AUDIO_MPEG,
750            "audio_decoder.mp3", "audio_encoder.mp3" },
751        { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I,
752            "audio_decoder.mp1", "audio_encoder.mp1" },
753        { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II,
754            "audio_decoder.mp2", "audio_encoder.mp2" },
755        { MEDIA_MIMETYPE_AUDIO_AMR_NB,
756            "audio_decoder.amrnb", "audio_encoder.amrnb" },
757        { MEDIA_MIMETYPE_AUDIO_AMR_WB,
758            "audio_decoder.amrwb", "audio_encoder.amrwb" },
759        { MEDIA_MIMETYPE_AUDIO_AAC,
760            "audio_decoder.aac", "audio_encoder.aac" },
761        { MEDIA_MIMETYPE_AUDIO_VORBIS,
762            "audio_decoder.vorbis", "audio_encoder.vorbis" },
763        { MEDIA_MIMETYPE_AUDIO_G711_MLAW,
764            "audio_decoder.g711mlaw", "audio_encoder.g711mlaw" },
765        { MEDIA_MIMETYPE_AUDIO_G711_ALAW,
766            "audio_decoder.g711alaw", "audio_encoder.g711alaw" },
767        { MEDIA_MIMETYPE_VIDEO_AVC,
768            "video_decoder.avc", "video_encoder.avc" },
769        { MEDIA_MIMETYPE_VIDEO_MPEG4,
770            "video_decoder.mpeg4", "video_encoder.mpeg4" },
771        { MEDIA_MIMETYPE_VIDEO_H263,
772            "video_decoder.h263", "video_encoder.h263" },
773        { MEDIA_MIMETYPE_VIDEO_VPX,
774            "video_decoder.vpx", "video_encoder.vpx" },
775        { MEDIA_MIMETYPE_AUDIO_RAW,
776            "audio_decoder.raw", "audio_encoder.raw" },
777    };
778
779    static const size_t kNumMimeToRole =
780        sizeof(kMimeToRole) / sizeof(kMimeToRole[0]);
781
782    size_t i;
783    for (i = 0; i < kNumMimeToRole; ++i) {
784        if (!strcasecmp(mime, kMimeToRole[i].mime)) {
785            break;
786        }
787    }
788
789    if (i == kNumMimeToRole) {
790        return ERROR_UNSUPPORTED;
791    }
792
793    const char *role =
794        isEncoder ? kMimeToRole[i].encoderRole
795                  : kMimeToRole[i].decoderRole;
796
797    if (role != NULL) {
798        OMX_PARAM_COMPONENTROLETYPE roleParams;
799        InitOMXParams(&roleParams);
800
801        strncpy((char *)roleParams.cRole,
802                role, OMX_MAX_STRINGNAME_SIZE - 1);
803
804        roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
805
806        status_t err = mOMX->setParameter(
807                mNode, OMX_IndexParamStandardComponentRole,
808                &roleParams, sizeof(roleParams));
809
810        if (err != OK) {
811            ALOGW("[%s] Failed to set standard component role '%s'.",
812                 mComponentName.c_str(), role);
813
814            return err;
815        }
816    }
817
818    return OK;
819}
820
821status_t ACodec::configureCodec(
822        const char *mime, const sp<AMessage> &msg) {
823    int32_t encoder;
824    if (!msg->findInt32("encoder", &encoder)) {
825        encoder = false;
826    }
827
828    mIsEncoder = encoder;
829
830    status_t err = setComponentRole(encoder /* isEncoder */, mime);
831
832    if (err != OK) {
833        return err;
834    }
835
836    int32_t bitRate = 0;
837    if (encoder && !msg->findInt32("bitrate", &bitRate)) {
838        return INVALID_OPERATION;
839    }
840
841    if (!strncasecmp(mime, "video/", 6)) {
842        if (encoder) {
843            err = setupVideoEncoder(mime, msg);
844        } else {
845            int32_t width, height;
846            if (!msg->findInt32("width", &width)
847                    || !msg->findInt32("height", &height)) {
848                err = INVALID_OPERATION;
849            } else {
850                err = setupVideoDecoder(mime, width, height);
851            }
852        }
853    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
854        int32_t numChannels, sampleRate;
855        if (!msg->findInt32("channel-count", &numChannels)
856                || !msg->findInt32("sample-rate", &sampleRate)) {
857            err = INVALID_OPERATION;
858        } else {
859            int32_t isADTS, aacProfile;
860            if (!msg->findInt32("is-adts", &isADTS)) {
861                isADTS = 0;
862            }
863            if (!msg->findInt32("aac-profile", &aacProfile)) {
864                aacProfile = OMX_AUDIO_AACObjectNull;
865            }
866
867            err = setupAACCodec(
868                    encoder, numChannels, sampleRate, bitRate, aacProfile, isADTS != 0);
869        }
870    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) {
871        err = setupAMRCodec(encoder, false /* isWAMR */, bitRate);
872    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
873        err = setupAMRCodec(encoder, true /* isWAMR */, bitRate);
874    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW)
875            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) {
876        // These are PCM-like formats with a fixed sample rate but
877        // a variable number of channels.
878
879        int32_t numChannels;
880        if (!msg->findInt32("channel-count", &numChannels)) {
881            err = INVALID_OPERATION;
882        } else {
883            err = setupG711Codec(encoder, numChannels);
884        }
885    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
886        int32_t numChannels, sampleRate;
887        if (encoder
888                || !msg->findInt32("channel-count", &numChannels)
889                || !msg->findInt32("sample-rate", &sampleRate)) {
890            err = INVALID_OPERATION;
891        } else {
892            err = setupRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
893        }
894    }
895
896    if (!msg->findInt32("encoder-delay", &mEncoderDelay)) {
897        mEncoderDelay = 0;
898    }
899
900    if (!msg->findInt32("encoder-padding", &mEncoderPadding)) {
901        mEncoderPadding = 0;
902    }
903
904    if (msg->findInt32("channel-mask", &mChannelMask)) {
905        mChannelMaskPresent = true;
906    } else {
907        mChannelMaskPresent = false;
908    }
909
910    int32_t maxInputSize;
911    if (msg->findInt32("max-input-size", &maxInputSize)) {
912        err = setMinBufferSize(kPortIndexInput, (size_t)maxInputSize);
913    } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) {
914        err = setMinBufferSize(kPortIndexInput, 8192);  // XXX
915    }
916
917    return err;
918}
919
920status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) {
921    OMX_PARAM_PORTDEFINITIONTYPE def;
922    InitOMXParams(&def);
923    def.nPortIndex = portIndex;
924
925    status_t err = mOMX->getParameter(
926            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
927
928    if (err != OK) {
929        return err;
930    }
931
932    if (def.nBufferSize >= size) {
933        return OK;
934    }
935
936    def.nBufferSize = size;
937
938    err = mOMX->setParameter(
939            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
940
941    if (err != OK) {
942        return err;
943    }
944
945    err = mOMX->getParameter(
946            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
947
948    if (err != OK) {
949        return err;
950    }
951
952    CHECK(def.nBufferSize >= size);
953
954    return OK;
955}
956
957status_t ACodec::selectAudioPortFormat(
958        OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat) {
959    OMX_AUDIO_PARAM_PORTFORMATTYPE format;
960    InitOMXParams(&format);
961
962    format.nPortIndex = portIndex;
963    for (OMX_U32 index = 0;; ++index) {
964        format.nIndex = index;
965
966        status_t err = mOMX->getParameter(
967                mNode, OMX_IndexParamAudioPortFormat,
968                &format, sizeof(format));
969
970        if (err != OK) {
971            return err;
972        }
973
974        if (format.eEncoding == desiredFormat) {
975            break;
976        }
977    }
978
979    return mOMX->setParameter(
980            mNode, OMX_IndexParamAudioPortFormat, &format, sizeof(format));
981}
982
983status_t ACodec::setupAACCodec(
984        bool encoder, int32_t numChannels, int32_t sampleRate,
985        int32_t bitRate, int32_t aacProfile, bool isADTS) {
986    if (encoder && isADTS) {
987        return -EINVAL;
988    }
989
990    status_t err = setupRawAudioFormat(
991            encoder ? kPortIndexInput : kPortIndexOutput,
992            sampleRate,
993            numChannels);
994
995    if (err != OK) {
996        return err;
997    }
998
999    if (encoder) {
1000        err = selectAudioPortFormat(kPortIndexOutput, OMX_AUDIO_CodingAAC);
1001
1002        if (err != OK) {
1003            return err;
1004        }
1005
1006        OMX_PARAM_PORTDEFINITIONTYPE def;
1007        InitOMXParams(&def);
1008        def.nPortIndex = kPortIndexOutput;
1009
1010        err = mOMX->getParameter(
1011                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1012
1013        if (err != OK) {
1014            return err;
1015        }
1016
1017        def.format.audio.bFlagErrorConcealment = OMX_TRUE;
1018        def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
1019
1020        err = mOMX->setParameter(
1021                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1022
1023        if (err != OK) {
1024            return err;
1025        }
1026
1027        OMX_AUDIO_PARAM_AACPROFILETYPE profile;
1028        InitOMXParams(&profile);
1029        profile.nPortIndex = kPortIndexOutput;
1030
1031        err = mOMX->getParameter(
1032                mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1033
1034        if (err != OK) {
1035            return err;
1036        }
1037
1038        profile.nChannels = numChannels;
1039
1040        profile.eChannelMode =
1041            (numChannels == 1)
1042                ? OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo;
1043
1044        profile.nSampleRate = sampleRate;
1045        profile.nBitRate = bitRate;
1046        profile.nAudioBandWidth = 0;
1047        profile.nFrameLength = 0;
1048        profile.nAACtools = OMX_AUDIO_AACToolAll;
1049        profile.nAACERtools = OMX_AUDIO_AACERNone;
1050        profile.eAACProfile = (OMX_AUDIO_AACPROFILETYPE) aacProfile;
1051        profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
1052
1053        err = mOMX->setParameter(
1054                mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1055
1056        if (err != OK) {
1057            return err;
1058        }
1059
1060        return err;
1061    }
1062
1063    OMX_AUDIO_PARAM_AACPROFILETYPE profile;
1064    InitOMXParams(&profile);
1065    profile.nPortIndex = kPortIndexInput;
1066
1067    err = mOMX->getParameter(
1068            mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1069
1070    if (err != OK) {
1071        return err;
1072    }
1073
1074    profile.nChannels = numChannels;
1075    profile.nSampleRate = sampleRate;
1076
1077    profile.eAACStreamFormat =
1078        isADTS
1079            ? OMX_AUDIO_AACStreamFormatMP4ADTS
1080            : OMX_AUDIO_AACStreamFormatMP4FF;
1081
1082    return mOMX->setParameter(
1083            mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1084}
1085
1086static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate(
1087        bool isAMRWB, int32_t bps) {
1088    if (isAMRWB) {
1089        if (bps <= 6600) {
1090            return OMX_AUDIO_AMRBandModeWB0;
1091        } else if (bps <= 8850) {
1092            return OMX_AUDIO_AMRBandModeWB1;
1093        } else if (bps <= 12650) {
1094            return OMX_AUDIO_AMRBandModeWB2;
1095        } else if (bps <= 14250) {
1096            return OMX_AUDIO_AMRBandModeWB3;
1097        } else if (bps <= 15850) {
1098            return OMX_AUDIO_AMRBandModeWB4;
1099        } else if (bps <= 18250) {
1100            return OMX_AUDIO_AMRBandModeWB5;
1101        } else if (bps <= 19850) {
1102            return OMX_AUDIO_AMRBandModeWB6;
1103        } else if (bps <= 23050) {
1104            return OMX_AUDIO_AMRBandModeWB7;
1105        }
1106
1107        // 23850 bps
1108        return OMX_AUDIO_AMRBandModeWB8;
1109    } else {  // AMRNB
1110        if (bps <= 4750) {
1111            return OMX_AUDIO_AMRBandModeNB0;
1112        } else if (bps <= 5150) {
1113            return OMX_AUDIO_AMRBandModeNB1;
1114        } else if (bps <= 5900) {
1115            return OMX_AUDIO_AMRBandModeNB2;
1116        } else if (bps <= 6700) {
1117            return OMX_AUDIO_AMRBandModeNB3;
1118        } else if (bps <= 7400) {
1119            return OMX_AUDIO_AMRBandModeNB4;
1120        } else if (bps <= 7950) {
1121            return OMX_AUDIO_AMRBandModeNB5;
1122        } else if (bps <= 10200) {
1123            return OMX_AUDIO_AMRBandModeNB6;
1124        }
1125
1126        // 12200 bps
1127        return OMX_AUDIO_AMRBandModeNB7;
1128    }
1129}
1130
1131status_t ACodec::setupAMRCodec(bool encoder, bool isWAMR, int32_t bitrate) {
1132    OMX_AUDIO_PARAM_AMRTYPE def;
1133    InitOMXParams(&def);
1134    def.nPortIndex = encoder ? kPortIndexOutput : kPortIndexInput;
1135
1136    status_t err =
1137        mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
1138
1139    if (err != OK) {
1140        return err;
1141    }
1142
1143    def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
1144    def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitrate);
1145
1146    err = mOMX->setParameter(
1147            mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
1148
1149    if (err != OK) {
1150        return err;
1151    }
1152
1153    return setupRawAudioFormat(
1154            encoder ? kPortIndexInput : kPortIndexOutput,
1155            isWAMR ? 16000 : 8000 /* sampleRate */,
1156            1 /* numChannels */);
1157}
1158
1159status_t ACodec::setupG711Codec(bool encoder, int32_t numChannels) {
1160    CHECK(!encoder);  // XXX TODO
1161
1162    return setupRawAudioFormat(
1163            kPortIndexInput, 8000 /* sampleRate */, numChannels);
1164}
1165
1166status_t ACodec::setupRawAudioFormat(
1167        OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) {
1168    OMX_PARAM_PORTDEFINITIONTYPE def;
1169    InitOMXParams(&def);
1170    def.nPortIndex = portIndex;
1171
1172    status_t err = mOMX->getParameter(
1173            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1174
1175    if (err != OK) {
1176        return err;
1177    }
1178
1179    def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
1180
1181    err = mOMX->setParameter(
1182            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1183
1184    if (err != OK) {
1185        return err;
1186    }
1187
1188    OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
1189    InitOMXParams(&pcmParams);
1190    pcmParams.nPortIndex = portIndex;
1191
1192    err = mOMX->getParameter(
1193            mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
1194
1195    if (err != OK) {
1196        return err;
1197    }
1198
1199    pcmParams.nChannels = numChannels;
1200    pcmParams.eNumData = OMX_NumericalDataSigned;
1201    pcmParams.bInterleaved = OMX_TRUE;
1202    pcmParams.nBitPerSample = 16;
1203    pcmParams.nSamplingRate = sampleRate;
1204    pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
1205
1206    if (getOMXChannelMapping(numChannels, pcmParams.eChannelMapping) != OK) {
1207        return OMX_ErrorNone;
1208    }
1209
1210    return mOMX->setParameter(
1211            mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
1212}
1213
1214status_t ACodec::setVideoPortFormatType(
1215        OMX_U32 portIndex,
1216        OMX_VIDEO_CODINGTYPE compressionFormat,
1217        OMX_COLOR_FORMATTYPE colorFormat) {
1218    OMX_VIDEO_PARAM_PORTFORMATTYPE format;
1219    InitOMXParams(&format);
1220    format.nPortIndex = portIndex;
1221    format.nIndex = 0;
1222    bool found = false;
1223
1224    OMX_U32 index = 0;
1225    for (;;) {
1226        format.nIndex = index;
1227        status_t err = mOMX->getParameter(
1228                mNode, OMX_IndexParamVideoPortFormat,
1229                &format, sizeof(format));
1230
1231        if (err != OK) {
1232            return err;
1233        }
1234
1235        // The following assertion is violated by TI's video decoder.
1236        // CHECK_EQ(format.nIndex, index);
1237
1238        if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) {
1239            if (portIndex == kPortIndexInput
1240                    && colorFormat == format.eColorFormat) {
1241                // eCompressionFormat does not seem right.
1242                found = true;
1243                break;
1244            }
1245            if (portIndex == kPortIndexOutput
1246                    && compressionFormat == format.eCompressionFormat) {
1247                // eColorFormat does not seem right.
1248                found = true;
1249                break;
1250            }
1251        }
1252
1253        if (format.eCompressionFormat == compressionFormat
1254            && format.eColorFormat == colorFormat) {
1255            found = true;
1256            break;
1257        }
1258
1259        ++index;
1260    }
1261
1262    if (!found) {
1263        return UNKNOWN_ERROR;
1264    }
1265
1266    status_t err = mOMX->setParameter(
1267            mNode, OMX_IndexParamVideoPortFormat,
1268            &format, sizeof(format));
1269
1270    return err;
1271}
1272
1273status_t ACodec::setSupportedOutputFormat() {
1274    OMX_VIDEO_PARAM_PORTFORMATTYPE format;
1275    InitOMXParams(&format);
1276    format.nPortIndex = kPortIndexOutput;
1277    format.nIndex = 0;
1278
1279    status_t err = mOMX->getParameter(
1280            mNode, OMX_IndexParamVideoPortFormat,
1281            &format, sizeof(format));
1282    CHECK_EQ(err, (status_t)OK);
1283    CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused);
1284
1285    CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar
1286           || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
1287           || format.eColorFormat == OMX_COLOR_FormatCbYCrY
1288           || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar
1289           || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar);
1290
1291    return mOMX->setParameter(
1292            mNode, OMX_IndexParamVideoPortFormat,
1293            &format, sizeof(format));
1294}
1295
1296static status_t GetVideoCodingTypeFromMime(
1297        const char *mime, OMX_VIDEO_CODINGTYPE *codingType) {
1298    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
1299        *codingType = OMX_VIDEO_CodingAVC;
1300    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
1301        *codingType = OMX_VIDEO_CodingMPEG4;
1302    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
1303        *codingType = OMX_VIDEO_CodingH263;
1304    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG2, mime)) {
1305        *codingType = OMX_VIDEO_CodingMPEG2;
1306    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_VPX, mime)) {
1307        *codingType = OMX_VIDEO_CodingVPX;
1308    } else {
1309        *codingType = OMX_VIDEO_CodingUnused;
1310        return ERROR_UNSUPPORTED;
1311    }
1312
1313    return OK;
1314}
1315
1316status_t ACodec::setupVideoDecoder(
1317        const char *mime, int32_t width, int32_t height) {
1318    OMX_VIDEO_CODINGTYPE compressionFormat;
1319    status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
1320
1321    if (err != OK) {
1322        return err;
1323    }
1324
1325    err = setVideoPortFormatType(
1326            kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
1327
1328    if (err != OK) {
1329        return err;
1330    }
1331
1332    err = setSupportedOutputFormat();
1333
1334    if (err != OK) {
1335        return err;
1336    }
1337
1338    err = setVideoFormatOnPort(
1339            kPortIndexInput, width, height, compressionFormat);
1340
1341    if (err != OK) {
1342        return err;
1343    }
1344
1345    err = setVideoFormatOnPort(
1346            kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused);
1347
1348    if (err != OK) {
1349        return err;
1350    }
1351
1352    return OK;
1353}
1354
1355status_t ACodec::setupVideoEncoder(const char *mime, const sp<AMessage> &msg) {
1356    int32_t tmp;
1357    if (!msg->findInt32("color-format", &tmp)) {
1358        return INVALID_OPERATION;
1359    }
1360
1361    OMX_COLOR_FORMATTYPE colorFormat =
1362        static_cast<OMX_COLOR_FORMATTYPE>(tmp);
1363
1364    status_t err = setVideoPortFormatType(
1365            kPortIndexInput, OMX_VIDEO_CodingUnused, colorFormat);
1366
1367    if (err != OK) {
1368        ALOGE("[%s] does not support color format %d",
1369              mComponentName.c_str(), colorFormat);
1370
1371        return err;
1372    }
1373
1374    /* Input port configuration */
1375
1376    OMX_PARAM_PORTDEFINITIONTYPE def;
1377    InitOMXParams(&def);
1378
1379    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
1380
1381    def.nPortIndex = kPortIndexInput;
1382
1383    err = mOMX->getParameter(
1384            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1385
1386    if (err != OK) {
1387        return err;
1388    }
1389
1390    int32_t width, height, bitrate;
1391    if (!msg->findInt32("width", &width)
1392            || !msg->findInt32("height", &height)
1393            || !msg->findInt32("bitrate", &bitrate)) {
1394        return INVALID_OPERATION;
1395    }
1396
1397    video_def->nFrameWidth = width;
1398    video_def->nFrameHeight = height;
1399
1400    int32_t stride;
1401    if (!msg->findInt32("stride", &stride)) {
1402        stride = width;
1403    }
1404
1405    video_def->nStride = stride;
1406
1407    int32_t sliceHeight;
1408    if (!msg->findInt32("slice-height", &sliceHeight)) {
1409        sliceHeight = height;
1410    }
1411
1412    video_def->nSliceHeight = sliceHeight;
1413
1414    def.nBufferSize = (video_def->nStride * video_def->nSliceHeight * 3) / 2;
1415
1416    float frameRate;
1417    if (!msg->findFloat("frame-rate", &frameRate)) {
1418        int32_t tmp;
1419        if (!msg->findInt32("frame-rate", &tmp)) {
1420            return INVALID_OPERATION;
1421        }
1422        frameRate = (float)tmp;
1423    }
1424
1425    video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f);
1426    video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
1427    video_def->eColorFormat = colorFormat;
1428
1429    err = mOMX->setParameter(
1430            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1431
1432    if (err != OK) {
1433        ALOGE("[%s] failed to set input port definition parameters.",
1434              mComponentName.c_str());
1435
1436        return err;
1437    }
1438
1439    /* Output port configuration */
1440
1441    OMX_VIDEO_CODINGTYPE compressionFormat;
1442    err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
1443
1444    if (err != OK) {
1445        return err;
1446    }
1447
1448    err = setVideoPortFormatType(
1449            kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused);
1450
1451    if (err != OK) {
1452        ALOGE("[%s] does not support compression format %d",
1453             mComponentName.c_str(), compressionFormat);
1454
1455        return err;
1456    }
1457
1458    def.nPortIndex = kPortIndexOutput;
1459
1460    err = mOMX->getParameter(
1461            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1462
1463    if (err != OK) {
1464        return err;
1465    }
1466
1467    video_def->nFrameWidth = width;
1468    video_def->nFrameHeight = height;
1469    video_def->xFramerate = 0;
1470    video_def->nBitrate = bitrate;
1471    video_def->eCompressionFormat = compressionFormat;
1472    video_def->eColorFormat = OMX_COLOR_FormatUnused;
1473
1474    err = mOMX->setParameter(
1475            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1476
1477    if (err != OK) {
1478        ALOGE("[%s] failed to set output port definition parameters.",
1479              mComponentName.c_str());
1480
1481        return err;
1482    }
1483
1484    switch (compressionFormat) {
1485        case OMX_VIDEO_CodingMPEG4:
1486            err = setupMPEG4EncoderParameters(msg);
1487            break;
1488
1489        case OMX_VIDEO_CodingH263:
1490            err = setupH263EncoderParameters(msg);
1491            break;
1492
1493        case OMX_VIDEO_CodingAVC:
1494            err = setupAVCEncoderParameters(msg);
1495            break;
1496
1497        default:
1498            break;
1499    }
1500
1501    ALOGI("setupVideoEncoder succeeded");
1502
1503    return err;
1504}
1505
1506static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) {
1507    if (iFramesInterval < 0) {
1508        return 0xFFFFFFFF;
1509    } else if (iFramesInterval == 0) {
1510        return 0;
1511    }
1512    OMX_U32 ret = frameRate * iFramesInterval;
1513    CHECK(ret > 1);
1514    return ret;
1515}
1516
1517status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) {
1518    int32_t bitrate, iFrameInterval;
1519    if (!msg->findInt32("bitrate", &bitrate)
1520            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
1521        return INVALID_OPERATION;
1522    }
1523
1524    float frameRate;
1525    if (!msg->findFloat("frame-rate", &frameRate)) {
1526        int32_t tmp;
1527        if (!msg->findInt32("frame-rate", &tmp)) {
1528            return INVALID_OPERATION;
1529        }
1530        frameRate = (float)tmp;
1531    }
1532
1533    OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type;
1534    InitOMXParams(&mpeg4type);
1535    mpeg4type.nPortIndex = kPortIndexOutput;
1536
1537    status_t err = mOMX->getParameter(
1538            mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
1539
1540    if (err != OK) {
1541        return err;
1542    }
1543
1544    mpeg4type.nSliceHeaderSpacing = 0;
1545    mpeg4type.bSVH = OMX_FALSE;
1546    mpeg4type.bGov = OMX_FALSE;
1547
1548    mpeg4type.nAllowedPictureTypes =
1549        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
1550
1551    mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
1552    if (mpeg4type.nPFrames == 0) {
1553        mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
1554    }
1555    mpeg4type.nBFrames = 0;
1556    mpeg4type.nIDCVLCThreshold = 0;
1557    mpeg4type.bACPred = OMX_TRUE;
1558    mpeg4type.nMaxPacketSize = 256;
1559    mpeg4type.nTimeIncRes = 1000;
1560    mpeg4type.nHeaderExtension = 0;
1561    mpeg4type.bReversibleVLC = OMX_FALSE;
1562
1563    int32_t profile;
1564    if (msg->findInt32("profile", &profile)) {
1565        int32_t level;
1566        if (!msg->findInt32("level", &level)) {
1567            return INVALID_OPERATION;
1568        }
1569
1570        err = verifySupportForProfileAndLevel(profile, level);
1571
1572        if (err != OK) {
1573            return err;
1574        }
1575
1576        mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile);
1577        mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level);
1578    }
1579
1580    err = mOMX->setParameter(
1581            mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
1582
1583    if (err != OK) {
1584        return err;
1585    }
1586
1587    err = configureBitrate(bitrate);
1588
1589    if (err != OK) {
1590        return err;
1591    }
1592
1593    return setupErrorCorrectionParameters();
1594}
1595
1596status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) {
1597    int32_t bitrate, iFrameInterval;
1598    if (!msg->findInt32("bitrate", &bitrate)
1599            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
1600        return INVALID_OPERATION;
1601    }
1602
1603    float frameRate;
1604    if (!msg->findFloat("frame-rate", &frameRate)) {
1605        int32_t tmp;
1606        if (!msg->findInt32("frame-rate", &tmp)) {
1607            return INVALID_OPERATION;
1608        }
1609        frameRate = (float)tmp;
1610    }
1611
1612    OMX_VIDEO_PARAM_H263TYPE h263type;
1613    InitOMXParams(&h263type);
1614    h263type.nPortIndex = kPortIndexOutput;
1615
1616    status_t err = mOMX->getParameter(
1617            mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
1618
1619    if (err != OK) {
1620        return err;
1621    }
1622
1623    h263type.nAllowedPictureTypes =
1624        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
1625
1626    h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
1627    if (h263type.nPFrames == 0) {
1628        h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
1629    }
1630    h263type.nBFrames = 0;
1631
1632    int32_t profile;
1633    if (msg->findInt32("profile", &profile)) {
1634        int32_t level;
1635        if (!msg->findInt32("level", &level)) {
1636            return INVALID_OPERATION;
1637        }
1638
1639        err = verifySupportForProfileAndLevel(profile, level);
1640
1641        if (err != OK) {
1642            return err;
1643        }
1644
1645        h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile);
1646        h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level);
1647    }
1648
1649    h263type.bPLUSPTYPEAllowed = OMX_FALSE;
1650    h263type.bForceRoundingTypeToZero = OMX_FALSE;
1651    h263type.nPictureHeaderRepetition = 0;
1652    h263type.nGOBHeaderInterval = 0;
1653
1654    err = mOMX->setParameter(
1655            mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
1656
1657    if (err != OK) {
1658        return err;
1659    }
1660
1661    err = configureBitrate(bitrate);
1662
1663    if (err != OK) {
1664        return err;
1665    }
1666
1667    return setupErrorCorrectionParameters();
1668}
1669
1670status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) {
1671    int32_t bitrate, iFrameInterval;
1672    if (!msg->findInt32("bitrate", &bitrate)
1673            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
1674        return INVALID_OPERATION;
1675    }
1676
1677    float frameRate;
1678    if (!msg->findFloat("frame-rate", &frameRate)) {
1679        int32_t tmp;
1680        if (!msg->findInt32("frame-rate", &tmp)) {
1681            return INVALID_OPERATION;
1682        }
1683        frameRate = (float)tmp;
1684    }
1685
1686    OMX_VIDEO_PARAM_AVCTYPE h264type;
1687    InitOMXParams(&h264type);
1688    h264type.nPortIndex = kPortIndexOutput;
1689
1690    status_t err = mOMX->getParameter(
1691            mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
1692
1693    if (err != OK) {
1694        return err;
1695    }
1696
1697    h264type.nAllowedPictureTypes =
1698        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
1699
1700    int32_t profile;
1701    if (msg->findInt32("profile", &profile)) {
1702        int32_t level;
1703        if (!msg->findInt32("level", &level)) {
1704            return INVALID_OPERATION;
1705        }
1706
1707        err = verifySupportForProfileAndLevel(profile, level);
1708
1709        if (err != OK) {
1710            return err;
1711        }
1712
1713        h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile);
1714        h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level);
1715    }
1716
1717    // XXX
1718    if (!strncmp(mComponentName.c_str(), "OMX.TI.DUCATI1", 14)) {
1719        h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
1720    }
1721
1722    if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
1723        h264type.nSliceHeaderSpacing = 0;
1724        h264type.bUseHadamard = OMX_TRUE;
1725        h264type.nRefFrames = 1;
1726        h264type.nBFrames = 0;
1727        h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
1728        if (h264type.nPFrames == 0) {
1729            h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
1730        }
1731        h264type.nRefIdx10ActiveMinus1 = 0;
1732        h264type.nRefIdx11ActiveMinus1 = 0;
1733        h264type.bEntropyCodingCABAC = OMX_FALSE;
1734        h264type.bWeightedPPrediction = OMX_FALSE;
1735        h264type.bconstIpred = OMX_FALSE;
1736        h264type.bDirect8x8Inference = OMX_FALSE;
1737        h264type.bDirectSpatialTemporal = OMX_FALSE;
1738        h264type.nCabacInitIdc = 0;
1739    }
1740
1741    if (h264type.nBFrames != 0) {
1742        h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
1743    }
1744
1745    h264type.bEnableUEP = OMX_FALSE;
1746    h264type.bEnableFMO = OMX_FALSE;
1747    h264type.bEnableASO = OMX_FALSE;
1748    h264type.bEnableRS = OMX_FALSE;
1749    h264type.bFrameMBsOnly = OMX_TRUE;
1750    h264type.bMBAFF = OMX_FALSE;
1751    h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
1752
1753    if (!strcasecmp("OMX.Nvidia.h264.encoder", mComponentName.c_str())) {
1754        h264type.eLevel = OMX_VIDEO_AVCLevelMax;
1755    }
1756
1757    err = mOMX->setParameter(
1758            mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
1759
1760    if (err != OK) {
1761        return err;
1762    }
1763
1764    return configureBitrate(bitrate);
1765}
1766
1767status_t ACodec::verifySupportForProfileAndLevel(
1768        int32_t profile, int32_t level) {
1769    OMX_VIDEO_PARAM_PROFILELEVELTYPE params;
1770    InitOMXParams(&params);
1771    params.nPortIndex = kPortIndexOutput;
1772
1773    for (params.nProfileIndex = 0;; ++params.nProfileIndex) {
1774        status_t err = mOMX->getParameter(
1775                mNode,
1776                OMX_IndexParamVideoProfileLevelQuerySupported,
1777                &params,
1778                sizeof(params));
1779
1780        if (err != OK) {
1781            return err;
1782        }
1783
1784        int32_t supportedProfile = static_cast<int32_t>(params.eProfile);
1785        int32_t supportedLevel = static_cast<int32_t>(params.eLevel);
1786
1787        if (profile == supportedProfile && level <= supportedLevel) {
1788            return OK;
1789        }
1790    }
1791}
1792
1793status_t ACodec::configureBitrate(int32_t bitrate) {
1794    OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
1795    InitOMXParams(&bitrateType);
1796    bitrateType.nPortIndex = kPortIndexOutput;
1797
1798    status_t err = mOMX->getParameter(
1799            mNode, OMX_IndexParamVideoBitrate,
1800            &bitrateType, sizeof(bitrateType));
1801
1802    if (err != OK) {
1803        return err;
1804    }
1805
1806    bitrateType.eControlRate = OMX_Video_ControlRateVariable;
1807    bitrateType.nTargetBitrate = bitrate;
1808
1809    return mOMX->setParameter(
1810            mNode, OMX_IndexParamVideoBitrate,
1811            &bitrateType, sizeof(bitrateType));
1812}
1813
1814status_t ACodec::setupErrorCorrectionParameters() {
1815    OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
1816    InitOMXParams(&errorCorrectionType);
1817    errorCorrectionType.nPortIndex = kPortIndexOutput;
1818
1819    status_t err = mOMX->getParameter(
1820            mNode, OMX_IndexParamVideoErrorCorrection,
1821            &errorCorrectionType, sizeof(errorCorrectionType));
1822
1823    if (err != OK) {
1824        return OK;  // Optional feature. Ignore this failure
1825    }
1826
1827    errorCorrectionType.bEnableHEC = OMX_FALSE;
1828    errorCorrectionType.bEnableResync = OMX_TRUE;
1829    errorCorrectionType.nResynchMarkerSpacing = 256;
1830    errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
1831    errorCorrectionType.bEnableRVLC = OMX_FALSE;
1832
1833    return mOMX->setParameter(
1834            mNode, OMX_IndexParamVideoErrorCorrection,
1835            &errorCorrectionType, sizeof(errorCorrectionType));
1836}
1837
1838status_t ACodec::setVideoFormatOnPort(
1839        OMX_U32 portIndex,
1840        int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat) {
1841    OMX_PARAM_PORTDEFINITIONTYPE def;
1842    InitOMXParams(&def);
1843    def.nPortIndex = portIndex;
1844
1845    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
1846
1847    status_t err = mOMX->getParameter(
1848            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1849
1850    CHECK_EQ(err, (status_t)OK);
1851
1852    if (portIndex == kPortIndexInput) {
1853        // XXX Need a (much) better heuristic to compute input buffer sizes.
1854        const size_t X = 64 * 1024;
1855        if (def.nBufferSize < X) {
1856            def.nBufferSize = X;
1857        }
1858    }
1859
1860    CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
1861
1862    video_def->nFrameWidth = width;
1863    video_def->nFrameHeight = height;
1864
1865    if (portIndex == kPortIndexInput) {
1866        video_def->eCompressionFormat = compressionFormat;
1867        video_def->eColorFormat = OMX_COLOR_FormatUnused;
1868    }
1869
1870    err = mOMX->setParameter(
1871            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1872
1873    return err;
1874}
1875
1876status_t ACodec::initNativeWindow() {
1877    if (mNativeWindow != NULL) {
1878        return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE);
1879    }
1880
1881    mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE);
1882    return OK;
1883}
1884
1885size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const {
1886    size_t n = 0;
1887
1888    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
1889        const BufferInfo &info = mBuffers[portIndex].itemAt(i);
1890
1891        if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) {
1892            ++n;
1893        }
1894    }
1895
1896    return n;
1897}
1898
1899bool ACodec::allYourBuffersAreBelongToUs(
1900        OMX_U32 portIndex) {
1901    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
1902        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
1903
1904        if (info->mStatus != BufferInfo::OWNED_BY_US
1905                && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
1906            ALOGV("[%s] Buffer %p on port %ld still has status %d",
1907                    mComponentName.c_str(),
1908                    info->mBufferID, portIndex, info->mStatus);
1909            return false;
1910        }
1911    }
1912
1913    return true;
1914}
1915
1916bool ACodec::allYourBuffersAreBelongToUs() {
1917    return allYourBuffersAreBelongToUs(kPortIndexInput)
1918        && allYourBuffersAreBelongToUs(kPortIndexOutput);
1919}
1920
1921void ACodec::deferMessage(const sp<AMessage> &msg) {
1922    bool wasEmptyBefore = mDeferredQueue.empty();
1923    mDeferredQueue.push_back(msg);
1924}
1925
1926void ACodec::processDeferredMessages() {
1927    List<sp<AMessage> > queue = mDeferredQueue;
1928    mDeferredQueue.clear();
1929
1930    List<sp<AMessage> >::iterator it = queue.begin();
1931    while (it != queue.end()) {
1932        onMessageReceived(*it++);
1933    }
1934}
1935
1936void ACodec::sendFormatChange() {
1937    sp<AMessage> notify = mNotify->dup();
1938    notify->setInt32("what", kWhatOutputFormatChanged);
1939
1940    OMX_PARAM_PORTDEFINITIONTYPE def;
1941    InitOMXParams(&def);
1942    def.nPortIndex = kPortIndexOutput;
1943
1944    CHECK_EQ(mOMX->getParameter(
1945                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)),
1946             (status_t)OK);
1947
1948    CHECK_EQ((int)def.eDir, (int)OMX_DirOutput);
1949
1950    switch (def.eDomain) {
1951        case OMX_PortDomainVideo:
1952        {
1953            OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
1954
1955            notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW);
1956            notify->setInt32("width", videoDef->nFrameWidth);
1957            notify->setInt32("height", videoDef->nFrameHeight);
1958            notify->setInt32("stride", videoDef->nStride);
1959            notify->setInt32("slice-height", videoDef->nSliceHeight);
1960            notify->setInt32("color-format", videoDef->eColorFormat);
1961
1962            OMX_CONFIG_RECTTYPE rect;
1963            InitOMXParams(&rect);
1964            rect.nPortIndex = kPortIndexOutput;
1965
1966            if (mOMX->getConfig(
1967                        mNode, OMX_IndexConfigCommonOutputCrop,
1968                        &rect, sizeof(rect)) != OK) {
1969                rect.nLeft = 0;
1970                rect.nTop = 0;
1971                rect.nWidth = videoDef->nFrameWidth;
1972                rect.nHeight = videoDef->nFrameHeight;
1973            }
1974
1975            CHECK_GE(rect.nLeft, 0);
1976            CHECK_GE(rect.nTop, 0);
1977            CHECK_GE(rect.nWidth, 0u);
1978            CHECK_GE(rect.nHeight, 0u);
1979            CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth);
1980            CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight);
1981
1982            notify->setRect(
1983                    "crop",
1984                    rect.nLeft,
1985                    rect.nTop,
1986                    rect.nLeft + rect.nWidth - 1,
1987                    rect.nTop + rect.nHeight - 1);
1988
1989            if (mNativeWindow != NULL) {
1990                android_native_rect_t crop;
1991                crop.left = rect.nLeft;
1992                crop.top = rect.nTop;
1993                crop.right = rect.nLeft + rect.nWidth;
1994                crop.bottom = rect.nTop + rect.nHeight;
1995
1996                CHECK_EQ(0, native_window_set_crop(
1997                            mNativeWindow.get(), &crop));
1998            }
1999            break;
2000        }
2001
2002        case OMX_PortDomainAudio:
2003        {
2004            OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
2005            CHECK_EQ((int)audioDef->eEncoding, (int)OMX_AUDIO_CodingPCM);
2006
2007            OMX_AUDIO_PARAM_PCMMODETYPE params;
2008            InitOMXParams(&params);
2009            params.nPortIndex = kPortIndexOutput;
2010
2011            CHECK_EQ(mOMX->getParameter(
2012                        mNode, OMX_IndexParamAudioPcm,
2013                        &params, sizeof(params)),
2014                     (status_t)OK);
2015
2016            CHECK(params.nChannels == 1 || params.bInterleaved);
2017            CHECK_EQ(params.nBitPerSample, 16u);
2018            CHECK_EQ((int)params.eNumData, (int)OMX_NumericalDataSigned);
2019            CHECK_EQ((int)params.ePCMMode, (int)OMX_AUDIO_PCMModeLinear);
2020
2021            notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
2022            notify->setInt32("channel-count", params.nChannels);
2023            notify->setInt32("sample-rate", params.nSamplingRate);
2024            if (mEncoderDelay + mEncoderPadding) {
2025                size_t frameSize = params.nChannels * sizeof(int16_t);
2026                if (mSkipCutBuffer != NULL) {
2027                    size_t prevbufsize = mSkipCutBuffer->size();
2028                    if (prevbufsize != 0) {
2029                        ALOGW("Replacing SkipCutBuffer holding %d bytes", prevbufsize);
2030                    }
2031                }
2032                mSkipCutBuffer = new SkipCutBuffer(mEncoderDelay * frameSize,
2033                                                   mEncoderPadding * frameSize);
2034            }
2035
2036            if (mChannelMaskPresent) {
2037                notify->setInt32("channel-mask", mChannelMask);
2038            }
2039
2040            break;
2041        }
2042
2043        default:
2044            TRESPASS();
2045    }
2046
2047    notify->post();
2048
2049    mSentFormat = true;
2050}
2051
2052void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) {
2053    sp<AMessage> notify = mNotify->dup();
2054    notify->setInt32("what", ACodec::kWhatError);
2055    notify->setInt32("omx-error", error);
2056    notify->setInt32("err", internalError);
2057    notify->post();
2058}
2059
2060////////////////////////////////////////////////////////////////////////////////
2061
2062ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
2063    : AState(parentState),
2064      mCodec(codec) {
2065}
2066
2067ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(OMX_U32 portIndex) {
2068    return KEEP_BUFFERS;
2069}
2070
2071bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) {
2072    switch (msg->what()) {
2073        case kWhatInputBufferFilled:
2074        {
2075            onInputBufferFilled(msg);
2076            break;
2077        }
2078
2079        case kWhatOutputBufferDrained:
2080        {
2081            onOutputBufferDrained(msg);
2082            break;
2083        }
2084
2085        case ACodec::kWhatOMXMessage:
2086        {
2087            return onOMXMessage(msg);
2088        }
2089
2090        default:
2091            return false;
2092    }
2093
2094    return true;
2095}
2096
2097bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) {
2098    int32_t type;
2099    CHECK(msg->findInt32("type", &type));
2100
2101    IOMX::node_id nodeID;
2102    CHECK(msg->findPointer("node", &nodeID));
2103    CHECK_EQ(nodeID, mCodec->mNode);
2104
2105    switch (type) {
2106        case omx_message::EVENT:
2107        {
2108            int32_t event, data1, data2;
2109            CHECK(msg->findInt32("event", &event));
2110            CHECK(msg->findInt32("data1", &data1));
2111            CHECK(msg->findInt32("data2", &data2));
2112
2113            if (event == OMX_EventCmdComplete
2114                    && data1 == OMX_CommandFlush
2115                    && data2 == (int32_t)OMX_ALL) {
2116                // Use of this notification is not consistent across
2117                // implementations. We'll drop this notification and rely
2118                // on flush-complete notifications on the individual port
2119                // indices instead.
2120
2121                return true;
2122            }
2123
2124            return onOMXEvent(
2125                    static_cast<OMX_EVENTTYPE>(event),
2126                    static_cast<OMX_U32>(data1),
2127                    static_cast<OMX_U32>(data2));
2128        }
2129
2130        case omx_message::EMPTY_BUFFER_DONE:
2131        {
2132            IOMX::buffer_id bufferID;
2133            CHECK(msg->findPointer("buffer", &bufferID));
2134
2135            return onOMXEmptyBufferDone(bufferID);
2136        }
2137
2138        case omx_message::FILL_BUFFER_DONE:
2139        {
2140            IOMX::buffer_id bufferID;
2141            CHECK(msg->findPointer("buffer", &bufferID));
2142
2143            int32_t rangeOffset, rangeLength, flags;
2144            int64_t timeUs;
2145            void *platformPrivate;
2146            void *dataPtr;
2147
2148            CHECK(msg->findInt32("range_offset", &rangeOffset));
2149            CHECK(msg->findInt32("range_length", &rangeLength));
2150            CHECK(msg->findInt32("flags", &flags));
2151            CHECK(msg->findInt64("timestamp", &timeUs));
2152            CHECK(msg->findPointer("platform_private", &platformPrivate));
2153            CHECK(msg->findPointer("data_ptr", &dataPtr));
2154
2155            return onOMXFillBufferDone(
2156                    bufferID,
2157                    (size_t)rangeOffset, (size_t)rangeLength,
2158                    (OMX_U32)flags,
2159                    timeUs,
2160                    platformPrivate,
2161                    dataPtr);
2162        }
2163
2164        default:
2165            TRESPASS();
2166            break;
2167    }
2168}
2169
2170bool ACodec::BaseState::onOMXEvent(
2171        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2172    if (event != OMX_EventError) {
2173        ALOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)",
2174             mCodec->mComponentName.c_str(), event, data1, data2);
2175
2176        return false;
2177    }
2178
2179    ALOGE("[%s] ERROR(0x%08lx)", mCodec->mComponentName.c_str(), data1);
2180
2181    mCodec->signalError((OMX_ERRORTYPE)data1);
2182
2183    return true;
2184}
2185
2186bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) {
2187    ALOGV("[%s] onOMXEmptyBufferDone %p",
2188         mCodec->mComponentName.c_str(), bufferID);
2189
2190    BufferInfo *info =
2191        mCodec->findBufferByID(kPortIndexInput, bufferID);
2192
2193    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
2194    info->mStatus = BufferInfo::OWNED_BY_US;
2195
2196    PortMode mode = getPortMode(kPortIndexInput);
2197
2198    switch (mode) {
2199        case KEEP_BUFFERS:
2200            break;
2201
2202        case RESUBMIT_BUFFERS:
2203            postFillThisBuffer(info);
2204            break;
2205
2206        default:
2207        {
2208            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
2209            TRESPASS();  // Not currently used
2210            break;
2211        }
2212    }
2213
2214    return true;
2215}
2216
2217void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) {
2218    if (mCodec->mPortEOS[kPortIndexInput]) {
2219        return;
2220    }
2221
2222    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
2223
2224    sp<AMessage> notify = mCodec->mNotify->dup();
2225    notify->setInt32("what", ACodec::kWhatFillThisBuffer);
2226    notify->setPointer("buffer-id", info->mBufferID);
2227
2228    info->mData->meta()->clear();
2229    notify->setBuffer("buffer", info->mData);
2230
2231    sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id());
2232    reply->setPointer("buffer-id", info->mBufferID);
2233
2234    notify->setMessage("reply", reply);
2235
2236    notify->post();
2237
2238    info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
2239}
2240
2241void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
2242    IOMX::buffer_id bufferID;
2243    CHECK(msg->findPointer("buffer-id", &bufferID));
2244
2245    sp<ABuffer> buffer;
2246    int32_t err = OK;
2247    bool eos = false;
2248
2249    if (!msg->findBuffer("buffer", &buffer)) {
2250        CHECK(msg->findInt32("err", &err));
2251
2252        ALOGV("[%s] saw error %d instead of an input buffer",
2253             mCodec->mComponentName.c_str(), err);
2254
2255        buffer.clear();
2256
2257        eos = true;
2258    }
2259
2260    int32_t tmp;
2261    if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) {
2262        eos = true;
2263        err = ERROR_END_OF_STREAM;
2264    }
2265
2266    BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
2267    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM);
2268
2269    info->mStatus = BufferInfo::OWNED_BY_US;
2270
2271    PortMode mode = getPortMode(kPortIndexInput);
2272
2273    switch (mode) {
2274        case KEEP_BUFFERS:
2275        {
2276            if (eos) {
2277                if (!mCodec->mPortEOS[kPortIndexInput]) {
2278                    mCodec->mPortEOS[kPortIndexInput] = true;
2279                    mCodec->mInputEOSResult = err;
2280                }
2281            }
2282            break;
2283        }
2284
2285        case RESUBMIT_BUFFERS:
2286        {
2287            if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) {
2288                int64_t timeUs;
2289                CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
2290
2291                OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
2292
2293                int32_t isCSD;
2294                if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) {
2295                    flags |= OMX_BUFFERFLAG_CODECCONFIG;
2296                }
2297
2298                if (eos) {
2299                    flags |= OMX_BUFFERFLAG_EOS;
2300                }
2301
2302                if (buffer != info->mData) {
2303                    if (0 && !(flags & OMX_BUFFERFLAG_CODECCONFIG)) {
2304                        ALOGV("[%s] Needs to copy input data.",
2305                             mCodec->mComponentName.c_str());
2306                    }
2307
2308                    CHECK_LE(buffer->size(), info->mData->capacity());
2309                    memcpy(info->mData->data(), buffer->data(), buffer->size());
2310                }
2311
2312                if (flags & OMX_BUFFERFLAG_CODECCONFIG) {
2313                    ALOGV("[%s] calling emptyBuffer %p w/ codec specific data",
2314                         mCodec->mComponentName.c_str(), bufferID);
2315                } else if (flags & OMX_BUFFERFLAG_EOS) {
2316                    ALOGV("[%s] calling emptyBuffer %p w/ EOS",
2317                         mCodec->mComponentName.c_str(), bufferID);
2318                } else {
2319                    ALOGV("[%s] calling emptyBuffer %p w/ time %lld us",
2320                         mCodec->mComponentName.c_str(), bufferID, timeUs);
2321                }
2322
2323                CHECK_EQ(mCodec->mOMX->emptyBuffer(
2324                            mCodec->mNode,
2325                            bufferID,
2326                            0,
2327                            buffer->size(),
2328                            flags,
2329                            timeUs),
2330                         (status_t)OK);
2331
2332                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
2333
2334                if (!eos) {
2335                    getMoreInputDataIfPossible();
2336                } else {
2337                    ALOGV("[%s] Signalled EOS on the input port",
2338                         mCodec->mComponentName.c_str());
2339
2340                    mCodec->mPortEOS[kPortIndexInput] = true;
2341                    mCodec->mInputEOSResult = err;
2342                }
2343            } else if (!mCodec->mPortEOS[kPortIndexInput]) {
2344                if (err != ERROR_END_OF_STREAM) {
2345                    ALOGV("[%s] Signalling EOS on the input port "
2346                         "due to error %d",
2347                         mCodec->mComponentName.c_str(), err);
2348                } else {
2349                    ALOGV("[%s] Signalling EOS on the input port",
2350                         mCodec->mComponentName.c_str());
2351                }
2352
2353                ALOGV("[%s] calling emptyBuffer %p signalling EOS",
2354                     mCodec->mComponentName.c_str(), bufferID);
2355
2356                CHECK_EQ(mCodec->mOMX->emptyBuffer(
2357                            mCodec->mNode,
2358                            bufferID,
2359                            0,
2360                            0,
2361                            OMX_BUFFERFLAG_EOS,
2362                            0),
2363                         (status_t)OK);
2364
2365                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
2366
2367                mCodec->mPortEOS[kPortIndexInput] = true;
2368                mCodec->mInputEOSResult = err;
2369            }
2370            break;
2371
2372            default:
2373                CHECK_EQ((int)mode, (int)FREE_BUFFERS);
2374                break;
2375        }
2376    }
2377}
2378
2379void ACodec::BaseState::getMoreInputDataIfPossible() {
2380    if (mCodec->mPortEOS[kPortIndexInput]) {
2381        return;
2382    }
2383
2384    BufferInfo *eligible = NULL;
2385
2386    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
2387        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
2388
2389#if 0
2390        if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) {
2391            // There's already a "read" pending.
2392            return;
2393        }
2394#endif
2395
2396        if (info->mStatus == BufferInfo::OWNED_BY_US) {
2397            eligible = info;
2398        }
2399    }
2400
2401    if (eligible == NULL) {
2402        return;
2403    }
2404
2405    postFillThisBuffer(eligible);
2406}
2407
2408bool ACodec::BaseState::onOMXFillBufferDone(
2409        IOMX::buffer_id bufferID,
2410        size_t rangeOffset, size_t rangeLength,
2411        OMX_U32 flags,
2412        int64_t timeUs,
2413        void *platformPrivate,
2414        void *dataPtr) {
2415    ALOGV("[%s] onOMXFillBufferDone %p time %lld us, flags = 0x%08lx",
2416         mCodec->mComponentName.c_str(), bufferID, timeUs, flags);
2417
2418    ssize_t index;
2419    BufferInfo *info =
2420        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
2421
2422    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
2423
2424    info->mStatus = BufferInfo::OWNED_BY_US;
2425
2426    PortMode mode = getPortMode(kPortIndexOutput);
2427
2428    switch (mode) {
2429        case KEEP_BUFFERS:
2430            break;
2431
2432        case RESUBMIT_BUFFERS:
2433        {
2434            if (rangeLength == 0 && !(flags & OMX_BUFFERFLAG_EOS)) {
2435                ALOGV("[%s] calling fillBuffer %p",
2436                     mCodec->mComponentName.c_str(), info->mBufferID);
2437
2438                CHECK_EQ(mCodec->mOMX->fillBuffer(
2439                            mCodec->mNode, info->mBufferID),
2440                         (status_t)OK);
2441
2442                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
2443                break;
2444            }
2445
2446            if (!mCodec->mIsEncoder && !mCodec->mSentFormat) {
2447                mCodec->sendFormatChange();
2448            }
2449
2450            if (mCodec->mNativeWindow == NULL) {
2451                info->mData->setRange(rangeOffset, rangeLength);
2452            }
2453
2454            if (mCodec->mSkipCutBuffer != NULL) {
2455                mCodec->mSkipCutBuffer->submit(info->mData);
2456            }
2457            info->mData->meta()->setInt64("timeUs", timeUs);
2458
2459            sp<AMessage> notify = mCodec->mNotify->dup();
2460            notify->setInt32("what", ACodec::kWhatDrainThisBuffer);
2461            notify->setPointer("buffer-id", info->mBufferID);
2462            notify->setBuffer("buffer", info->mData);
2463            notify->setInt32("flags", flags);
2464
2465            sp<AMessage> reply =
2466                new AMessage(kWhatOutputBufferDrained, mCodec->id());
2467
2468            reply->setPointer("buffer-id", info->mBufferID);
2469
2470            notify->setMessage("reply", reply);
2471
2472            notify->post();
2473
2474            info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;
2475
2476            if (flags & OMX_BUFFERFLAG_EOS) {
2477                ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str());
2478
2479                sp<AMessage> notify = mCodec->mNotify->dup();
2480                notify->setInt32("what", ACodec::kWhatEOS);
2481                notify->setInt32("err", mCodec->mInputEOSResult);
2482                notify->post();
2483
2484                mCodec->mPortEOS[kPortIndexOutput] = true;
2485            }
2486            break;
2487        }
2488
2489        default:
2490        {
2491            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
2492
2493            CHECK_EQ((status_t)OK,
2494                     mCodec->freeBuffer(kPortIndexOutput, index));
2495            break;
2496        }
2497    }
2498
2499    return true;
2500}
2501
2502void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
2503    IOMX::buffer_id bufferID;
2504    CHECK(msg->findPointer("buffer-id", &bufferID));
2505
2506    ssize_t index;
2507    BufferInfo *info =
2508        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
2509    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
2510
2511    int32_t render;
2512    if (mCodec->mNativeWindow != NULL
2513            && msg->findInt32("render", &render) && render != 0) {
2514        // The client wants this buffer to be rendered.
2515
2516        status_t err;
2517        if ((err = mCodec->mNativeWindow->queueBuffer(
2518                    mCodec->mNativeWindow.get(),
2519                    info->mGraphicBuffer.get())) == OK) {
2520            info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
2521        } else {
2522            mCodec->signalError(OMX_ErrorUndefined, err);
2523            info->mStatus = BufferInfo::OWNED_BY_US;
2524        }
2525    } else {
2526        info->mStatus = BufferInfo::OWNED_BY_US;
2527    }
2528
2529    PortMode mode = getPortMode(kPortIndexOutput);
2530
2531    switch (mode) {
2532        case KEEP_BUFFERS:
2533        {
2534            // XXX fishy, revisit!!! What about the FREE_BUFFERS case below?
2535
2536            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
2537                // We cannot resubmit the buffer we just rendered, dequeue
2538                // the spare instead.
2539
2540                info = mCodec->dequeueBufferFromNativeWindow();
2541            }
2542            break;
2543        }
2544
2545        case RESUBMIT_BUFFERS:
2546        {
2547            if (!mCodec->mPortEOS[kPortIndexOutput]) {
2548                if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
2549                    // We cannot resubmit the buffer we just rendered, dequeue
2550                    // the spare instead.
2551
2552                    info = mCodec->dequeueBufferFromNativeWindow();
2553                }
2554
2555                if (info != NULL) {
2556                    ALOGV("[%s] calling fillBuffer %p",
2557                         mCodec->mComponentName.c_str(), info->mBufferID);
2558
2559                    CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
2560                             (status_t)OK);
2561
2562                    info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
2563                }
2564            }
2565            break;
2566        }
2567
2568        default:
2569        {
2570            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
2571
2572            CHECK_EQ((status_t)OK,
2573                     mCodec->freeBuffer(kPortIndexOutput, index));
2574            break;
2575        }
2576    }
2577}
2578
2579////////////////////////////////////////////////////////////////////////////////
2580
2581ACodec::UninitializedState::UninitializedState(ACodec *codec)
2582    : BaseState(codec) {
2583}
2584
2585void ACodec::UninitializedState::stateEntered() {
2586    ALOGV("Now uninitialized");
2587}
2588
2589bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
2590    bool handled = false;
2591
2592    switch (msg->what()) {
2593        case ACodec::kWhatSetup:
2594        {
2595            onSetup(msg);
2596
2597            handled = true;
2598            break;
2599        }
2600
2601        case ACodec::kWhatAllocateComponent:
2602        {
2603            onAllocateComponent(msg);
2604            handled = true;
2605            break;
2606        }
2607
2608        case ACodec::kWhatShutdown:
2609        {
2610            int32_t keepComponentAllocated;
2611            CHECK(msg->findInt32(
2612                        "keepComponentAllocated", &keepComponentAllocated));
2613            CHECK(!keepComponentAllocated);
2614
2615            sp<AMessage> notify = mCodec->mNotify->dup();
2616            notify->setInt32("what", ACodec::kWhatShutdownCompleted);
2617            notify->post();
2618
2619            handled = true;
2620            break;
2621        }
2622
2623        case ACodec::kWhatFlush:
2624        {
2625            sp<AMessage> notify = mCodec->mNotify->dup();
2626            notify->setInt32("what", ACodec::kWhatFlushCompleted);
2627            notify->post();
2628
2629            handled = true;
2630            break;
2631        }
2632
2633        default:
2634            return BaseState::onMessageReceived(msg);
2635    }
2636
2637    return handled;
2638}
2639
2640void ACodec::UninitializedState::onSetup(
2641        const sp<AMessage> &msg) {
2642    if (onAllocateComponent(msg)
2643            && mCodec->mLoadedState->onConfigureComponent(msg)) {
2644        mCodec->mLoadedState->onStart();
2645    }
2646}
2647
2648bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
2649    ALOGV("onAllocateComponent");
2650
2651    CHECK(mCodec->mNode == NULL);
2652
2653    OMXClient client;
2654    CHECK_EQ(client.connect(), (status_t)OK);
2655
2656    sp<IOMX> omx = client.interface();
2657
2658    Vector<String8> matchingCodecs;
2659    Vector<uint32_t> matchingCodecQuirks;
2660
2661    AString mime;
2662
2663    AString componentName;
2664    uint32_t quirks;
2665    if (msg->findString("componentName", &componentName)) {
2666        matchingCodecs.push_back(String8(componentName.c_str()));
2667
2668        if (!OMXCodec::findCodecQuirks(componentName.c_str(), &quirks)) {
2669            quirks = 0;
2670        }
2671        matchingCodecQuirks.push_back(quirks);
2672    } else {
2673        CHECK(msg->findString("mime", &mime));
2674
2675        int32_t encoder;
2676        if (!msg->findInt32("encoder", &encoder)) {
2677            encoder = false;
2678        }
2679
2680        OMXCodec::findMatchingCodecs(
2681                mime.c_str(),
2682                encoder, // createEncoder
2683                NULL,  // matchComponentName
2684                0,     // flags
2685                &matchingCodecs,
2686                &matchingCodecQuirks);
2687    }
2688
2689    sp<CodecObserver> observer = new CodecObserver;
2690    IOMX::node_id node = NULL;
2691
2692    for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
2693            ++matchIndex) {
2694        componentName = matchingCodecs.itemAt(matchIndex).string();
2695        quirks = matchingCodecQuirks.itemAt(matchIndex);
2696
2697        pid_t tid = androidGetTid();
2698        int prevPriority = androidGetThreadPriority(tid);
2699        androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
2700        status_t err = omx->allocateNode(componentName.c_str(), observer, &node);
2701        androidSetThreadPriority(tid, prevPriority);
2702
2703        if (err == OK) {
2704            break;
2705        }
2706
2707        node = NULL;
2708    }
2709
2710    if (node == NULL) {
2711        if (!mime.empty()) {
2712            ALOGE("Unable to instantiate a decoder for type '%s'.",
2713                 mime.c_str());
2714        } else {
2715            ALOGE("Unable to instantiate decoder '%s'.", componentName.c_str());
2716        }
2717
2718        mCodec->signalError(OMX_ErrorComponentNotFound);
2719        return false;
2720    }
2721
2722    sp<AMessage> notify = new AMessage(kWhatOMXMessage, mCodec->id());
2723    observer->setNotificationMessage(notify);
2724
2725    mCodec->mComponentName = componentName;
2726    mCodec->mFlags = 0;
2727
2728    if (componentName.endsWith(".secure")) {
2729        mCodec->mFlags |= kFlagIsSecure;
2730    }
2731
2732    mCodec->mQuirks = quirks;
2733    mCodec->mOMX = omx;
2734    mCodec->mNode = node;
2735
2736    mCodec->mPortEOS[kPortIndexInput] =
2737        mCodec->mPortEOS[kPortIndexOutput] = false;
2738
2739    mCodec->mInputEOSResult = OK;
2740
2741    {
2742        sp<AMessage> notify = mCodec->mNotify->dup();
2743        notify->setInt32("what", ACodec::kWhatComponentAllocated);
2744        notify->setString("componentName", mCodec->mComponentName.c_str());
2745        notify->post();
2746    }
2747
2748    mCodec->changeState(mCodec->mLoadedState);
2749
2750    return true;
2751}
2752
2753////////////////////////////////////////////////////////////////////////////////
2754
2755ACodec::LoadedState::LoadedState(ACodec *codec)
2756    : BaseState(codec) {
2757}
2758
2759void ACodec::LoadedState::stateEntered() {
2760    ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
2761
2762    if (mCodec->mShutdownInProgress) {
2763        bool keepComponentAllocated = mCodec->mKeepComponentAllocated;
2764
2765        mCodec->mShutdownInProgress = false;
2766        mCodec->mKeepComponentAllocated = false;
2767
2768        onShutdown(keepComponentAllocated);
2769    }
2770}
2771
2772void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) {
2773    if (!keepComponentAllocated) {
2774        CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
2775
2776        mCodec->mNativeWindow.clear();
2777        mCodec->mNode = NULL;
2778        mCodec->mOMX.clear();
2779        mCodec->mQuirks = 0;
2780        mCodec->mFlags = 0;
2781        mCodec->mComponentName.clear();
2782
2783        mCodec->changeState(mCodec->mUninitializedState);
2784    }
2785
2786    sp<AMessage> notify = mCodec->mNotify->dup();
2787    notify->setInt32("what", ACodec::kWhatShutdownCompleted);
2788    notify->post();
2789}
2790
2791bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) {
2792    bool handled = false;
2793
2794    switch (msg->what()) {
2795        case ACodec::kWhatConfigureComponent:
2796        {
2797            onConfigureComponent(msg);
2798            handled = true;
2799            break;
2800        }
2801
2802        case ACodec::kWhatStart:
2803        {
2804            onStart();
2805            handled = true;
2806            break;
2807        }
2808
2809        case ACodec::kWhatShutdown:
2810        {
2811            int32_t keepComponentAllocated;
2812            CHECK(msg->findInt32(
2813                        "keepComponentAllocated", &keepComponentAllocated));
2814
2815            onShutdown(keepComponentAllocated);
2816
2817            handled = true;
2818            break;
2819        }
2820
2821        case ACodec::kWhatFlush:
2822        {
2823            sp<AMessage> notify = mCodec->mNotify->dup();
2824            notify->setInt32("what", ACodec::kWhatFlushCompleted);
2825            notify->post();
2826
2827            handled = true;
2828            break;
2829        }
2830
2831        default:
2832            return BaseState::onMessageReceived(msg);
2833    }
2834
2835    return handled;
2836}
2837
2838bool ACodec::LoadedState::onConfigureComponent(
2839        const sp<AMessage> &msg) {
2840    ALOGV("onConfigureComponent");
2841
2842    CHECK(mCodec->mNode != NULL);
2843
2844    AString mime;
2845    CHECK(msg->findString("mime", &mime));
2846
2847    status_t err = mCodec->configureCodec(mime.c_str(), msg);
2848
2849    if (err != OK) {
2850        ALOGE("[%s] configureCodec returning error %d",
2851              mCodec->mComponentName.c_str(), err);
2852
2853        mCodec->signalError(OMX_ErrorUndefined, err);
2854        return false;
2855    }
2856
2857    sp<RefBase> obj;
2858    if (msg->findObject("native-window", &obj)
2859            && strncmp("OMX.google.", mCodec->mComponentName.c_str(), 11)) {
2860        sp<NativeWindowWrapper> nativeWindow(
2861                static_cast<NativeWindowWrapper *>(obj.get()));
2862        CHECK(nativeWindow != NULL);
2863        mCodec->mNativeWindow = nativeWindow->getNativeWindow();
2864    }
2865    CHECK_EQ((status_t)OK, mCodec->initNativeWindow());
2866
2867    {
2868        sp<AMessage> notify = mCodec->mNotify->dup();
2869        notify->setInt32("what", ACodec::kWhatComponentConfigured);
2870        notify->post();
2871    }
2872
2873    return true;
2874}
2875
2876void ACodec::LoadedState::onStart() {
2877    ALOGV("onStart");
2878
2879    CHECK_EQ(mCodec->mOMX->sendCommand(
2880                mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
2881             (status_t)OK);
2882
2883    mCodec->changeState(mCodec->mLoadedToIdleState);
2884}
2885
2886////////////////////////////////////////////////////////////////////////////////
2887
2888ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec)
2889    : BaseState(codec) {
2890}
2891
2892void ACodec::LoadedToIdleState::stateEntered() {
2893    ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
2894
2895    status_t err;
2896    if ((err = allocateBuffers()) != OK) {
2897        ALOGE("Failed to allocate buffers after transitioning to IDLE state "
2898             "(error 0x%08x)",
2899             err);
2900
2901        mCodec->signalError(OMX_ErrorUndefined, err);
2902    }
2903}
2904
2905status_t ACodec::LoadedToIdleState::allocateBuffers() {
2906    status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput);
2907
2908    if (err != OK) {
2909        return err;
2910    }
2911
2912    return mCodec->allocateBuffersOnPort(kPortIndexOutput);
2913}
2914
2915bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
2916    switch (msg->what()) {
2917        case kWhatShutdown:
2918        {
2919            mCodec->deferMessage(msg);
2920            return true;
2921        }
2922
2923        default:
2924            return BaseState::onMessageReceived(msg);
2925    }
2926}
2927
2928bool ACodec::LoadedToIdleState::onOMXEvent(
2929        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2930    switch (event) {
2931        case OMX_EventCmdComplete:
2932        {
2933            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
2934            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
2935
2936            CHECK_EQ(mCodec->mOMX->sendCommand(
2937                        mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting),
2938                     (status_t)OK);
2939
2940            mCodec->changeState(mCodec->mIdleToExecutingState);
2941
2942            return true;
2943        }
2944
2945        default:
2946            return BaseState::onOMXEvent(event, data1, data2);
2947    }
2948}
2949
2950////////////////////////////////////////////////////////////////////////////////
2951
2952ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec)
2953    : BaseState(codec) {
2954}
2955
2956void ACodec::IdleToExecutingState::stateEntered() {
2957    ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
2958}
2959
2960bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
2961    switch (msg->what()) {
2962        case kWhatShutdown:
2963        {
2964            mCodec->deferMessage(msg);
2965            return true;
2966        }
2967
2968        default:
2969            return BaseState::onMessageReceived(msg);
2970    }
2971}
2972
2973bool ACodec::IdleToExecutingState::onOMXEvent(
2974        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2975    switch (event) {
2976        case OMX_EventCmdComplete:
2977        {
2978            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
2979            CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting);
2980
2981            mCodec->mExecutingState->resume();
2982            mCodec->changeState(mCodec->mExecutingState);
2983
2984            return true;
2985        }
2986
2987        default:
2988            return BaseState::onOMXEvent(event, data1, data2);
2989    }
2990}
2991
2992////////////////////////////////////////////////////////////////////////////////
2993
2994ACodec::ExecutingState::ExecutingState(ACodec *codec)
2995    : BaseState(codec),
2996      mActive(false) {
2997}
2998
2999ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode(
3000        OMX_U32 portIndex) {
3001    return RESUBMIT_BUFFERS;
3002}
3003
3004void ACodec::ExecutingState::submitOutputBuffers() {
3005    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
3006        BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
3007
3008        if (mCodec->mNativeWindow != NULL) {
3009            CHECK(info->mStatus == BufferInfo::OWNED_BY_US
3010                    || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
3011
3012            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
3013                continue;
3014            }
3015
3016            status_t err = mCodec->mNativeWindow->lockBuffer(
3017                    mCodec->mNativeWindow.get(),
3018                    info->mGraphicBuffer.get());
3019            CHECK_EQ(err, (status_t)OK);
3020        } else {
3021            CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
3022        }
3023
3024        ALOGV("[%s] calling fillBuffer %p",
3025             mCodec->mComponentName.c_str(), info->mBufferID);
3026
3027        CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
3028                 (status_t)OK);
3029
3030        info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
3031    }
3032}
3033
3034void ACodec::ExecutingState::resume() {
3035    if (mActive) {
3036        ALOGV("[%s] We're already active, no need to resume.",
3037             mCodec->mComponentName.c_str());
3038
3039        return;
3040    }
3041
3042    submitOutputBuffers();
3043
3044    // Post the first input buffer.
3045    CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u);
3046    BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(0);
3047
3048    postFillThisBuffer(info);
3049
3050    mActive = true;
3051}
3052
3053void ACodec::ExecutingState::stateEntered() {
3054    ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
3055
3056    mCodec->processDeferredMessages();
3057}
3058
3059bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) {
3060    bool handled = false;
3061
3062    switch (msg->what()) {
3063        case kWhatShutdown:
3064        {
3065            int32_t keepComponentAllocated;
3066            CHECK(msg->findInt32(
3067                        "keepComponentAllocated", &keepComponentAllocated));
3068
3069            mCodec->mShutdownInProgress = true;
3070            mCodec->mKeepComponentAllocated = keepComponentAllocated;
3071
3072            mActive = false;
3073
3074            CHECK_EQ(mCodec->mOMX->sendCommand(
3075                        mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
3076                     (status_t)OK);
3077
3078            mCodec->changeState(mCodec->mExecutingToIdleState);
3079
3080            handled = true;
3081            break;
3082        }
3083
3084        case kWhatFlush:
3085        {
3086            ALOGV("[%s] ExecutingState flushing now "
3087                 "(codec owns %d/%d input, %d/%d output).",
3088                    mCodec->mComponentName.c_str(),
3089                    mCodec->countBuffersOwnedByComponent(kPortIndexInput),
3090                    mCodec->mBuffers[kPortIndexInput].size(),
3091                    mCodec->countBuffersOwnedByComponent(kPortIndexOutput),
3092                    mCodec->mBuffers[kPortIndexOutput].size());
3093
3094            mActive = false;
3095
3096            CHECK_EQ(mCodec->mOMX->sendCommand(
3097                        mCodec->mNode, OMX_CommandFlush, OMX_ALL),
3098                     (status_t)OK);
3099
3100            mCodec->changeState(mCodec->mFlushingState);
3101
3102            handled = true;
3103            break;
3104        }
3105
3106        case kWhatResume:
3107        {
3108            resume();
3109
3110            handled = true;
3111            break;
3112        }
3113
3114        default:
3115            handled = BaseState::onMessageReceived(msg);
3116            break;
3117    }
3118
3119    return handled;
3120}
3121
3122bool ACodec::ExecutingState::onOMXEvent(
3123        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3124    switch (event) {
3125        case OMX_EventPortSettingsChanged:
3126        {
3127            CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
3128
3129            if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
3130                CHECK_EQ(mCodec->mOMX->sendCommand(
3131                            mCodec->mNode,
3132                            OMX_CommandPortDisable, kPortIndexOutput),
3133                         (status_t)OK);
3134
3135                mCodec->freeOutputBuffersNotOwnedByComponent();
3136
3137                mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
3138            } else if (data2 == OMX_IndexConfigCommonOutputCrop) {
3139                mCodec->mSentFormat = false;
3140            } else {
3141                ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx",
3142                     mCodec->mComponentName.c_str(), data2);
3143            }
3144
3145            return true;
3146        }
3147
3148        case OMX_EventBufferFlag:
3149        {
3150            return true;
3151        }
3152
3153        default:
3154            return BaseState::onOMXEvent(event, data1, data2);
3155    }
3156}
3157
3158////////////////////////////////////////////////////////////////////////////////
3159
3160ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState(
3161        ACodec *codec)
3162    : BaseState(codec) {
3163}
3164
3165ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode(
3166        OMX_U32 portIndex) {
3167    if (portIndex == kPortIndexOutput) {
3168        return FREE_BUFFERS;
3169    }
3170
3171    CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput);
3172
3173    return RESUBMIT_BUFFERS;
3174}
3175
3176bool ACodec::OutputPortSettingsChangedState::onMessageReceived(
3177        const sp<AMessage> &msg) {
3178    bool handled = false;
3179
3180    switch (msg->what()) {
3181        case kWhatFlush:
3182        case kWhatShutdown:
3183        case kWhatResume:
3184        {
3185            if (msg->what() == kWhatResume) {
3186                ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
3187            }
3188
3189            mCodec->deferMessage(msg);
3190            handled = true;
3191            break;
3192        }
3193
3194        default:
3195            handled = BaseState::onMessageReceived(msg);
3196            break;
3197    }
3198
3199    return handled;
3200}
3201
3202void ACodec::OutputPortSettingsChangedState::stateEntered() {
3203    ALOGV("[%s] Now handling output port settings change",
3204         mCodec->mComponentName.c_str());
3205}
3206
3207bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
3208        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3209    switch (event) {
3210        case OMX_EventCmdComplete:
3211        {
3212            if (data1 == (OMX_U32)OMX_CommandPortDisable) {
3213                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
3214
3215                ALOGV("[%s] Output port now disabled.",
3216                        mCodec->mComponentName.c_str());
3217
3218                CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty());
3219                mCodec->mDealer[kPortIndexOutput].clear();
3220
3221                CHECK_EQ(mCodec->mOMX->sendCommand(
3222                            mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput),
3223                         (status_t)OK);
3224
3225                status_t err;
3226                if ((err = mCodec->allocateBuffersOnPort(
3227                                kPortIndexOutput)) != OK) {
3228                    ALOGE("Failed to allocate output port buffers after "
3229                         "port reconfiguration (error 0x%08x)",
3230                         err);
3231
3232                    mCodec->signalError(OMX_ErrorUndefined, err);
3233
3234                    // This is technically not correct, since we were unable
3235                    // to allocate output buffers and therefore the output port
3236                    // remains disabled. It is necessary however to allow us
3237                    // to shutdown the codec properly.
3238                    mCodec->changeState(mCodec->mExecutingState);
3239                }
3240
3241                return true;
3242            } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
3243                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
3244
3245                mCodec->mSentFormat = false;
3246
3247                ALOGV("[%s] Output port now reenabled.",
3248                        mCodec->mComponentName.c_str());
3249
3250                if (mCodec->mExecutingState->active()) {
3251                    mCodec->mExecutingState->submitOutputBuffers();
3252                }
3253
3254                mCodec->changeState(mCodec->mExecutingState);
3255
3256                return true;
3257            }
3258
3259            return false;
3260        }
3261
3262        default:
3263            return false;
3264    }
3265}
3266
3267////////////////////////////////////////////////////////////////////////////////
3268
3269ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec)
3270    : BaseState(codec),
3271      mComponentNowIdle(false) {
3272}
3273
3274bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) {
3275    bool handled = false;
3276
3277    switch (msg->what()) {
3278        case kWhatFlush:
3279        {
3280            // Don't send me a flush request if you previously wanted me
3281            // to shutdown.
3282            TRESPASS();
3283            break;
3284        }
3285
3286        case kWhatShutdown:
3287        {
3288            // We're already doing that...
3289
3290            handled = true;
3291            break;
3292        }
3293
3294        default:
3295            handled = BaseState::onMessageReceived(msg);
3296            break;
3297    }
3298
3299    return handled;
3300}
3301
3302void ACodec::ExecutingToIdleState::stateEntered() {
3303    ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
3304
3305    mComponentNowIdle = false;
3306    mCodec->mSentFormat = false;
3307}
3308
3309bool ACodec::ExecutingToIdleState::onOMXEvent(
3310        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3311    switch (event) {
3312        case OMX_EventCmdComplete:
3313        {
3314            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
3315            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
3316
3317            mComponentNowIdle = true;
3318
3319            changeStateIfWeOwnAllBuffers();
3320
3321            return true;
3322        }
3323
3324        case OMX_EventPortSettingsChanged:
3325        case OMX_EventBufferFlag:
3326        {
3327            // We're shutting down and don't care about this anymore.
3328            return true;
3329        }
3330
3331        default:
3332            return BaseState::onOMXEvent(event, data1, data2);
3333    }
3334}
3335
3336void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
3337    if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) {
3338        CHECK_EQ(mCodec->mOMX->sendCommand(
3339                    mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded),
3340                 (status_t)OK);
3341
3342        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK);
3343        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK);
3344
3345        mCodec->changeState(mCodec->mIdleToLoadedState);
3346    }
3347}
3348
3349void ACodec::ExecutingToIdleState::onInputBufferFilled(
3350        const sp<AMessage> &msg) {
3351    BaseState::onInputBufferFilled(msg);
3352
3353    changeStateIfWeOwnAllBuffers();
3354}
3355
3356void ACodec::ExecutingToIdleState::onOutputBufferDrained(
3357        const sp<AMessage> &msg) {
3358    BaseState::onOutputBufferDrained(msg);
3359
3360    changeStateIfWeOwnAllBuffers();
3361}
3362
3363////////////////////////////////////////////////////////////////////////////////
3364
3365ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec)
3366    : BaseState(codec) {
3367}
3368
3369bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) {
3370    bool handled = false;
3371
3372    switch (msg->what()) {
3373        case kWhatShutdown:
3374        {
3375            // We're already doing that...
3376
3377            handled = true;
3378            break;
3379        }
3380
3381        case kWhatFlush:
3382        {
3383            // Don't send me a flush request if you previously wanted me
3384            // to shutdown.
3385            TRESPASS();
3386            break;
3387        }
3388
3389        default:
3390            handled = BaseState::onMessageReceived(msg);
3391            break;
3392    }
3393
3394    return handled;
3395}
3396
3397void ACodec::IdleToLoadedState::stateEntered() {
3398    ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
3399}
3400
3401bool ACodec::IdleToLoadedState::onOMXEvent(
3402        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3403    switch (event) {
3404        case OMX_EventCmdComplete:
3405        {
3406            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
3407            CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded);
3408
3409            mCodec->changeState(mCodec->mLoadedState);
3410
3411            return true;
3412        }
3413
3414        default:
3415            return BaseState::onOMXEvent(event, data1, data2);
3416    }
3417}
3418
3419////////////////////////////////////////////////////////////////////////////////
3420
3421ACodec::FlushingState::FlushingState(ACodec *codec)
3422    : BaseState(codec) {
3423}
3424
3425void ACodec::FlushingState::stateEntered() {
3426    ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());
3427
3428    mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
3429}
3430
3431bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) {
3432    bool handled = false;
3433
3434    switch (msg->what()) {
3435        case kWhatShutdown:
3436        {
3437            mCodec->deferMessage(msg);
3438            break;
3439        }
3440
3441        case kWhatFlush:
3442        {
3443            // We're already doing this right now.
3444            handled = true;
3445            break;
3446        }
3447
3448        default:
3449            handled = BaseState::onMessageReceived(msg);
3450            break;
3451    }
3452
3453    return handled;
3454}
3455
3456bool ACodec::FlushingState::onOMXEvent(
3457        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3458    ALOGV("[%s] FlushingState onOMXEvent(%d,%ld)",
3459            mCodec->mComponentName.c_str(), event, data1);
3460
3461    switch (event) {
3462        case OMX_EventCmdComplete:
3463        {
3464            CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush);
3465
3466            if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
3467                CHECK(!mFlushComplete[data2]);
3468                mFlushComplete[data2] = true;
3469
3470                if (mFlushComplete[kPortIndexInput]
3471                        && mFlushComplete[kPortIndexOutput]) {
3472                    changeStateIfWeOwnAllBuffers();
3473                }
3474            } else {
3475                CHECK_EQ(data2, OMX_ALL);
3476                CHECK(mFlushComplete[kPortIndexInput]);
3477                CHECK(mFlushComplete[kPortIndexOutput]);
3478
3479                changeStateIfWeOwnAllBuffers();
3480            }
3481
3482            return true;
3483        }
3484
3485        case OMX_EventPortSettingsChanged:
3486        {
3487            sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id());
3488            msg->setInt32("type", omx_message::EVENT);
3489            msg->setPointer("node", mCodec->mNode);
3490            msg->setInt32("event", event);
3491            msg->setInt32("data1", data1);
3492            msg->setInt32("data2", data2);
3493
3494            ALOGV("[%s] Deferring OMX_EventPortSettingsChanged",
3495                 mCodec->mComponentName.c_str());
3496
3497            mCodec->deferMessage(msg);
3498
3499            return true;
3500        }
3501
3502        default:
3503            return BaseState::onOMXEvent(event, data1, data2);
3504    }
3505
3506    return true;
3507}
3508
3509void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) {
3510    BaseState::onOutputBufferDrained(msg);
3511
3512    changeStateIfWeOwnAllBuffers();
3513}
3514
3515void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) {
3516    BaseState::onInputBufferFilled(msg);
3517
3518    changeStateIfWeOwnAllBuffers();
3519}
3520
3521void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() {
3522    if (mFlushComplete[kPortIndexInput]
3523            && mFlushComplete[kPortIndexOutput]
3524            && mCodec->allYourBuffersAreBelongToUs()) {
3525        sp<AMessage> notify = mCodec->mNotify->dup();
3526        notify->setInt32("what", ACodec::kWhatFlushCompleted);
3527        notify->post();
3528
3529        mCodec->mPortEOS[kPortIndexInput] =
3530            mCodec->mPortEOS[kPortIndexOutput] = false;
3531
3532        mCodec->mInputEOSResult = OK;
3533
3534        mCodec->changeState(mCodec->mExecutingState);
3535    }
3536}
3537
3538}  // namespace android
3539