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