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