ACodec.cpp revision 3097dafa3ee60440c10b5bf9ed4d355fee1c1ae5
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#ifdef __LP64__
21#define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
22#endif
23
24#include <inttypes.h>
25#include <utils/Trace.h>
26
27#include <media/stagefright/ACodec.h>
28
29#include <binder/MemoryDealer.h>
30
31#include <media/stagefright/foundation/hexdump.h>
32#include <media/stagefright/foundation/ABuffer.h>
33#include <media/stagefright/foundation/ADebug.h>
34#include <media/stagefright/foundation/AMessage.h>
35#include <media/stagefright/foundation/AUtils.h>
36
37#include <media/stagefright/BufferProducerWrapper.h>
38#include <media/stagefright/MediaCodecList.h>
39#include <media/stagefright/MediaDefs.h>
40#include <media/stagefright/NativeWindowWrapper.h>
41#include <media/stagefright/OMXClient.h>
42#include <media/stagefright/OMXCodec.h>
43
44#include <media/hardware/HardwareAPI.h>
45
46#include <OMX_AudioExt.h>
47#include <OMX_VideoExt.h>
48#include <OMX_Component.h>
49#include <OMX_IndexExt.h>
50
51#include "include/avc_utils.h"
52
53namespace android {
54
55// OMX errors are directly mapped into status_t range if
56// there is no corresponding MediaError status code.
57// Use the statusFromOMXError(int32_t omxError) function.
58//
59// Currently this is a direct map.
60// See frameworks/native/include/media/openmax/OMX_Core.h
61//
62// Vendor OMX errors     from 0x90000000 - 0x9000FFFF
63// Extension OMX errors  from 0x8F000000 - 0x90000000
64// Standard OMX errors   from 0x80001000 - 0x80001024 (0x80001024 current)
65//
66
67// returns true if err is a recognized OMX error code.
68// as OMX error is OMX_S32, this is an int32_t type
69static inline bool isOMXError(int32_t err) {
70    return (ERROR_CODEC_MIN <= err && err <= ERROR_CODEC_MAX);
71}
72
73// converts an OMX error to a status_t
74static inline status_t statusFromOMXError(int32_t omxError) {
75    switch (omxError) {
76    case OMX_ErrorInvalidComponentName:
77    case OMX_ErrorComponentNotFound:
78        return NAME_NOT_FOUND; // can trigger illegal argument error for provided names.
79    default:
80        return isOMXError(omxError) ? omxError : 0; // no translation required
81    }
82}
83
84// checks and converts status_t to a non-side-effect status_t
85static inline status_t makeNoSideEffectStatus(status_t err) {
86    switch (err) {
87    // the following errors have side effects and may come
88    // from other code modules. Remap for safety reasons.
89    case INVALID_OPERATION:
90    case DEAD_OBJECT:
91        return UNKNOWN_ERROR;
92    default:
93        return err;
94    }
95}
96
97template<class T>
98static void InitOMXParams(T *params) {
99    params->nSize = sizeof(T);
100    params->nVersion.s.nVersionMajor = 1;
101    params->nVersion.s.nVersionMinor = 0;
102    params->nVersion.s.nRevision = 0;
103    params->nVersion.s.nStep = 0;
104}
105
106struct CodecObserver : public BnOMXObserver {
107    CodecObserver() {}
108
109    void setNotificationMessage(const sp<AMessage> &msg) {
110        mNotify = msg;
111    }
112
113    // from IOMXObserver
114    virtual void onMessage(const omx_message &omx_msg) {
115        sp<AMessage> msg = mNotify->dup();
116
117        msg->setInt32("type", omx_msg.type);
118        msg->setInt32("node", omx_msg.node);
119
120        switch (omx_msg.type) {
121            case omx_message::EVENT:
122            {
123                msg->setInt32("event", omx_msg.u.event_data.event);
124                msg->setInt32("data1", omx_msg.u.event_data.data1);
125                msg->setInt32("data2", omx_msg.u.event_data.data2);
126                break;
127            }
128
129            case omx_message::EMPTY_BUFFER_DONE:
130            {
131                msg->setInt32("buffer", omx_msg.u.buffer_data.buffer);
132                break;
133            }
134
135            case omx_message::FILL_BUFFER_DONE:
136            {
137                msg->setInt32(
138                        "buffer", omx_msg.u.extended_buffer_data.buffer);
139                msg->setInt32(
140                        "range_offset",
141                        omx_msg.u.extended_buffer_data.range_offset);
142                msg->setInt32(
143                        "range_length",
144                        omx_msg.u.extended_buffer_data.range_length);
145                msg->setInt32(
146                        "flags",
147                        omx_msg.u.extended_buffer_data.flags);
148                msg->setInt64(
149                        "timestamp",
150                        omx_msg.u.extended_buffer_data.timestamp);
151                break;
152            }
153
154            default:
155                TRESPASS();
156                break;
157        }
158
159        msg->post();
160    }
161
162protected:
163    virtual ~CodecObserver() {}
164
165private:
166    sp<AMessage> mNotify;
167
168    DISALLOW_EVIL_CONSTRUCTORS(CodecObserver);
169};
170
171////////////////////////////////////////////////////////////////////////////////
172
173struct ACodec::BaseState : public AState {
174    BaseState(ACodec *codec, const sp<AState> &parentState = NULL);
175
176protected:
177    enum PortMode {
178        KEEP_BUFFERS,
179        RESUBMIT_BUFFERS,
180        FREE_BUFFERS,
181    };
182
183    ACodec *mCodec;
184
185    virtual PortMode getPortMode(OMX_U32 portIndex);
186
187    virtual bool onMessageReceived(const sp<AMessage> &msg);
188
189    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
190
191    virtual void onOutputBufferDrained(const sp<AMessage> &msg);
192    virtual void onInputBufferFilled(const sp<AMessage> &msg);
193
194    void postFillThisBuffer(BufferInfo *info);
195
196private:
197    bool onOMXMessage(const sp<AMessage> &msg);
198
199    bool onOMXEmptyBufferDone(IOMX::buffer_id bufferID);
200
201    bool onOMXFillBufferDone(
202            IOMX::buffer_id bufferID,
203            size_t rangeOffset, size_t rangeLength,
204            OMX_U32 flags,
205            int64_t timeUs);
206
207    void getMoreInputDataIfPossible();
208
209    DISALLOW_EVIL_CONSTRUCTORS(BaseState);
210};
211
212////////////////////////////////////////////////////////////////////////////////
213
214struct ACodec::DeathNotifier : public IBinder::DeathRecipient {
215    DeathNotifier(const sp<AMessage> &notify)
216        : mNotify(notify) {
217    }
218
219    virtual void binderDied(const wp<IBinder> &) {
220        mNotify->post();
221    }
222
223protected:
224    virtual ~DeathNotifier() {}
225
226private:
227    sp<AMessage> mNotify;
228
229    DISALLOW_EVIL_CONSTRUCTORS(DeathNotifier);
230};
231
232struct ACodec::UninitializedState : public ACodec::BaseState {
233    UninitializedState(ACodec *codec);
234
235protected:
236    virtual bool onMessageReceived(const sp<AMessage> &msg);
237    virtual void stateEntered();
238
239private:
240    void onSetup(const sp<AMessage> &msg);
241    bool onAllocateComponent(const sp<AMessage> &msg);
242
243    sp<DeathNotifier> mDeathNotifier;
244
245    DISALLOW_EVIL_CONSTRUCTORS(UninitializedState);
246};
247
248////////////////////////////////////////////////////////////////////////////////
249
250struct ACodec::LoadedState : public ACodec::BaseState {
251    LoadedState(ACodec *codec);
252
253protected:
254    virtual bool onMessageReceived(const sp<AMessage> &msg);
255    virtual void stateEntered();
256
257private:
258    friend struct ACodec::UninitializedState;
259
260    bool onConfigureComponent(const sp<AMessage> &msg);
261    void onCreateInputSurface(const sp<AMessage> &msg);
262    void onStart();
263    void onShutdown(bool keepComponentAllocated);
264
265    DISALLOW_EVIL_CONSTRUCTORS(LoadedState);
266};
267
268////////////////////////////////////////////////////////////////////////////////
269
270struct ACodec::LoadedToIdleState : public ACodec::BaseState {
271    LoadedToIdleState(ACodec *codec);
272
273protected:
274    virtual bool onMessageReceived(const sp<AMessage> &msg);
275    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
276    virtual void stateEntered();
277
278private:
279    status_t allocateBuffers();
280
281    DISALLOW_EVIL_CONSTRUCTORS(LoadedToIdleState);
282};
283
284////////////////////////////////////////////////////////////////////////////////
285
286struct ACodec::IdleToExecutingState : public ACodec::BaseState {
287    IdleToExecutingState(ACodec *codec);
288
289protected:
290    virtual bool onMessageReceived(const sp<AMessage> &msg);
291    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
292    virtual void stateEntered();
293
294private:
295    DISALLOW_EVIL_CONSTRUCTORS(IdleToExecutingState);
296};
297
298////////////////////////////////////////////////////////////////////////////////
299
300struct ACodec::ExecutingState : public ACodec::BaseState {
301    ExecutingState(ACodec *codec);
302
303    void submitRegularOutputBuffers();
304    void submitOutputMetaBuffers();
305    void submitOutputBuffers();
306
307    // Submit output buffers to the decoder, submit input buffers to client
308    // to fill with data.
309    void resume();
310
311    // Returns true iff input and output buffers are in play.
312    bool active() const { return mActive; }
313
314protected:
315    virtual PortMode getPortMode(OMX_U32 portIndex);
316    virtual bool onMessageReceived(const sp<AMessage> &msg);
317    virtual void stateEntered();
318
319    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
320
321private:
322    bool mActive;
323
324    DISALLOW_EVIL_CONSTRUCTORS(ExecutingState);
325};
326
327////////////////////////////////////////////////////////////////////////////////
328
329struct ACodec::OutputPortSettingsChangedState : public ACodec::BaseState {
330    OutputPortSettingsChangedState(ACodec *codec);
331
332protected:
333    virtual PortMode getPortMode(OMX_U32 portIndex);
334    virtual bool onMessageReceived(const sp<AMessage> &msg);
335    virtual void stateEntered();
336
337    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
338
339private:
340    DISALLOW_EVIL_CONSTRUCTORS(OutputPortSettingsChangedState);
341};
342
343////////////////////////////////////////////////////////////////////////////////
344
345struct ACodec::ExecutingToIdleState : public ACodec::BaseState {
346    ExecutingToIdleState(ACodec *codec);
347
348protected:
349    virtual bool onMessageReceived(const sp<AMessage> &msg);
350    virtual void stateEntered();
351
352    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
353
354    virtual void onOutputBufferDrained(const sp<AMessage> &msg);
355    virtual void onInputBufferFilled(const sp<AMessage> &msg);
356
357private:
358    void changeStateIfWeOwnAllBuffers();
359
360    bool mComponentNowIdle;
361
362    DISALLOW_EVIL_CONSTRUCTORS(ExecutingToIdleState);
363};
364
365////////////////////////////////////////////////////////////////////////////////
366
367struct ACodec::IdleToLoadedState : public ACodec::BaseState {
368    IdleToLoadedState(ACodec *codec);
369
370protected:
371    virtual bool onMessageReceived(const sp<AMessage> &msg);
372    virtual void stateEntered();
373
374    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
375
376private:
377    DISALLOW_EVIL_CONSTRUCTORS(IdleToLoadedState);
378};
379
380////////////////////////////////////////////////////////////////////////////////
381
382struct ACodec::FlushingState : public ACodec::BaseState {
383    FlushingState(ACodec *codec);
384
385protected:
386    virtual bool onMessageReceived(const sp<AMessage> &msg);
387    virtual void stateEntered();
388
389    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
390
391    virtual void onOutputBufferDrained(const sp<AMessage> &msg);
392    virtual void onInputBufferFilled(const sp<AMessage> &msg);
393
394private:
395    bool mFlushComplete[2];
396
397    void changeStateIfWeOwnAllBuffers();
398
399    DISALLOW_EVIL_CONSTRUCTORS(FlushingState);
400};
401
402////////////////////////////////////////////////////////////////////////////////
403
404ACodec::ACodec()
405    : mQuirks(0),
406      mNode(0),
407      mSentFormat(false),
408      mIsEncoder(false),
409      mUseMetadataOnEncoderOutput(false),
410      mShutdownInProgress(false),
411      mExplicitShutdown(false),
412      mEncoderDelay(0),
413      mEncoderPadding(0),
414      mRotationDegrees(0),
415      mChannelMaskPresent(false),
416      mChannelMask(0),
417      mDequeueCounter(0),
418      mStoreMetaDataInOutputBuffers(false),
419      mMetaDataBuffersToSubmit(0),
420      mRepeatFrameDelayUs(-1ll),
421      mMaxPtsGapUs(-1ll),
422      mTimePerFrameUs(-1ll),
423      mTimePerCaptureUs(-1ll),
424      mCreateInputBuffersSuspended(false),
425      mTunneled(false) {
426    mUninitializedState = new UninitializedState(this);
427    mLoadedState = new LoadedState(this);
428    mLoadedToIdleState = new LoadedToIdleState(this);
429    mIdleToExecutingState = new IdleToExecutingState(this);
430    mExecutingState = new ExecutingState(this);
431
432    mOutputPortSettingsChangedState =
433        new OutputPortSettingsChangedState(this);
434
435    mExecutingToIdleState = new ExecutingToIdleState(this);
436    mIdleToLoadedState = new IdleToLoadedState(this);
437    mFlushingState = new FlushingState(this);
438
439    mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false;
440    mInputEOSResult = OK;
441
442    changeState(mUninitializedState);
443}
444
445ACodec::~ACodec() {
446}
447
448void ACodec::setNotificationMessage(const sp<AMessage> &msg) {
449    mNotify = msg;
450}
451
452void ACodec::initiateSetup(const sp<AMessage> &msg) {
453    msg->setWhat(kWhatSetup);
454    msg->setTarget(id());
455    msg->post();
456}
457
458void ACodec::signalSetParameters(const sp<AMessage> &params) {
459    sp<AMessage> msg = new AMessage(kWhatSetParameters, id());
460    msg->setMessage("params", params);
461    msg->post();
462}
463
464void ACodec::initiateAllocateComponent(const sp<AMessage> &msg) {
465    msg->setWhat(kWhatAllocateComponent);
466    msg->setTarget(id());
467    msg->post();
468}
469
470void ACodec::initiateConfigureComponent(const sp<AMessage> &msg) {
471    msg->setWhat(kWhatConfigureComponent);
472    msg->setTarget(id());
473    msg->post();
474}
475
476void ACodec::initiateCreateInputSurface() {
477    (new AMessage(kWhatCreateInputSurface, id()))->post();
478}
479
480void ACodec::signalEndOfInputStream() {
481    (new AMessage(kWhatSignalEndOfInputStream, id()))->post();
482}
483
484void ACodec::initiateStart() {
485    (new AMessage(kWhatStart, id()))->post();
486}
487
488void ACodec::signalFlush() {
489    ALOGV("[%s] signalFlush", mComponentName.c_str());
490    (new AMessage(kWhatFlush, id()))->post();
491}
492
493void ACodec::signalResume() {
494    (new AMessage(kWhatResume, id()))->post();
495}
496
497void ACodec::initiateShutdown(bool keepComponentAllocated) {
498    sp<AMessage> msg = new AMessage(kWhatShutdown, id());
499    msg->setInt32("keepComponentAllocated", keepComponentAllocated);
500    msg->post();
501    if (!keepComponentAllocated) {
502        // ensure shutdown completes in 3 seconds
503        (new AMessage(kWhatReleaseCodecInstance, id()))->post(3000000);
504    }
505}
506
507void ACodec::signalRequestIDRFrame() {
508    (new AMessage(kWhatRequestIDRFrame, id()))->post();
509}
510
511// *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
512// Some codecs may return input buffers before having them processed.
513// This causes a halt if we already signaled an EOS on the input
514// port.  For now keep submitting an output buffer if there was an
515// EOS on the input port, but not yet on the output port.
516void ACodec::signalSubmitOutputMetaDataBufferIfEOS_workaround() {
517    if (mPortEOS[kPortIndexInput] && !mPortEOS[kPortIndexOutput] &&
518            mMetaDataBuffersToSubmit > 0) {
519        (new AMessage(kWhatSubmitOutputMetaDataBufferIfEOS, id()))->post();
520    }
521}
522
523status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) {
524    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
525
526    CHECK(mDealer[portIndex] == NULL);
527    CHECK(mBuffers[portIndex].isEmpty());
528
529    status_t err;
530    if (mNativeWindow != NULL && portIndex == kPortIndexOutput) {
531        if (mStoreMetaDataInOutputBuffers) {
532            err = allocateOutputMetaDataBuffers();
533        } else {
534            err = allocateOutputBuffersFromNativeWindow();
535        }
536    } else {
537        OMX_PARAM_PORTDEFINITIONTYPE def;
538        InitOMXParams(&def);
539        def.nPortIndex = portIndex;
540
541        err = mOMX->getParameter(
542                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
543
544        if (err == OK) {
545            ALOGV("[%s] Allocating %u buffers of size %u on %s port",
546                    mComponentName.c_str(),
547                    def.nBufferCountActual, def.nBufferSize,
548                    portIndex == kPortIndexInput ? "input" : "output");
549
550            size_t totalSize = def.nBufferCountActual * def.nBufferSize;
551            mDealer[portIndex] = new MemoryDealer(totalSize, "ACodec");
552
553            for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
554                sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
555                CHECK(mem.get() != NULL);
556
557                BufferInfo info;
558                info.mStatus = BufferInfo::OWNED_BY_US;
559
560                uint32_t requiresAllocateBufferBit =
561                    (portIndex == kPortIndexInput)
562                        ? OMXCodec::kRequiresAllocateBufferOnInputPorts
563                        : OMXCodec::kRequiresAllocateBufferOnOutputPorts;
564
565                if ((portIndex == kPortIndexInput && (mFlags & kFlagIsSecure))
566                        || mUseMetadataOnEncoderOutput) {
567                    mem.clear();
568
569                    void *ptr;
570                    err = mOMX->allocateBuffer(
571                            mNode, portIndex, def.nBufferSize, &info.mBufferID,
572                            &ptr);
573
574                    int32_t bufSize = mUseMetadataOnEncoderOutput ?
575                            (4 + sizeof(buffer_handle_t)) : def.nBufferSize;
576
577                    info.mData = new ABuffer(ptr, bufSize);
578                } else if (mQuirks & requiresAllocateBufferBit) {
579                    err = mOMX->allocateBufferWithBackup(
580                            mNode, portIndex, mem, &info.mBufferID);
581                } else {
582                    err = mOMX->useBuffer(mNode, portIndex, mem, &info.mBufferID);
583                }
584
585                if (mem != NULL) {
586                    info.mData = new ABuffer(mem->pointer(), def.nBufferSize);
587                }
588
589                mBuffers[portIndex].push(info);
590            }
591        }
592    }
593
594    if (err != OK) {
595        return err;
596    }
597
598    sp<AMessage> notify = mNotify->dup();
599    notify->setInt32("what", CodecBase::kWhatBuffersAllocated);
600
601    notify->setInt32("portIndex", portIndex);
602
603    sp<PortDescription> desc = new PortDescription;
604
605    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
606        const BufferInfo &info = mBuffers[portIndex][i];
607
608        desc->addBuffer(info.mBufferID, info.mData);
609    }
610
611    notify->setObject("portDesc", desc);
612    notify->post();
613
614    return OK;
615}
616
617status_t ACodec::configureOutputBuffersFromNativeWindow(
618        OMX_U32 *bufferCount, OMX_U32 *bufferSize,
619        OMX_U32 *minUndequeuedBuffers) {
620    OMX_PARAM_PORTDEFINITIONTYPE def;
621    InitOMXParams(&def);
622    def.nPortIndex = kPortIndexOutput;
623
624    status_t err = mOMX->getParameter(
625            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
626
627    if (err != OK) {
628        return err;
629    }
630
631    err = native_window_set_buffers_geometry(
632            mNativeWindow.get(),
633            def.format.video.nFrameWidth,
634            def.format.video.nFrameHeight,
635            def.format.video.eColorFormat);
636
637    if (err != 0) {
638        ALOGE("native_window_set_buffers_geometry failed: %s (%d)",
639                strerror(-err), -err);
640        return err;
641    }
642
643    if (mRotationDegrees != 0) {
644        uint32_t transform = 0;
645        switch (mRotationDegrees) {
646            case 0: transform = 0; break;
647            case 90: transform = HAL_TRANSFORM_ROT_90; break;
648            case 180: transform = HAL_TRANSFORM_ROT_180; break;
649            case 270: transform = HAL_TRANSFORM_ROT_270; break;
650            default: transform = 0; break;
651        }
652
653        if (transform > 0) {
654            err = native_window_set_buffers_transform(
655                    mNativeWindow.get(), transform);
656            if (err != 0) {
657                ALOGE("native_window_set_buffers_transform failed: %s (%d)",
658                        strerror(-err), -err);
659                return err;
660            }
661        }
662    }
663
664    // Set up the native window.
665    OMX_U32 usage = 0;
666    err = mOMX->getGraphicBufferUsage(mNode, kPortIndexOutput, &usage);
667    if (err != 0) {
668        ALOGW("querying usage flags from OMX IL component failed: %d", err);
669        // XXX: Currently this error is logged, but not fatal.
670        usage = 0;
671    }
672
673    if (mFlags & kFlagIsGrallocUsageProtected) {
674        usage |= GRALLOC_USAGE_PROTECTED;
675    }
676
677    // Make sure to check whether either Stagefright or the video decoder
678    // requested protected buffers.
679    if (usage & GRALLOC_USAGE_PROTECTED) {
680        // Verify that the ANativeWindow sends images directly to
681        // SurfaceFlinger.
682        int queuesToNativeWindow = 0;
683        err = mNativeWindow->query(
684                mNativeWindow.get(), NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER,
685                &queuesToNativeWindow);
686        if (err != 0) {
687            ALOGE("error authenticating native window: %d", err);
688            return err;
689        }
690        if (queuesToNativeWindow != 1) {
691            ALOGE("native window could not be authenticated");
692            return PERMISSION_DENIED;
693        }
694    }
695
696    err = native_window_set_usage(
697            mNativeWindow.get(),
698            usage | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP);
699
700    if (err != 0) {
701        ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err);
702        return err;
703    }
704
705    // Exits here for tunneled video playback codecs -- i.e. skips native window
706    // buffer allocation step as this is managed by the tunneled OMX omponent
707    // itself and explicitly sets def.nBufferCountActual to 0.
708    if (mTunneled) {
709        ALOGV("Tunneled Playback: skipping native window buffer allocation.");
710        def.nBufferCountActual = 0;
711        err = mOMX->setParameter(
712                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
713
714        *minUndequeuedBuffers = 0;
715        *bufferCount = 0;
716        *bufferSize = 0;
717        return err;
718    }
719
720    *minUndequeuedBuffers = 0;
721    err = mNativeWindow->query(
722            mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
723            (int *)minUndequeuedBuffers);
724
725    if (err != 0) {
726        ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)",
727                strerror(-err), -err);
728        return err;
729    }
730
731    // FIXME: assume that surface is controlled by app (native window
732    // returns the number for the case when surface is not controlled by app)
733    // FIXME2: This means that minUndeqeueudBufs can be 1 larger than reported
734    // For now, try to allocate 1 more buffer, but don't fail if unsuccessful
735
736    // Use conservative allocation while also trying to reduce starvation
737    //
738    // 1. allocate at least nBufferCountMin + minUndequeuedBuffers - that is the
739    //    minimum needed for the consumer to be able to work
740    // 2. try to allocate two (2) additional buffers to reduce starvation from
741    //    the consumer
742    //    plus an extra buffer to account for incorrect minUndequeuedBufs
743    for (OMX_U32 extraBuffers = 2 + 1; /* condition inside loop */; extraBuffers--) {
744        OMX_U32 newBufferCount =
745            def.nBufferCountMin + *minUndequeuedBuffers + extraBuffers;
746        def.nBufferCountActual = newBufferCount;
747        err = mOMX->setParameter(
748                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
749
750        if (err == OK) {
751            *minUndequeuedBuffers += extraBuffers;
752            break;
753        }
754
755        ALOGW("[%s] setting nBufferCountActual to %u failed: %d",
756                mComponentName.c_str(), newBufferCount, err);
757        /* exit condition */
758        if (extraBuffers == 0) {
759            return err;
760        }
761    }
762
763    err = native_window_set_buffer_count(
764            mNativeWindow.get(), def.nBufferCountActual);
765
766    if (err != 0) {
767        ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err),
768                -err);
769        return err;
770    }
771
772    *bufferCount = def.nBufferCountActual;
773    *bufferSize =  def.nBufferSize;
774    return err;
775}
776
777status_t ACodec::allocateOutputBuffersFromNativeWindow() {
778    OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers;
779    status_t err = configureOutputBuffersFromNativeWindow(
780            &bufferCount, &bufferSize, &minUndequeuedBuffers);
781    if (err != 0)
782        return err;
783    mNumUndequeuedBuffers = minUndequeuedBuffers;
784
785    ALOGV("[%s] Allocating %u buffers from a native window of size %u on "
786         "output port",
787         mComponentName.c_str(), bufferCount, bufferSize);
788
789    // Dequeue buffers and send them to OMX
790    for (OMX_U32 i = 0; i < bufferCount; i++) {
791        ANativeWindowBuffer *buf;
792        err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &buf);
793        if (err != 0) {
794            ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
795            break;
796        }
797
798        sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false));
799        BufferInfo info;
800        info.mStatus = BufferInfo::OWNED_BY_US;
801        info.mData = new ABuffer(NULL /* data */, bufferSize /* capacity */);
802        info.mGraphicBuffer = graphicBuffer;
803        mBuffers[kPortIndexOutput].push(info);
804
805        IOMX::buffer_id bufferId;
806        err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer,
807                &bufferId);
808        if (err != 0) {
809            ALOGE("registering GraphicBuffer %u with OMX IL component failed: "
810                 "%d", i, err);
811            break;
812        }
813
814        mBuffers[kPortIndexOutput].editItemAt(i).mBufferID = bufferId;
815
816        ALOGV("[%s] Registered graphic buffer with ID %u (pointer = %p)",
817             mComponentName.c_str(),
818             bufferId, graphicBuffer.get());
819    }
820
821    OMX_U32 cancelStart;
822    OMX_U32 cancelEnd;
823
824    if (err != 0) {
825        // If an error occurred while dequeuing we need to cancel any buffers
826        // that were dequeued.
827        cancelStart = 0;
828        cancelEnd = mBuffers[kPortIndexOutput].size();
829    } else {
830        // Return the required minimum undequeued buffers to the native window.
831        cancelStart = bufferCount - minUndequeuedBuffers;
832        cancelEnd = bufferCount;
833    }
834
835    for (OMX_U32 i = cancelStart; i < cancelEnd; i++) {
836        BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
837        status_t error = cancelBufferToNativeWindow(info);
838        if (err == 0) {
839            err = error;
840        }
841    }
842
843    return err;
844}
845
846status_t ACodec::allocateOutputMetaDataBuffers() {
847    OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers;
848    status_t err = configureOutputBuffersFromNativeWindow(
849            &bufferCount, &bufferSize, &minUndequeuedBuffers);
850    if (err != 0)
851        return err;
852    mNumUndequeuedBuffers = minUndequeuedBuffers;
853
854    ALOGV("[%s] Allocating %u meta buffers on output port",
855         mComponentName.c_str(), bufferCount);
856
857    size_t totalSize = bufferCount * 8;
858    mDealer[kPortIndexOutput] = new MemoryDealer(totalSize, "ACodec");
859
860    // Dequeue buffers and send them to OMX
861    for (OMX_U32 i = 0; i < bufferCount; i++) {
862        BufferInfo info;
863        info.mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
864        info.mGraphicBuffer = NULL;
865        info.mDequeuedAt = mDequeueCounter;
866
867        sp<IMemory> mem = mDealer[kPortIndexOutput]->allocate(
868                sizeof(struct VideoDecoderOutputMetaData));
869        CHECK(mem.get() != NULL);
870        info.mData = new ABuffer(mem->pointer(), mem->size());
871
872        // we use useBuffer for metadata regardless of quirks
873        err = mOMX->useBuffer(
874                mNode, kPortIndexOutput, mem, &info.mBufferID);
875
876        mBuffers[kPortIndexOutput].push(info);
877
878        ALOGV("[%s] allocated meta buffer with ID %u (pointer = %p)",
879             mComponentName.c_str(), info.mBufferID, mem->pointer());
880    }
881
882    mMetaDataBuffersToSubmit = bufferCount - minUndequeuedBuffers;
883    return err;
884}
885
886status_t ACodec::submitOutputMetaDataBuffer() {
887    CHECK(mStoreMetaDataInOutputBuffers);
888    if (mMetaDataBuffersToSubmit == 0)
889        return OK;
890
891    BufferInfo *info = dequeueBufferFromNativeWindow();
892    if (info == NULL)
893        return ERROR_IO;
894
895    ALOGV("[%s] submitting output meta buffer ID %u for graphic buffer %p",
896          mComponentName.c_str(), info->mBufferID, info->mGraphicBuffer.get());
897
898    --mMetaDataBuffersToSubmit;
899    CHECK_EQ(mOMX->fillBuffer(mNode, info->mBufferID),
900             (status_t)OK);
901
902    info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
903    return OK;
904}
905
906status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) {
907    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
908
909    ALOGV("[%s] Calling cancelBuffer on buffer %u",
910         mComponentName.c_str(), info->mBufferID);
911
912    int err = mNativeWindow->cancelBuffer(
913        mNativeWindow.get(), info->mGraphicBuffer.get(), -1);
914
915    ALOGW_IF(err != 0, "[%s] can not return buffer %u to native window",
916            mComponentName.c_str(), info->mBufferID);
917
918    info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
919
920    return err;
921}
922
923ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() {
924    ANativeWindowBuffer *buf;
925    CHECK(mNativeWindow.get() != NULL);
926
927    if (mTunneled) {
928        ALOGW("dequeueBufferFromNativeWindow() should not be called in tunnel"
929              " video playback mode mode!");
930        return NULL;
931    }
932
933    if (native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &buf) != 0) {
934        ALOGE("dequeueBuffer failed.");
935        return NULL;
936    }
937
938    BufferInfo *oldest = NULL;
939    for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
940        BufferInfo *info =
941            &mBuffers[kPortIndexOutput].editItemAt(i);
942
943        if (info->mGraphicBuffer != NULL &&
944            info->mGraphicBuffer->handle == buf->handle) {
945            CHECK_EQ((int)info->mStatus,
946                     (int)BufferInfo::OWNED_BY_NATIVE_WINDOW);
947
948            info->mStatus = BufferInfo::OWNED_BY_US;
949
950            return info;
951        }
952
953        if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW &&
954            (oldest == NULL ||
955             // avoid potential issues from counter rolling over
956             mDequeueCounter - info->mDequeuedAt >
957                    mDequeueCounter - oldest->mDequeuedAt)) {
958            oldest = info;
959        }
960    }
961
962    if (oldest) {
963        CHECK(mStoreMetaDataInOutputBuffers);
964
965        // discard buffer in LRU info and replace with new buffer
966        oldest->mGraphicBuffer = new GraphicBuffer(buf, false);
967        oldest->mStatus = BufferInfo::OWNED_BY_US;
968
969        mOMX->updateGraphicBufferInMeta(
970                mNode, kPortIndexOutput, oldest->mGraphicBuffer,
971                oldest->mBufferID);
972
973        VideoDecoderOutputMetaData *metaData =
974            reinterpret_cast<VideoDecoderOutputMetaData *>(
975                    oldest->mData->base());
976        CHECK_EQ(metaData->eType, kMetadataBufferTypeGrallocSource);
977
978        ALOGV("replaced oldest buffer #%u with age %u (%p/%p stored in %p)",
979                oldest - &mBuffers[kPortIndexOutput][0],
980                mDequeueCounter - oldest->mDequeuedAt,
981                metaData->pHandle,
982                oldest->mGraphicBuffer->handle, oldest->mData->base());
983
984        return oldest;
985    }
986
987    TRESPASS();
988
989    return NULL;
990}
991
992status_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) {
993    for (size_t i = mBuffers[portIndex].size(); i-- > 0;) {
994        CHECK_EQ((status_t)OK, freeBuffer(portIndex, i));
995    }
996
997    mDealer[portIndex].clear();
998
999    return OK;
1000}
1001
1002status_t ACodec::freeOutputBuffersNotOwnedByComponent() {
1003    for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
1004        BufferInfo *info =
1005            &mBuffers[kPortIndexOutput].editItemAt(i);
1006
1007        // At this time some buffers may still be with the component
1008        // or being drained.
1009        if (info->mStatus != BufferInfo::OWNED_BY_COMPONENT &&
1010            info->mStatus != BufferInfo::OWNED_BY_DOWNSTREAM) {
1011            CHECK_EQ((status_t)OK, freeBuffer(kPortIndexOutput, i));
1012        }
1013    }
1014
1015    return OK;
1016}
1017
1018status_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) {
1019    BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
1020
1021    CHECK(info->mStatus == BufferInfo::OWNED_BY_US
1022            || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
1023
1024    if (portIndex == kPortIndexOutput && mNativeWindow != NULL
1025            && info->mStatus == BufferInfo::OWNED_BY_US) {
1026        cancelBufferToNativeWindow(info);
1027    }
1028
1029    CHECK_EQ(mOMX->freeBuffer(
1030                mNode, portIndex, info->mBufferID),
1031             (status_t)OK);
1032
1033    mBuffers[portIndex].removeAt(i);
1034
1035    return OK;
1036}
1037
1038ACodec::BufferInfo *ACodec::findBufferByID(
1039        uint32_t portIndex, IOMX::buffer_id bufferID,
1040        ssize_t *index) {
1041    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
1042        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
1043
1044        if (info->mBufferID == bufferID) {
1045            if (index != NULL) {
1046                *index = i;
1047            }
1048            return info;
1049        }
1050    }
1051
1052    TRESPASS();
1053
1054    return NULL;
1055}
1056
1057status_t ACodec::setComponentRole(
1058        bool isEncoder, const char *mime) {
1059    struct MimeToRole {
1060        const char *mime;
1061        const char *decoderRole;
1062        const char *encoderRole;
1063    };
1064
1065    static const MimeToRole kMimeToRole[] = {
1066        { MEDIA_MIMETYPE_AUDIO_MPEG,
1067            "audio_decoder.mp3", "audio_encoder.mp3" },
1068        { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I,
1069            "audio_decoder.mp1", "audio_encoder.mp1" },
1070        { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II,
1071            "audio_decoder.mp2", "audio_encoder.mp2" },
1072        { MEDIA_MIMETYPE_AUDIO_AMR_NB,
1073            "audio_decoder.amrnb", "audio_encoder.amrnb" },
1074        { MEDIA_MIMETYPE_AUDIO_AMR_WB,
1075            "audio_decoder.amrwb", "audio_encoder.amrwb" },
1076        { MEDIA_MIMETYPE_AUDIO_AAC,
1077            "audio_decoder.aac", "audio_encoder.aac" },
1078        { MEDIA_MIMETYPE_AUDIO_VORBIS,
1079            "audio_decoder.vorbis", "audio_encoder.vorbis" },
1080        { MEDIA_MIMETYPE_AUDIO_OPUS,
1081            "audio_decoder.opus", "audio_encoder.opus" },
1082        { MEDIA_MIMETYPE_AUDIO_G711_MLAW,
1083            "audio_decoder.g711mlaw", "audio_encoder.g711mlaw" },
1084        { MEDIA_MIMETYPE_AUDIO_G711_ALAW,
1085            "audio_decoder.g711alaw", "audio_encoder.g711alaw" },
1086        { MEDIA_MIMETYPE_VIDEO_AVC,
1087            "video_decoder.avc", "video_encoder.avc" },
1088        { MEDIA_MIMETYPE_VIDEO_HEVC,
1089            "video_decoder.hevc", "video_encoder.hevc" },
1090        { MEDIA_MIMETYPE_VIDEO_MPEG4,
1091            "video_decoder.mpeg4", "video_encoder.mpeg4" },
1092        { MEDIA_MIMETYPE_VIDEO_H263,
1093            "video_decoder.h263", "video_encoder.h263" },
1094        { MEDIA_MIMETYPE_VIDEO_VP8,
1095            "video_decoder.vp8", "video_encoder.vp8" },
1096        { MEDIA_MIMETYPE_VIDEO_VP9,
1097            "video_decoder.vp9", "video_encoder.vp9" },
1098        { MEDIA_MIMETYPE_AUDIO_RAW,
1099            "audio_decoder.raw", "audio_encoder.raw" },
1100        { MEDIA_MIMETYPE_AUDIO_FLAC,
1101            "audio_decoder.flac", "audio_encoder.flac" },
1102        { MEDIA_MIMETYPE_AUDIO_MSGSM,
1103            "audio_decoder.gsm", "audio_encoder.gsm" },
1104        { MEDIA_MIMETYPE_VIDEO_MPEG2,
1105            "video_decoder.mpeg2", "video_encoder.mpeg2" },
1106        { MEDIA_MIMETYPE_AUDIO_AC3,
1107            "audio_decoder.ac3", "audio_encoder.ac3" },
1108        { MEDIA_MIMETYPE_AUDIO_EAC3,
1109            "audio_decoder.eac3", "audio_encoder.eac3" },
1110    };
1111
1112    static const size_t kNumMimeToRole =
1113        sizeof(kMimeToRole) / sizeof(kMimeToRole[0]);
1114
1115    size_t i;
1116    for (i = 0; i < kNumMimeToRole; ++i) {
1117        if (!strcasecmp(mime, kMimeToRole[i].mime)) {
1118            break;
1119        }
1120    }
1121
1122    if (i == kNumMimeToRole) {
1123        return ERROR_UNSUPPORTED;
1124    }
1125
1126    const char *role =
1127        isEncoder ? kMimeToRole[i].encoderRole
1128                  : kMimeToRole[i].decoderRole;
1129
1130    if (role != NULL) {
1131        OMX_PARAM_COMPONENTROLETYPE roleParams;
1132        InitOMXParams(&roleParams);
1133
1134        strncpy((char *)roleParams.cRole,
1135                role, OMX_MAX_STRINGNAME_SIZE - 1);
1136
1137        roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
1138
1139        status_t err = mOMX->setParameter(
1140                mNode, OMX_IndexParamStandardComponentRole,
1141                &roleParams, sizeof(roleParams));
1142
1143        if (err != OK) {
1144            ALOGW("[%s] Failed to set standard component role '%s'.",
1145                 mComponentName.c_str(), role);
1146
1147            return err;
1148        }
1149    }
1150
1151    return OK;
1152}
1153
1154status_t ACodec::configureCodec(
1155        const char *mime, const sp<AMessage> &msg) {
1156    int32_t encoder;
1157    if (!msg->findInt32("encoder", &encoder)) {
1158        encoder = false;
1159    }
1160
1161    sp<AMessage> inputFormat = new AMessage();
1162    sp<AMessage> outputFormat = mNotify->dup(); // will use this for kWhatOutputFormatChanged
1163
1164    mIsEncoder = encoder;
1165
1166    status_t err = setComponentRole(encoder /* isEncoder */, mime);
1167
1168    if (err != OK) {
1169        return err;
1170    }
1171
1172    int32_t bitRate = 0;
1173    // FLAC encoder doesn't need a bitrate, other encoders do
1174    if (encoder && strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)
1175            && !msg->findInt32("bitrate", &bitRate)) {
1176        return INVALID_OPERATION;
1177    }
1178
1179    int32_t storeMeta;
1180    if (encoder
1181            && msg->findInt32("store-metadata-in-buffers", &storeMeta)
1182            && storeMeta != 0) {
1183        err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexInput, OMX_TRUE);
1184
1185        if (err != OK) {
1186              ALOGE("[%s] storeMetaDataInBuffers (input) failed w/ err %d",
1187                    mComponentName.c_str(), err);
1188
1189              return err;
1190          }
1191      }
1192
1193    int32_t prependSPSPPS = 0;
1194    if (encoder
1195            && msg->findInt32("prepend-sps-pps-to-idr-frames", &prependSPSPPS)
1196            && prependSPSPPS != 0) {
1197        OMX_INDEXTYPE index;
1198        err = mOMX->getExtensionIndex(
1199                mNode,
1200                "OMX.google.android.index.prependSPSPPSToIDRFrames",
1201                &index);
1202
1203        if (err == OK) {
1204            PrependSPSPPSToIDRFramesParams params;
1205            InitOMXParams(&params);
1206            params.bEnable = OMX_TRUE;
1207
1208            err = mOMX->setParameter(
1209                    mNode, index, &params, sizeof(params));
1210        }
1211
1212        if (err != OK) {
1213            ALOGE("Encoder could not be configured to emit SPS/PPS before "
1214                  "IDR frames. (err %d)", err);
1215
1216            return err;
1217        }
1218    }
1219
1220    // Only enable metadata mode on encoder output if encoder can prepend
1221    // sps/pps to idr frames, since in metadata mode the bitstream is in an
1222    // opaque handle, to which we don't have access.
1223    int32_t video = !strncasecmp(mime, "video/", 6);
1224    if (encoder && video) {
1225        OMX_BOOL enable = (OMX_BOOL) (prependSPSPPS
1226            && msg->findInt32("store-metadata-in-buffers-output", &storeMeta)
1227            && storeMeta != 0);
1228
1229        err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexOutput, enable);
1230
1231        if (err != OK) {
1232            ALOGE("[%s] storeMetaDataInBuffers (output) failed w/ err %d",
1233                mComponentName.c_str(), err);
1234            mUseMetadataOnEncoderOutput = 0;
1235        } else {
1236            mUseMetadataOnEncoderOutput = enable;
1237        }
1238
1239        if (!msg->findInt64(
1240                    "repeat-previous-frame-after",
1241                    &mRepeatFrameDelayUs)) {
1242            mRepeatFrameDelayUs = -1ll;
1243        }
1244
1245        if (!msg->findInt64("max-pts-gap-to-encoder", &mMaxPtsGapUs)) {
1246            mMaxPtsGapUs = -1ll;
1247        }
1248
1249        if (!msg->findInt64("time-lapse", &mTimePerCaptureUs)) {
1250            mTimePerCaptureUs = -1ll;
1251        }
1252
1253        if (!msg->findInt32(
1254                    "create-input-buffers-suspended",
1255                    (int32_t*)&mCreateInputBuffersSuspended)) {
1256            mCreateInputBuffersSuspended = false;
1257        }
1258    }
1259
1260    sp<RefBase> obj;
1261    int32_t haveNativeWindow = msg->findObject("native-window", &obj) &&
1262        obj != NULL;
1263    mStoreMetaDataInOutputBuffers = false;
1264    if (video && !encoder) {
1265        inputFormat->setInt32("adaptive-playback", false);
1266
1267        int32_t usageProtected;
1268        if (msg->findInt32("protected", &usageProtected) && usageProtected) {
1269            if (!haveNativeWindow) {
1270                ALOGE("protected output buffers must be sent to an ANativeWindow");
1271                return PERMISSION_DENIED;
1272            }
1273            mFlags |= kFlagIsGrallocUsageProtected;
1274            mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
1275        }
1276    }
1277    if (!encoder && video && haveNativeWindow) {
1278        sp<NativeWindowWrapper> windowWrapper(
1279                static_cast<NativeWindowWrapper *>(obj.get()));
1280        sp<ANativeWindow> nativeWindow = windowWrapper->getNativeWindow();
1281
1282        // START of temporary support for automatic FRC - THIS WILL BE REMOVED
1283        int32_t autoFrc;
1284        if (msg->findInt32("auto-frc", &autoFrc)) {
1285            bool enabled = autoFrc;
1286            OMX_CONFIG_BOOLEANTYPE config;
1287            InitOMXParams(&config);
1288            config.bEnabled = (OMX_BOOL)enabled;
1289            status_t temp = mOMX->setConfig(
1290                    mNode, (OMX_INDEXTYPE)OMX_IndexConfigAutoFramerateConversion,
1291                    &config, sizeof(config));
1292            if (temp == OK) {
1293                outputFormat->setInt32("auto-frc", enabled);
1294            } else if (enabled) {
1295                ALOGI("codec does not support requested auto-frc (err %d)", temp);
1296            }
1297        }
1298        // END of temporary support for automatic FRC
1299
1300        int32_t tunneled;
1301        if (msg->findInt32("feature-tunneled-playback", &tunneled) &&
1302            tunneled != 0) {
1303            ALOGI("Configuring TUNNELED video playback.");
1304            mTunneled = true;
1305
1306            int32_t audioHwSync = 0;
1307            if (!msg->findInt32("audio-hw-sync", &audioHwSync)) {
1308                ALOGW("No Audio HW Sync provided for video tunnel");
1309            }
1310            err = configureTunneledVideoPlayback(audioHwSync, nativeWindow);
1311            if (err != OK) {
1312                ALOGE("configureTunneledVideoPlayback(%d,%p) failed!",
1313                        audioHwSync, nativeWindow.get());
1314                return err;
1315            }
1316
1317            int32_t maxWidth = 0, maxHeight = 0;
1318            if (msg->findInt32("max-width", &maxWidth) &&
1319                    msg->findInt32("max-height", &maxHeight)) {
1320
1321                err = mOMX->prepareForAdaptivePlayback(
1322                        mNode, kPortIndexOutput, OMX_TRUE, maxWidth, maxHeight);
1323                if (err != OK) {
1324                    ALOGW("[%s] prepareForAdaptivePlayback failed w/ err %d",
1325                            mComponentName.c_str(), err);
1326                } else {
1327                    inputFormat->setInt32("max-width", maxWidth);
1328                    inputFormat->setInt32("max-height", maxHeight);
1329                    inputFormat->setInt32("adaptive-playback", true);
1330                }
1331            }
1332        } else {
1333            ALOGV("Configuring CPU controlled video playback.");
1334            mTunneled = false;
1335
1336            // Explicity reset the sideband handle of the window for
1337            // non-tunneled video in case the window was previously used
1338            // for a tunneled video playback.
1339            err = native_window_set_sideband_stream(nativeWindow.get(), NULL);
1340            if (err != OK) {
1341                ALOGE("set_sideband_stream(NULL) failed! (err %d).", err);
1342                return err;
1343            }
1344
1345            // Always try to enable dynamic output buffers on native surface
1346            err = mOMX->storeMetaDataInBuffers(
1347                    mNode, kPortIndexOutput, OMX_TRUE);
1348            if (err != OK) {
1349                ALOGE("[%s] storeMetaDataInBuffers failed w/ err %d",
1350                        mComponentName.c_str(), err);
1351
1352                // if adaptive playback has been requested, try JB fallback
1353                // NOTE: THIS FALLBACK MECHANISM WILL BE REMOVED DUE TO ITS
1354                // LARGE MEMORY REQUIREMENT
1355
1356                // we will not do adaptive playback on software accessed
1357                // surfaces as they never had to respond to changes in the
1358                // crop window, and we don't trust that they will be able to.
1359                int usageBits = 0;
1360                bool canDoAdaptivePlayback;
1361
1362                if (nativeWindow->query(
1363                        nativeWindow.get(),
1364                        NATIVE_WINDOW_CONSUMER_USAGE_BITS,
1365                        &usageBits) != OK) {
1366                    canDoAdaptivePlayback = false;
1367                } else {
1368                    canDoAdaptivePlayback =
1369                        (usageBits &
1370                                (GRALLOC_USAGE_SW_READ_MASK |
1371                                 GRALLOC_USAGE_SW_WRITE_MASK)) == 0;
1372                }
1373
1374                int32_t maxWidth = 0, maxHeight = 0;
1375                if (canDoAdaptivePlayback &&
1376                        msg->findInt32("max-width", &maxWidth) &&
1377                        msg->findInt32("max-height", &maxHeight)) {
1378                    ALOGV("[%s] prepareForAdaptivePlayback(%dx%d)",
1379                            mComponentName.c_str(), maxWidth, maxHeight);
1380
1381                    err = mOMX->prepareForAdaptivePlayback(
1382                            mNode, kPortIndexOutput, OMX_TRUE, maxWidth,
1383                            maxHeight);
1384                    ALOGW_IF(err != OK,
1385                            "[%s] prepareForAdaptivePlayback failed w/ err %d",
1386                            mComponentName.c_str(), err);
1387
1388                    if (err == OK) {
1389                        inputFormat->setInt32("max-width", maxWidth);
1390                        inputFormat->setInt32("max-height", maxHeight);
1391                        inputFormat->setInt32("adaptive-playback", true);
1392                    }
1393                }
1394                // allow failure
1395                err = OK;
1396            } else {
1397                ALOGV("[%s] storeMetaDataInBuffers succeeded",
1398                        mComponentName.c_str());
1399                mStoreMetaDataInOutputBuffers = true;
1400                inputFormat->setInt32("adaptive-playback", true);
1401            }
1402
1403            int32_t push;
1404            if (msg->findInt32("push-blank-buffers-on-shutdown", &push)
1405                    && push != 0) {
1406                mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
1407            }
1408        }
1409
1410        int32_t rotationDegrees;
1411        if (msg->findInt32("rotation-degrees", &rotationDegrees)) {
1412            mRotationDegrees = rotationDegrees;
1413        } else {
1414            mRotationDegrees = 0;
1415        }
1416    }
1417
1418    if (video) {
1419        if (encoder) {
1420            err = setupVideoEncoder(mime, msg);
1421        } else {
1422            err = setupVideoDecoder(mime, msg);
1423        }
1424    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
1425        int32_t numChannels, sampleRate;
1426        if (!msg->findInt32("channel-count", &numChannels)
1427                || !msg->findInt32("sample-rate", &sampleRate)) {
1428            // Since we did not always check for these, leave them optional
1429            // and have the decoder figure it all out.
1430            err = OK;
1431        } else {
1432            err = setupRawAudioFormat(
1433                    encoder ? kPortIndexInput : kPortIndexOutput,
1434                    sampleRate,
1435                    numChannels);
1436        }
1437    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
1438        int32_t numChannels, sampleRate;
1439        if (!msg->findInt32("channel-count", &numChannels)
1440                || !msg->findInt32("sample-rate", &sampleRate)) {
1441            err = INVALID_OPERATION;
1442        } else {
1443            int32_t isADTS, aacProfile;
1444            int32_t sbrMode;
1445            int32_t maxOutputChannelCount;
1446            int32_t pcmLimiterEnable;
1447            drcParams_t drc;
1448            if (!msg->findInt32("is-adts", &isADTS)) {
1449                isADTS = 0;
1450            }
1451            if (!msg->findInt32("aac-profile", &aacProfile)) {
1452                aacProfile = OMX_AUDIO_AACObjectNull;
1453            }
1454            if (!msg->findInt32("aac-sbr-mode", &sbrMode)) {
1455                sbrMode = -1;
1456            }
1457
1458            if (!msg->findInt32("aac-max-output-channel_count", &maxOutputChannelCount)) {
1459                maxOutputChannelCount = -1;
1460            }
1461            if (!msg->findInt32("aac-pcm-limiter-enable", &pcmLimiterEnable)) {
1462                // value is unknown
1463                pcmLimiterEnable = -1;
1464            }
1465            if (!msg->findInt32("aac-encoded-target-level", &drc.encodedTargetLevel)) {
1466                // value is unknown
1467                drc.encodedTargetLevel = -1;
1468            }
1469            if (!msg->findInt32("aac-drc-cut-level", &drc.drcCut)) {
1470                // value is unknown
1471                drc.drcCut = -1;
1472            }
1473            if (!msg->findInt32("aac-drc-boost-level", &drc.drcBoost)) {
1474                // value is unknown
1475                drc.drcBoost = -1;
1476            }
1477            if (!msg->findInt32("aac-drc-heavy-compression", &drc.heavyCompression)) {
1478                // value is unknown
1479                drc.heavyCompression = -1;
1480            }
1481            if (!msg->findInt32("aac-target-ref-level", &drc.targetRefLevel)) {
1482                // value is unknown
1483                drc.targetRefLevel = -1;
1484            }
1485
1486            err = setupAACCodec(
1487                    encoder, numChannels, sampleRate, bitRate, aacProfile,
1488                    isADTS != 0, sbrMode, maxOutputChannelCount, drc,
1489                    pcmLimiterEnable);
1490        }
1491    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) {
1492        err = setupAMRCodec(encoder, false /* isWAMR */, bitRate);
1493    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
1494        err = setupAMRCodec(encoder, true /* isWAMR */, bitRate);
1495    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW)
1496            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) {
1497        // These are PCM-like formats with a fixed sample rate but
1498        // a variable number of channels.
1499
1500        int32_t numChannels;
1501        if (!msg->findInt32("channel-count", &numChannels)) {
1502            err = INVALID_OPERATION;
1503        } else {
1504            err = setupG711Codec(encoder, numChannels);
1505        }
1506    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)) {
1507        int32_t numChannels, sampleRate, compressionLevel = -1;
1508        if (encoder &&
1509                (!msg->findInt32("channel-count", &numChannels)
1510                        || !msg->findInt32("sample-rate", &sampleRate))) {
1511            ALOGE("missing channel count or sample rate for FLAC encoder");
1512            err = INVALID_OPERATION;
1513        } else {
1514            if (encoder) {
1515                if (!msg->findInt32(
1516                            "complexity", &compressionLevel) &&
1517                    !msg->findInt32(
1518                            "flac-compression-level", &compressionLevel)) {
1519                    compressionLevel = 5; // default FLAC compression level
1520                } else if (compressionLevel < 0) {
1521                    ALOGW("compression level %d outside [0..8] range, "
1522                          "using 0",
1523                          compressionLevel);
1524                    compressionLevel = 0;
1525                } else if (compressionLevel > 8) {
1526                    ALOGW("compression level %d outside [0..8] range, "
1527                          "using 8",
1528                          compressionLevel);
1529                    compressionLevel = 8;
1530                }
1531            }
1532            err = setupFlacCodec(
1533                    encoder, numChannels, sampleRate, compressionLevel);
1534        }
1535    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
1536        int32_t numChannels, sampleRate;
1537        if (encoder
1538                || !msg->findInt32("channel-count", &numChannels)
1539                || !msg->findInt32("sample-rate", &sampleRate)) {
1540            err = INVALID_OPERATION;
1541        } else {
1542            err = setupRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
1543        }
1544    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AC3)) {
1545        int32_t numChannels;
1546        int32_t sampleRate;
1547        if (!msg->findInt32("channel-count", &numChannels)
1548                || !msg->findInt32("sample-rate", &sampleRate)) {
1549            err = INVALID_OPERATION;
1550        } else {
1551            err = setupAC3Codec(encoder, numChannels, sampleRate);
1552        }
1553    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_EAC3)) {
1554        int32_t numChannels;
1555        int32_t sampleRate;
1556        if (!msg->findInt32("channel-count", &numChannels)
1557                || !msg->findInt32("sample-rate", &sampleRate)) {
1558            err = INVALID_OPERATION;
1559        } else {
1560            err = setupEAC3Codec(encoder, numChannels, sampleRate);
1561        }
1562    }
1563
1564    if (err != OK) {
1565        return err;
1566    }
1567
1568    if (!msg->findInt32("encoder-delay", &mEncoderDelay)) {
1569        mEncoderDelay = 0;
1570    }
1571
1572    if (!msg->findInt32("encoder-padding", &mEncoderPadding)) {
1573        mEncoderPadding = 0;
1574    }
1575
1576    if (msg->findInt32("channel-mask", &mChannelMask)) {
1577        mChannelMaskPresent = true;
1578    } else {
1579        mChannelMaskPresent = false;
1580    }
1581
1582    int32_t maxInputSize;
1583    if (msg->findInt32("max-input-size", &maxInputSize)) {
1584        err = setMinBufferSize(kPortIndexInput, (size_t)maxInputSize);
1585    } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) {
1586        err = setMinBufferSize(kPortIndexInput, 8192);  // XXX
1587    }
1588
1589    mBaseOutputFormat = outputFormat;
1590
1591    CHECK_EQ(getPortFormat(kPortIndexInput, inputFormat), (status_t)OK);
1592    CHECK_EQ(getPortFormat(kPortIndexOutput, outputFormat), (status_t)OK);
1593    mInputFormat = inputFormat;
1594    mOutputFormat = outputFormat;
1595
1596    return err;
1597}
1598
1599status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) {
1600    OMX_PARAM_PORTDEFINITIONTYPE def;
1601    InitOMXParams(&def);
1602    def.nPortIndex = portIndex;
1603
1604    status_t err = mOMX->getParameter(
1605            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1606
1607    if (err != OK) {
1608        return err;
1609    }
1610
1611    if (def.nBufferSize >= size) {
1612        return OK;
1613    }
1614
1615    def.nBufferSize = size;
1616
1617    err = mOMX->setParameter(
1618            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1619
1620    if (err != OK) {
1621        return err;
1622    }
1623
1624    err = mOMX->getParameter(
1625            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1626
1627    if (err != OK) {
1628        return err;
1629    }
1630
1631    CHECK(def.nBufferSize >= size);
1632
1633    return OK;
1634}
1635
1636status_t ACodec::selectAudioPortFormat(
1637        OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat) {
1638    OMX_AUDIO_PARAM_PORTFORMATTYPE format;
1639    InitOMXParams(&format);
1640
1641    format.nPortIndex = portIndex;
1642    for (OMX_U32 index = 0;; ++index) {
1643        format.nIndex = index;
1644
1645        status_t err = mOMX->getParameter(
1646                mNode, OMX_IndexParamAudioPortFormat,
1647                &format, sizeof(format));
1648
1649        if (err != OK) {
1650            return err;
1651        }
1652
1653        if (format.eEncoding == desiredFormat) {
1654            break;
1655        }
1656    }
1657
1658    return mOMX->setParameter(
1659            mNode, OMX_IndexParamAudioPortFormat, &format, sizeof(format));
1660}
1661
1662status_t ACodec::setupAACCodec(
1663        bool encoder, int32_t numChannels, int32_t sampleRate,
1664        int32_t bitRate, int32_t aacProfile, bool isADTS, int32_t sbrMode,
1665        int32_t maxOutputChannelCount, const drcParams_t& drc,
1666        int32_t pcmLimiterEnable) {
1667    if (encoder && isADTS) {
1668        return -EINVAL;
1669    }
1670
1671    status_t err = setupRawAudioFormat(
1672            encoder ? kPortIndexInput : kPortIndexOutput,
1673            sampleRate,
1674            numChannels);
1675
1676    if (err != OK) {
1677        return err;
1678    }
1679
1680    if (encoder) {
1681        err = selectAudioPortFormat(kPortIndexOutput, OMX_AUDIO_CodingAAC);
1682
1683        if (err != OK) {
1684            return err;
1685        }
1686
1687        OMX_PARAM_PORTDEFINITIONTYPE def;
1688        InitOMXParams(&def);
1689        def.nPortIndex = kPortIndexOutput;
1690
1691        err = mOMX->getParameter(
1692                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1693
1694        if (err != OK) {
1695            return err;
1696        }
1697
1698        def.format.audio.bFlagErrorConcealment = OMX_TRUE;
1699        def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
1700
1701        err = mOMX->setParameter(
1702                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1703
1704        if (err != OK) {
1705            return err;
1706        }
1707
1708        OMX_AUDIO_PARAM_AACPROFILETYPE profile;
1709        InitOMXParams(&profile);
1710        profile.nPortIndex = kPortIndexOutput;
1711
1712        err = mOMX->getParameter(
1713                mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1714
1715        if (err != OK) {
1716            return err;
1717        }
1718
1719        profile.nChannels = numChannels;
1720
1721        profile.eChannelMode =
1722            (numChannels == 1)
1723                ? OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo;
1724
1725        profile.nSampleRate = sampleRate;
1726        profile.nBitRate = bitRate;
1727        profile.nAudioBandWidth = 0;
1728        profile.nFrameLength = 0;
1729        profile.nAACtools = OMX_AUDIO_AACToolAll;
1730        profile.nAACERtools = OMX_AUDIO_AACERNone;
1731        profile.eAACProfile = (OMX_AUDIO_AACPROFILETYPE) aacProfile;
1732        profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
1733        switch (sbrMode) {
1734        case 0:
1735            // disable sbr
1736            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR;
1737            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR;
1738            break;
1739        case 1:
1740            // enable single-rate sbr
1741            profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR;
1742            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR;
1743            break;
1744        case 2:
1745            // enable dual-rate sbr
1746            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR;
1747            profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR;
1748            break;
1749        case -1:
1750            // enable both modes -> the codec will decide which mode should be used
1751            profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR;
1752            profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR;
1753            break;
1754        default:
1755            // unsupported sbr mode
1756            return BAD_VALUE;
1757        }
1758
1759
1760        err = mOMX->setParameter(
1761                mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1762
1763        if (err != OK) {
1764            return err;
1765        }
1766
1767        return err;
1768    }
1769
1770    OMX_AUDIO_PARAM_AACPROFILETYPE profile;
1771    InitOMXParams(&profile);
1772    profile.nPortIndex = kPortIndexInput;
1773
1774    err = mOMX->getParameter(
1775            mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1776
1777    if (err != OK) {
1778        return err;
1779    }
1780
1781    profile.nChannels = numChannels;
1782    profile.nSampleRate = sampleRate;
1783
1784    profile.eAACStreamFormat =
1785        isADTS
1786            ? OMX_AUDIO_AACStreamFormatMP4ADTS
1787            : OMX_AUDIO_AACStreamFormatMP4FF;
1788
1789    OMX_AUDIO_PARAM_ANDROID_AACPRESENTATIONTYPE presentation;
1790    presentation.nMaxOutputChannels = maxOutputChannelCount;
1791    presentation.nDrcCut = drc.drcCut;
1792    presentation.nDrcBoost = drc.drcBoost;
1793    presentation.nHeavyCompression = drc.heavyCompression;
1794    presentation.nTargetReferenceLevel = drc.targetRefLevel;
1795    presentation.nEncodedTargetLevel = drc.encodedTargetLevel;
1796    presentation.nPCMLimiterEnable = pcmLimiterEnable;
1797
1798    status_t res = mOMX->setParameter(mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1799    if (res == OK) {
1800        // optional parameters, will not cause configuration failure
1801        mOMX->setParameter(mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAacPresentation,
1802                &presentation, sizeof(presentation));
1803    } else {
1804        ALOGW("did not set AudioAndroidAacPresentation due to error %d when setting AudioAac", res);
1805    }
1806    return res;
1807}
1808
1809status_t ACodec::setupAC3Codec(
1810        bool encoder, int32_t numChannels, int32_t sampleRate) {
1811    status_t err = setupRawAudioFormat(
1812            encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels);
1813
1814    if (err != OK) {
1815        return err;
1816    }
1817
1818    if (encoder) {
1819        ALOGW("AC3 encoding is not supported.");
1820        return INVALID_OPERATION;
1821    }
1822
1823    OMX_AUDIO_PARAM_ANDROID_AC3TYPE def;
1824    InitOMXParams(&def);
1825    def.nPortIndex = kPortIndexInput;
1826
1827    err = mOMX->getParameter(
1828            mNode,
1829            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
1830            &def,
1831            sizeof(def));
1832
1833    if (err != OK) {
1834        return err;
1835    }
1836
1837    def.nChannels = numChannels;
1838    def.nSampleRate = sampleRate;
1839
1840    return mOMX->setParameter(
1841            mNode,
1842            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
1843            &def,
1844            sizeof(def));
1845}
1846
1847status_t ACodec::setupEAC3Codec(
1848        bool encoder, int32_t numChannels, int32_t sampleRate) {
1849    status_t err = setupRawAudioFormat(
1850            encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels);
1851
1852    if (err != OK) {
1853        return err;
1854    }
1855
1856    if (encoder) {
1857        ALOGW("EAC3 encoding is not supported.");
1858        return INVALID_OPERATION;
1859    }
1860
1861    OMX_AUDIO_PARAM_ANDROID_EAC3TYPE def;
1862    InitOMXParams(&def);
1863    def.nPortIndex = kPortIndexInput;
1864
1865    err = mOMX->getParameter(
1866            mNode,
1867            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
1868            &def,
1869            sizeof(def));
1870
1871    if (err != OK) {
1872        return err;
1873    }
1874
1875    def.nChannels = numChannels;
1876    def.nSampleRate = sampleRate;
1877
1878    return mOMX->setParameter(
1879            mNode,
1880            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
1881            &def,
1882            sizeof(def));
1883}
1884
1885static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate(
1886        bool isAMRWB, int32_t bps) {
1887    if (isAMRWB) {
1888        if (bps <= 6600) {
1889            return OMX_AUDIO_AMRBandModeWB0;
1890        } else if (bps <= 8850) {
1891            return OMX_AUDIO_AMRBandModeWB1;
1892        } else if (bps <= 12650) {
1893            return OMX_AUDIO_AMRBandModeWB2;
1894        } else if (bps <= 14250) {
1895            return OMX_AUDIO_AMRBandModeWB3;
1896        } else if (bps <= 15850) {
1897            return OMX_AUDIO_AMRBandModeWB4;
1898        } else if (bps <= 18250) {
1899            return OMX_AUDIO_AMRBandModeWB5;
1900        } else if (bps <= 19850) {
1901            return OMX_AUDIO_AMRBandModeWB6;
1902        } else if (bps <= 23050) {
1903            return OMX_AUDIO_AMRBandModeWB7;
1904        }
1905
1906        // 23850 bps
1907        return OMX_AUDIO_AMRBandModeWB8;
1908    } else {  // AMRNB
1909        if (bps <= 4750) {
1910            return OMX_AUDIO_AMRBandModeNB0;
1911        } else if (bps <= 5150) {
1912            return OMX_AUDIO_AMRBandModeNB1;
1913        } else if (bps <= 5900) {
1914            return OMX_AUDIO_AMRBandModeNB2;
1915        } else if (bps <= 6700) {
1916            return OMX_AUDIO_AMRBandModeNB3;
1917        } else if (bps <= 7400) {
1918            return OMX_AUDIO_AMRBandModeNB4;
1919        } else if (bps <= 7950) {
1920            return OMX_AUDIO_AMRBandModeNB5;
1921        } else if (bps <= 10200) {
1922            return OMX_AUDIO_AMRBandModeNB6;
1923        }
1924
1925        // 12200 bps
1926        return OMX_AUDIO_AMRBandModeNB7;
1927    }
1928}
1929
1930status_t ACodec::setupAMRCodec(bool encoder, bool isWAMR, int32_t bitrate) {
1931    OMX_AUDIO_PARAM_AMRTYPE def;
1932    InitOMXParams(&def);
1933    def.nPortIndex = encoder ? kPortIndexOutput : kPortIndexInput;
1934
1935    status_t err =
1936        mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
1937
1938    if (err != OK) {
1939        return err;
1940    }
1941
1942    def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
1943    def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitrate);
1944
1945    err = mOMX->setParameter(
1946            mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
1947
1948    if (err != OK) {
1949        return err;
1950    }
1951
1952    return setupRawAudioFormat(
1953            encoder ? kPortIndexInput : kPortIndexOutput,
1954            isWAMR ? 16000 : 8000 /* sampleRate */,
1955            1 /* numChannels */);
1956}
1957
1958status_t ACodec::setupG711Codec(bool encoder, int32_t numChannels) {
1959    CHECK(!encoder);  // XXX TODO
1960
1961    return setupRawAudioFormat(
1962            kPortIndexInput, 8000 /* sampleRate */, numChannels);
1963}
1964
1965status_t ACodec::setupFlacCodec(
1966        bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel) {
1967
1968    if (encoder) {
1969        OMX_AUDIO_PARAM_FLACTYPE def;
1970        InitOMXParams(&def);
1971        def.nPortIndex = kPortIndexOutput;
1972
1973        // configure compression level
1974        status_t err = mOMX->getParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def));
1975        if (err != OK) {
1976            ALOGE("setupFlacCodec(): Error %d getting OMX_IndexParamAudioFlac parameter", err);
1977            return err;
1978        }
1979        def.nCompressionLevel = compressionLevel;
1980        err = mOMX->setParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def));
1981        if (err != OK) {
1982            ALOGE("setupFlacCodec(): Error %d setting OMX_IndexParamAudioFlac parameter", err);
1983            return err;
1984        }
1985    }
1986
1987    return setupRawAudioFormat(
1988            encoder ? kPortIndexInput : kPortIndexOutput,
1989            sampleRate,
1990            numChannels);
1991}
1992
1993status_t ACodec::setupRawAudioFormat(
1994        OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) {
1995    OMX_PARAM_PORTDEFINITIONTYPE def;
1996    InitOMXParams(&def);
1997    def.nPortIndex = portIndex;
1998
1999    status_t err = mOMX->getParameter(
2000            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2001
2002    if (err != OK) {
2003        return err;
2004    }
2005
2006    def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
2007
2008    err = mOMX->setParameter(
2009            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2010
2011    if (err != OK) {
2012        return err;
2013    }
2014
2015    OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
2016    InitOMXParams(&pcmParams);
2017    pcmParams.nPortIndex = portIndex;
2018
2019    err = mOMX->getParameter(
2020            mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
2021
2022    if (err != OK) {
2023        return err;
2024    }
2025
2026    pcmParams.nChannels = numChannels;
2027    pcmParams.eNumData = OMX_NumericalDataSigned;
2028    pcmParams.bInterleaved = OMX_TRUE;
2029    pcmParams.nBitPerSample = 16;
2030    pcmParams.nSamplingRate = sampleRate;
2031    pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
2032
2033    if (getOMXChannelMapping(numChannels, pcmParams.eChannelMapping) != OK) {
2034        return OMX_ErrorNone;
2035    }
2036
2037    return mOMX->setParameter(
2038            mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
2039}
2040
2041status_t ACodec::configureTunneledVideoPlayback(
2042        int32_t audioHwSync, const sp<ANativeWindow> &nativeWindow) {
2043    native_handle_t* sidebandHandle;
2044
2045    status_t err = mOMX->configureVideoTunnelMode(
2046            mNode, kPortIndexOutput, OMX_TRUE, audioHwSync, &sidebandHandle);
2047    if (err != OK) {
2048        ALOGE("configureVideoTunnelMode failed! (err %d).", err);
2049        return err;
2050    }
2051
2052    err = native_window_set_sideband_stream(nativeWindow.get(), sidebandHandle);
2053    if (err != OK) {
2054        ALOGE("native_window_set_sideband_stream(%p) failed! (err %d).",
2055                sidebandHandle, err);
2056        return err;
2057    }
2058
2059    return OK;
2060}
2061
2062status_t ACodec::setVideoPortFormatType(
2063        OMX_U32 portIndex,
2064        OMX_VIDEO_CODINGTYPE compressionFormat,
2065        OMX_COLOR_FORMATTYPE colorFormat) {
2066    OMX_VIDEO_PARAM_PORTFORMATTYPE format;
2067    InitOMXParams(&format);
2068    format.nPortIndex = portIndex;
2069    format.nIndex = 0;
2070    bool found = false;
2071
2072    OMX_U32 index = 0;
2073    for (;;) {
2074        format.nIndex = index;
2075        status_t err = mOMX->getParameter(
2076                mNode, OMX_IndexParamVideoPortFormat,
2077                &format, sizeof(format));
2078
2079        if (err != OK) {
2080            return err;
2081        }
2082
2083        // substitute back flexible color format to codec supported format
2084        OMX_U32 flexibleEquivalent;
2085        if (compressionFormat == OMX_VIDEO_CodingUnused &&
2086                isFlexibleColorFormat(
2087                        mOMX, mNode, format.eColorFormat, &flexibleEquivalent) &&
2088                colorFormat == flexibleEquivalent) {
2089            ALOGI("[%s] using color format %#x in place of %#x",
2090                    mComponentName.c_str(), format.eColorFormat, colorFormat);
2091            colorFormat = format.eColorFormat;
2092        }
2093
2094        // The following assertion is violated by TI's video decoder.
2095        // CHECK_EQ(format.nIndex, index);
2096
2097        if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) {
2098            if (portIndex == kPortIndexInput
2099                    && colorFormat == format.eColorFormat) {
2100                // eCompressionFormat does not seem right.
2101                found = true;
2102                break;
2103            }
2104            if (portIndex == kPortIndexOutput
2105                    && compressionFormat == format.eCompressionFormat) {
2106                // eColorFormat does not seem right.
2107                found = true;
2108                break;
2109            }
2110        }
2111
2112        if (format.eCompressionFormat == compressionFormat
2113            && format.eColorFormat == colorFormat) {
2114            found = true;
2115            break;
2116        }
2117
2118        ++index;
2119    }
2120
2121    if (!found) {
2122        return UNKNOWN_ERROR;
2123    }
2124
2125    status_t err = mOMX->setParameter(
2126            mNode, OMX_IndexParamVideoPortFormat,
2127            &format, sizeof(format));
2128
2129    return err;
2130}
2131
2132status_t ACodec::setSupportedOutputFormat() {
2133    OMX_VIDEO_PARAM_PORTFORMATTYPE format;
2134    InitOMXParams(&format);
2135    format.nPortIndex = kPortIndexOutput;
2136    format.nIndex = 0;
2137
2138    status_t err = mOMX->getParameter(
2139            mNode, OMX_IndexParamVideoPortFormat,
2140            &format, sizeof(format));
2141    CHECK_EQ(err, (status_t)OK);
2142    CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused);
2143
2144    return mOMX->setParameter(
2145            mNode, OMX_IndexParamVideoPortFormat,
2146            &format, sizeof(format));
2147}
2148
2149static const struct VideoCodingMapEntry {
2150    const char *mMime;
2151    OMX_VIDEO_CODINGTYPE mVideoCodingType;
2152} kVideoCodingMapEntry[] = {
2153    { MEDIA_MIMETYPE_VIDEO_AVC, OMX_VIDEO_CodingAVC },
2154    { MEDIA_MIMETYPE_VIDEO_HEVC, OMX_VIDEO_CodingHEVC },
2155    { MEDIA_MIMETYPE_VIDEO_MPEG4, OMX_VIDEO_CodingMPEG4 },
2156    { MEDIA_MIMETYPE_VIDEO_H263, OMX_VIDEO_CodingH263 },
2157    { MEDIA_MIMETYPE_VIDEO_MPEG2, OMX_VIDEO_CodingMPEG2 },
2158    { MEDIA_MIMETYPE_VIDEO_VP8, OMX_VIDEO_CodingVP8 },
2159    { MEDIA_MIMETYPE_VIDEO_VP9, OMX_VIDEO_CodingVP9 },
2160};
2161
2162static status_t GetVideoCodingTypeFromMime(
2163        const char *mime, OMX_VIDEO_CODINGTYPE *codingType) {
2164    for (size_t i = 0;
2165         i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]);
2166         ++i) {
2167        if (!strcasecmp(mime, kVideoCodingMapEntry[i].mMime)) {
2168            *codingType = kVideoCodingMapEntry[i].mVideoCodingType;
2169            return OK;
2170        }
2171    }
2172
2173    *codingType = OMX_VIDEO_CodingUnused;
2174
2175    return ERROR_UNSUPPORTED;
2176}
2177
2178static status_t GetMimeTypeForVideoCoding(
2179        OMX_VIDEO_CODINGTYPE codingType, AString *mime) {
2180    for (size_t i = 0;
2181         i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]);
2182         ++i) {
2183        if (codingType == kVideoCodingMapEntry[i].mVideoCodingType) {
2184            *mime = kVideoCodingMapEntry[i].mMime;
2185            return OK;
2186        }
2187    }
2188
2189    mime->clear();
2190
2191    return ERROR_UNSUPPORTED;
2192}
2193
2194status_t ACodec::setupVideoDecoder(
2195        const char *mime, const sp<AMessage> &msg) {
2196    int32_t width, height;
2197    if (!msg->findInt32("width", &width)
2198            || !msg->findInt32("height", &height)) {
2199        return INVALID_OPERATION;
2200    }
2201
2202    OMX_VIDEO_CODINGTYPE compressionFormat;
2203    status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
2204
2205    if (err != OK) {
2206        return err;
2207    }
2208
2209    err = setVideoPortFormatType(
2210            kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
2211
2212    if (err != OK) {
2213        return err;
2214    }
2215
2216    int32_t tmp;
2217    if (msg->findInt32("color-format", &tmp)) {
2218        OMX_COLOR_FORMATTYPE colorFormat =
2219            static_cast<OMX_COLOR_FORMATTYPE>(tmp);
2220        err = setVideoPortFormatType(
2221                kPortIndexOutput, OMX_VIDEO_CodingUnused, colorFormat);
2222        if (err != OK) {
2223            ALOGW("[%s] does not support color format %d",
2224                  mComponentName.c_str(), colorFormat);
2225            err = setSupportedOutputFormat();
2226        }
2227    } else {
2228        err = setSupportedOutputFormat();
2229    }
2230
2231    if (err != OK) {
2232        return err;
2233    }
2234
2235    int32_t frameRateInt;
2236    float frameRateFloat;
2237    if (!msg->findFloat("frame-rate", &frameRateFloat)) {
2238        if (!msg->findInt32("frame-rate", &frameRateInt)) {
2239            frameRateInt = -1;
2240        }
2241        frameRateFloat = (float)frameRateInt;
2242    }
2243
2244    err = setVideoFormatOnPort(
2245            kPortIndexInput, width, height, compressionFormat, frameRateFloat);
2246
2247    if (err != OK) {
2248        return err;
2249    }
2250
2251    err = setVideoFormatOnPort(
2252            kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused);
2253
2254    if (err != OK) {
2255        return err;
2256    }
2257
2258    return OK;
2259}
2260
2261status_t ACodec::setupVideoEncoder(const char *mime, const sp<AMessage> &msg) {
2262    int32_t tmp;
2263    if (!msg->findInt32("color-format", &tmp)) {
2264        return INVALID_OPERATION;
2265    }
2266
2267    OMX_COLOR_FORMATTYPE colorFormat =
2268        static_cast<OMX_COLOR_FORMATTYPE>(tmp);
2269
2270    status_t err = setVideoPortFormatType(
2271            kPortIndexInput, OMX_VIDEO_CodingUnused, colorFormat);
2272
2273    if (err != OK) {
2274        ALOGE("[%s] does not support color format %d",
2275              mComponentName.c_str(), colorFormat);
2276
2277        return err;
2278    }
2279
2280    /* Input port configuration */
2281
2282    OMX_PARAM_PORTDEFINITIONTYPE def;
2283    InitOMXParams(&def);
2284
2285    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
2286
2287    def.nPortIndex = kPortIndexInput;
2288
2289    err = mOMX->getParameter(
2290            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2291
2292    if (err != OK) {
2293        return err;
2294    }
2295
2296    int32_t width, height, bitrate;
2297    if (!msg->findInt32("width", &width)
2298            || !msg->findInt32("height", &height)
2299            || !msg->findInt32("bitrate", &bitrate)) {
2300        return INVALID_OPERATION;
2301    }
2302
2303    video_def->nFrameWidth = width;
2304    video_def->nFrameHeight = height;
2305
2306    int32_t stride;
2307    if (!msg->findInt32("stride", &stride)) {
2308        stride = width;
2309    }
2310
2311    video_def->nStride = stride;
2312
2313    int32_t sliceHeight;
2314    if (!msg->findInt32("slice-height", &sliceHeight)) {
2315        sliceHeight = height;
2316    }
2317
2318    video_def->nSliceHeight = sliceHeight;
2319
2320    def.nBufferSize = (video_def->nStride * video_def->nSliceHeight * 3) / 2;
2321
2322    float frameRate;
2323    if (!msg->findFloat("frame-rate", &frameRate)) {
2324        int32_t tmp;
2325        if (!msg->findInt32("frame-rate", &tmp)) {
2326            return INVALID_OPERATION;
2327        }
2328        frameRate = (float)tmp;
2329        mTimePerFrameUs = (int64_t) (1000000.0f / frameRate);
2330    }
2331
2332    video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f);
2333    video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
2334    // this is redundant as it was already set up in setVideoPortFormatType
2335    // FIXME for now skip this only for flexible YUV formats
2336    if (colorFormat != OMX_COLOR_FormatYUV420Flexible) {
2337        video_def->eColorFormat = colorFormat;
2338    }
2339
2340    err = mOMX->setParameter(
2341            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2342
2343    if (err != OK) {
2344        ALOGE("[%s] failed to set input port definition parameters.",
2345              mComponentName.c_str());
2346
2347        return err;
2348    }
2349
2350    /* Output port configuration */
2351
2352    OMX_VIDEO_CODINGTYPE compressionFormat;
2353    err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
2354
2355    if (err != OK) {
2356        return err;
2357    }
2358
2359    err = setVideoPortFormatType(
2360            kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused);
2361
2362    if (err != OK) {
2363        ALOGE("[%s] does not support compression format %d",
2364             mComponentName.c_str(), compressionFormat);
2365
2366        return err;
2367    }
2368
2369    def.nPortIndex = kPortIndexOutput;
2370
2371    err = mOMX->getParameter(
2372            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2373
2374    if (err != OK) {
2375        return err;
2376    }
2377
2378    video_def->nFrameWidth = width;
2379    video_def->nFrameHeight = height;
2380    video_def->xFramerate = 0;
2381    video_def->nBitrate = bitrate;
2382    video_def->eCompressionFormat = compressionFormat;
2383    video_def->eColorFormat = OMX_COLOR_FormatUnused;
2384
2385    err = mOMX->setParameter(
2386            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2387
2388    if (err != OK) {
2389        ALOGE("[%s] failed to set output port definition parameters.",
2390              mComponentName.c_str());
2391
2392        return err;
2393    }
2394
2395    switch (compressionFormat) {
2396        case OMX_VIDEO_CodingMPEG4:
2397            err = setupMPEG4EncoderParameters(msg);
2398            break;
2399
2400        case OMX_VIDEO_CodingH263:
2401            err = setupH263EncoderParameters(msg);
2402            break;
2403
2404        case OMX_VIDEO_CodingAVC:
2405            err = setupAVCEncoderParameters(msg);
2406            break;
2407
2408        case OMX_VIDEO_CodingHEVC:
2409            err = setupHEVCEncoderParameters(msg);
2410            break;
2411
2412        case OMX_VIDEO_CodingVP8:
2413        case OMX_VIDEO_CodingVP9:
2414            err = setupVPXEncoderParameters(msg);
2415            break;
2416
2417        default:
2418            break;
2419    }
2420
2421    ALOGI("setupVideoEncoder succeeded");
2422
2423    return err;
2424}
2425
2426status_t ACodec::setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode) {
2427    OMX_VIDEO_PARAM_INTRAREFRESHTYPE params;
2428    InitOMXParams(&params);
2429    params.nPortIndex = kPortIndexOutput;
2430
2431    params.eRefreshMode = static_cast<OMX_VIDEO_INTRAREFRESHTYPE>(mode);
2432
2433    if (params.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic ||
2434            params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) {
2435        int32_t mbs;
2436        if (!msg->findInt32("intra-refresh-CIR-mbs", &mbs)) {
2437            return INVALID_OPERATION;
2438        }
2439        params.nCirMBs = mbs;
2440    }
2441
2442    if (params.eRefreshMode == OMX_VIDEO_IntraRefreshAdaptive ||
2443            params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) {
2444        int32_t mbs;
2445        if (!msg->findInt32("intra-refresh-AIR-mbs", &mbs)) {
2446            return INVALID_OPERATION;
2447        }
2448        params.nAirMBs = mbs;
2449
2450        int32_t ref;
2451        if (!msg->findInt32("intra-refresh-AIR-ref", &ref)) {
2452            return INVALID_OPERATION;
2453        }
2454        params.nAirRef = ref;
2455    }
2456
2457    status_t err = mOMX->setParameter(
2458            mNode, OMX_IndexParamVideoIntraRefresh,
2459            &params, sizeof(params));
2460    return err;
2461}
2462
2463static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) {
2464    if (iFramesInterval < 0) {
2465        return 0xFFFFFFFF;
2466    } else if (iFramesInterval == 0) {
2467        return 0;
2468    }
2469    OMX_U32 ret = frameRate * iFramesInterval;
2470    return ret;
2471}
2472
2473static OMX_VIDEO_CONTROLRATETYPE getBitrateMode(const sp<AMessage> &msg) {
2474    int32_t tmp;
2475    if (!msg->findInt32("bitrate-mode", &tmp)) {
2476        return OMX_Video_ControlRateVariable;
2477    }
2478
2479    return static_cast<OMX_VIDEO_CONTROLRATETYPE>(tmp);
2480}
2481
2482status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) {
2483    int32_t bitrate, iFrameInterval;
2484    if (!msg->findInt32("bitrate", &bitrate)
2485            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
2486        return INVALID_OPERATION;
2487    }
2488
2489    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
2490
2491    float frameRate;
2492    if (!msg->findFloat("frame-rate", &frameRate)) {
2493        int32_t tmp;
2494        if (!msg->findInt32("frame-rate", &tmp)) {
2495            return INVALID_OPERATION;
2496        }
2497        frameRate = (float)tmp;
2498    }
2499
2500    OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type;
2501    InitOMXParams(&mpeg4type);
2502    mpeg4type.nPortIndex = kPortIndexOutput;
2503
2504    status_t err = mOMX->getParameter(
2505            mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
2506
2507    if (err != OK) {
2508        return err;
2509    }
2510
2511    mpeg4type.nSliceHeaderSpacing = 0;
2512    mpeg4type.bSVH = OMX_FALSE;
2513    mpeg4type.bGov = OMX_FALSE;
2514
2515    mpeg4type.nAllowedPictureTypes =
2516        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
2517
2518    mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
2519    if (mpeg4type.nPFrames == 0) {
2520        mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
2521    }
2522    mpeg4type.nBFrames = 0;
2523    mpeg4type.nIDCVLCThreshold = 0;
2524    mpeg4type.bACPred = OMX_TRUE;
2525    mpeg4type.nMaxPacketSize = 256;
2526    mpeg4type.nTimeIncRes = 1000;
2527    mpeg4type.nHeaderExtension = 0;
2528    mpeg4type.bReversibleVLC = OMX_FALSE;
2529
2530    int32_t profile;
2531    if (msg->findInt32("profile", &profile)) {
2532        int32_t level;
2533        if (!msg->findInt32("level", &level)) {
2534            return INVALID_OPERATION;
2535        }
2536
2537        err = verifySupportForProfileAndLevel(profile, level);
2538
2539        if (err != OK) {
2540            return err;
2541        }
2542
2543        mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile);
2544        mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level);
2545    }
2546
2547    err = mOMX->setParameter(
2548            mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
2549
2550    if (err != OK) {
2551        return err;
2552    }
2553
2554    err = configureBitrate(bitrate, bitrateMode);
2555
2556    if (err != OK) {
2557        return err;
2558    }
2559
2560    return setupErrorCorrectionParameters();
2561}
2562
2563status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) {
2564    int32_t bitrate, iFrameInterval;
2565    if (!msg->findInt32("bitrate", &bitrate)
2566            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
2567        return INVALID_OPERATION;
2568    }
2569
2570    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
2571
2572    float frameRate;
2573    if (!msg->findFloat("frame-rate", &frameRate)) {
2574        int32_t tmp;
2575        if (!msg->findInt32("frame-rate", &tmp)) {
2576            return INVALID_OPERATION;
2577        }
2578        frameRate = (float)tmp;
2579    }
2580
2581    OMX_VIDEO_PARAM_H263TYPE h263type;
2582    InitOMXParams(&h263type);
2583    h263type.nPortIndex = kPortIndexOutput;
2584
2585    status_t err = mOMX->getParameter(
2586            mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
2587
2588    if (err != OK) {
2589        return err;
2590    }
2591
2592    h263type.nAllowedPictureTypes =
2593        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
2594
2595    h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
2596    if (h263type.nPFrames == 0) {
2597        h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
2598    }
2599    h263type.nBFrames = 0;
2600
2601    int32_t profile;
2602    if (msg->findInt32("profile", &profile)) {
2603        int32_t level;
2604        if (!msg->findInt32("level", &level)) {
2605            return INVALID_OPERATION;
2606        }
2607
2608        err = verifySupportForProfileAndLevel(profile, level);
2609
2610        if (err != OK) {
2611            return err;
2612        }
2613
2614        h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile);
2615        h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level);
2616    }
2617
2618    h263type.bPLUSPTYPEAllowed = OMX_FALSE;
2619    h263type.bForceRoundingTypeToZero = OMX_FALSE;
2620    h263type.nPictureHeaderRepetition = 0;
2621    h263type.nGOBHeaderInterval = 0;
2622
2623    err = mOMX->setParameter(
2624            mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
2625
2626    if (err != OK) {
2627        return err;
2628    }
2629
2630    err = configureBitrate(bitrate, bitrateMode);
2631
2632    if (err != OK) {
2633        return err;
2634    }
2635
2636    return setupErrorCorrectionParameters();
2637}
2638
2639// static
2640int /* OMX_VIDEO_AVCLEVELTYPE */ ACodec::getAVCLevelFor(
2641        int width, int height, int rate, int bitrate,
2642        OMX_VIDEO_AVCPROFILETYPE profile) {
2643    // convert bitrate to main/baseline profile kbps equivalent
2644    switch (profile) {
2645        case OMX_VIDEO_AVCProfileHigh10:
2646            bitrate = divUp(bitrate, 3000); break;
2647        case OMX_VIDEO_AVCProfileHigh:
2648            bitrate = divUp(bitrate, 1250); break;
2649        default:
2650            bitrate = divUp(bitrate, 1000); break;
2651    }
2652
2653    // convert size and rate to MBs
2654    width = divUp(width, 16);
2655    height = divUp(height, 16);
2656    int mbs = width * height;
2657    rate *= mbs;
2658    int maxDimension = max(width, height);
2659
2660    static const int limits[][5] = {
2661        /*   MBps     MB   dim  bitrate        level */
2662        {    1485,    99,  28,     64, OMX_VIDEO_AVCLevel1  },
2663        {    1485,    99,  28,    128, OMX_VIDEO_AVCLevel1b },
2664        {    3000,   396,  56,    192, OMX_VIDEO_AVCLevel11 },
2665        {    6000,   396,  56,    384, OMX_VIDEO_AVCLevel12 },
2666        {   11880,   396,  56,    768, OMX_VIDEO_AVCLevel13 },
2667        {   11880,   396,  56,   2000, OMX_VIDEO_AVCLevel2  },
2668        {   19800,   792,  79,   4000, OMX_VIDEO_AVCLevel21 },
2669        {   20250,  1620, 113,   4000, OMX_VIDEO_AVCLevel22 },
2670        {   40500,  1620, 113,  10000, OMX_VIDEO_AVCLevel3  },
2671        {  108000,  3600, 169,  14000, OMX_VIDEO_AVCLevel31 },
2672        {  216000,  5120, 202,  20000, OMX_VIDEO_AVCLevel32 },
2673        {  245760,  8192, 256,  20000, OMX_VIDEO_AVCLevel4  },
2674        {  245760,  8192, 256,  50000, OMX_VIDEO_AVCLevel41 },
2675        {  522240,  8704, 263,  50000, OMX_VIDEO_AVCLevel42 },
2676        {  589824, 22080, 420, 135000, OMX_VIDEO_AVCLevel5  },
2677        {  983040, 36864, 543, 240000, OMX_VIDEO_AVCLevel51 },
2678        { 2073600, 36864, 543, 240000, OMX_VIDEO_AVCLevel52 },
2679    };
2680
2681    for (size_t i = 0; i < ARRAY_SIZE(limits); i++) {
2682        const int (&limit)[5] = limits[i];
2683        if (rate <= limit[0] && mbs <= limit[1] && maxDimension <= limit[2]
2684                && bitrate <= limit[3]) {
2685            return limit[4];
2686        }
2687    }
2688    return 0;
2689}
2690
2691status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) {
2692    int32_t bitrate, iFrameInterval;
2693    if (!msg->findInt32("bitrate", &bitrate)
2694            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
2695        return INVALID_OPERATION;
2696    }
2697
2698    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
2699
2700    float frameRate;
2701    if (!msg->findFloat("frame-rate", &frameRate)) {
2702        int32_t tmp;
2703        if (!msg->findInt32("frame-rate", &tmp)) {
2704            return INVALID_OPERATION;
2705        }
2706        frameRate = (float)tmp;
2707    }
2708
2709    status_t err = OK;
2710    int32_t intraRefreshMode = 0;
2711    if (msg->findInt32("intra-refresh-mode", &intraRefreshMode)) {
2712        err = setCyclicIntraMacroblockRefresh(msg, intraRefreshMode);
2713        if (err != OK) {
2714            ALOGE("Setting intra macroblock refresh mode (%d) failed: 0x%x",
2715                    err, intraRefreshMode);
2716            return err;
2717        }
2718    }
2719
2720    OMX_VIDEO_PARAM_AVCTYPE h264type;
2721    InitOMXParams(&h264type);
2722    h264type.nPortIndex = kPortIndexOutput;
2723
2724    err = mOMX->getParameter(
2725            mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
2726
2727    if (err != OK) {
2728        return err;
2729    }
2730
2731    h264type.nAllowedPictureTypes =
2732        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
2733
2734    int32_t profile;
2735    if (msg->findInt32("profile", &profile)) {
2736        int32_t level;
2737        if (!msg->findInt32("level", &level)) {
2738            return INVALID_OPERATION;
2739        }
2740
2741        err = verifySupportForProfileAndLevel(profile, level);
2742
2743        if (err != OK) {
2744            return err;
2745        }
2746
2747        h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile);
2748        h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level);
2749    }
2750
2751    // XXX
2752    if (h264type.eProfile != OMX_VIDEO_AVCProfileBaseline) {
2753        ALOGW("Use baseline profile instead of %d for AVC recording",
2754            h264type.eProfile);
2755        h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
2756    }
2757
2758    if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
2759        h264type.nSliceHeaderSpacing = 0;
2760        h264type.bUseHadamard = OMX_TRUE;
2761        h264type.nRefFrames = 1;
2762        h264type.nBFrames = 0;
2763        h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
2764        if (h264type.nPFrames == 0) {
2765            h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
2766        }
2767        h264type.nRefIdx10ActiveMinus1 = 0;
2768        h264type.nRefIdx11ActiveMinus1 = 0;
2769        h264type.bEntropyCodingCABAC = OMX_FALSE;
2770        h264type.bWeightedPPrediction = OMX_FALSE;
2771        h264type.bconstIpred = OMX_FALSE;
2772        h264type.bDirect8x8Inference = OMX_FALSE;
2773        h264type.bDirectSpatialTemporal = OMX_FALSE;
2774        h264type.nCabacInitIdc = 0;
2775    }
2776
2777    if (h264type.nBFrames != 0) {
2778        h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
2779    }
2780
2781    h264type.bEnableUEP = OMX_FALSE;
2782    h264type.bEnableFMO = OMX_FALSE;
2783    h264type.bEnableASO = OMX_FALSE;
2784    h264type.bEnableRS = OMX_FALSE;
2785    h264type.bFrameMBsOnly = OMX_TRUE;
2786    h264type.bMBAFF = OMX_FALSE;
2787    h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
2788
2789    err = mOMX->setParameter(
2790            mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
2791
2792    if (err != OK) {
2793        return err;
2794    }
2795
2796    return configureBitrate(bitrate, bitrateMode);
2797}
2798
2799status_t ACodec::setupHEVCEncoderParameters(const sp<AMessage> &msg) {
2800    int32_t bitrate, iFrameInterval;
2801    if (!msg->findInt32("bitrate", &bitrate)
2802            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
2803        return INVALID_OPERATION;
2804    }
2805
2806    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
2807
2808    float frameRate;
2809    if (!msg->findFloat("frame-rate", &frameRate)) {
2810        int32_t tmp;
2811        if (!msg->findInt32("frame-rate", &tmp)) {
2812            return INVALID_OPERATION;
2813        }
2814        frameRate = (float)tmp;
2815    }
2816
2817    OMX_VIDEO_PARAM_HEVCTYPE hevcType;
2818    InitOMXParams(&hevcType);
2819    hevcType.nPortIndex = kPortIndexOutput;
2820
2821    status_t err = OK;
2822    err = mOMX->getParameter(
2823            mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
2824    if (err != OK) {
2825        return err;
2826    }
2827
2828    int32_t profile;
2829    if (msg->findInt32("profile", &profile)) {
2830        int32_t level;
2831        if (!msg->findInt32("level", &level)) {
2832            return INVALID_OPERATION;
2833        }
2834
2835        err = verifySupportForProfileAndLevel(profile, level);
2836        if (err != OK) {
2837            return err;
2838        }
2839
2840        hevcType.eProfile = static_cast<OMX_VIDEO_HEVCPROFILETYPE>(profile);
2841        hevcType.eLevel = static_cast<OMX_VIDEO_HEVCLEVELTYPE>(level);
2842    }
2843
2844    // TODO: Need OMX structure definition for setting iFrameInterval
2845
2846    err = mOMX->setParameter(
2847            mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
2848    if (err != OK) {
2849        return err;
2850    }
2851
2852    return configureBitrate(bitrate, bitrateMode);
2853}
2854
2855status_t ACodec::setupVPXEncoderParameters(const sp<AMessage> &msg) {
2856    int32_t bitrate;
2857    int32_t iFrameInterval = 0;
2858    size_t tsLayers = 0;
2859    OMX_VIDEO_ANDROID_VPXTEMPORALLAYERPATTERNTYPE pattern =
2860        OMX_VIDEO_VPXTemporalLayerPatternNone;
2861    static const uint32_t kVp8LayerRateAlloction
2862        [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS]
2863        [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS] = {
2864        {100, 100, 100},  // 1 layer
2865        { 60, 100, 100},  // 2 layers {60%, 40%}
2866        { 40,  60, 100},  // 3 layers {40%, 20%, 40%}
2867    };
2868    if (!msg->findInt32("bitrate", &bitrate)) {
2869        return INVALID_OPERATION;
2870    }
2871    msg->findInt32("i-frame-interval", &iFrameInterval);
2872
2873    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
2874
2875    float frameRate;
2876    if (!msg->findFloat("frame-rate", &frameRate)) {
2877        int32_t tmp;
2878        if (!msg->findInt32("frame-rate", &tmp)) {
2879            return INVALID_OPERATION;
2880        }
2881        frameRate = (float)tmp;
2882    }
2883
2884    AString tsSchema;
2885    if (msg->findString("ts-schema", &tsSchema)) {
2886        if (tsSchema == "webrtc.vp8.1-layer") {
2887            pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
2888            tsLayers = 1;
2889        } else if (tsSchema == "webrtc.vp8.2-layer") {
2890            pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
2891            tsLayers = 2;
2892        } else if (tsSchema == "webrtc.vp8.3-layer") {
2893            pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
2894            tsLayers = 3;
2895        } else {
2896            ALOGW("Unsupported ts-schema [%s]", tsSchema.c_str());
2897        }
2898    }
2899
2900    OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type;
2901    InitOMXParams(&vp8type);
2902    vp8type.nPortIndex = kPortIndexOutput;
2903    status_t err = mOMX->getParameter(
2904            mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
2905            &vp8type, sizeof(vp8type));
2906
2907    if (err == OK) {
2908        if (iFrameInterval > 0) {
2909            vp8type.nKeyFrameInterval = setPFramesSpacing(iFrameInterval, frameRate);
2910        }
2911        vp8type.eTemporalPattern = pattern;
2912        vp8type.nTemporalLayerCount = tsLayers;
2913        if (tsLayers > 0) {
2914            for (size_t i = 0; i < OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS; i++) {
2915                vp8type.nTemporalLayerBitrateRatio[i] =
2916                    kVp8LayerRateAlloction[tsLayers - 1][i];
2917            }
2918        }
2919        if (bitrateMode == OMX_Video_ControlRateConstant) {
2920            vp8type.nMinQuantizer = 2;
2921            vp8type.nMaxQuantizer = 63;
2922        }
2923
2924        err = mOMX->setParameter(
2925                mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
2926                &vp8type, sizeof(vp8type));
2927        if (err != OK) {
2928            ALOGW("Extended VP8 parameters set failed: %d", err);
2929        }
2930    }
2931
2932    return configureBitrate(bitrate, bitrateMode);
2933}
2934
2935status_t ACodec::verifySupportForProfileAndLevel(
2936        int32_t profile, int32_t level) {
2937    OMX_VIDEO_PARAM_PROFILELEVELTYPE params;
2938    InitOMXParams(&params);
2939    params.nPortIndex = kPortIndexOutput;
2940
2941    for (params.nProfileIndex = 0;; ++params.nProfileIndex) {
2942        status_t err = mOMX->getParameter(
2943                mNode,
2944                OMX_IndexParamVideoProfileLevelQuerySupported,
2945                &params,
2946                sizeof(params));
2947
2948        if (err != OK) {
2949            return err;
2950        }
2951
2952        int32_t supportedProfile = static_cast<int32_t>(params.eProfile);
2953        int32_t supportedLevel = static_cast<int32_t>(params.eLevel);
2954
2955        if (profile == supportedProfile && level <= supportedLevel) {
2956            return OK;
2957        }
2958    }
2959}
2960
2961status_t ACodec::configureBitrate(
2962        int32_t bitrate, OMX_VIDEO_CONTROLRATETYPE bitrateMode) {
2963    OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
2964    InitOMXParams(&bitrateType);
2965    bitrateType.nPortIndex = kPortIndexOutput;
2966
2967    status_t err = mOMX->getParameter(
2968            mNode, OMX_IndexParamVideoBitrate,
2969            &bitrateType, sizeof(bitrateType));
2970
2971    if (err != OK) {
2972        return err;
2973    }
2974
2975    bitrateType.eControlRate = bitrateMode;
2976    bitrateType.nTargetBitrate = bitrate;
2977
2978    return mOMX->setParameter(
2979            mNode, OMX_IndexParamVideoBitrate,
2980            &bitrateType, sizeof(bitrateType));
2981}
2982
2983status_t ACodec::setupErrorCorrectionParameters() {
2984    OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
2985    InitOMXParams(&errorCorrectionType);
2986    errorCorrectionType.nPortIndex = kPortIndexOutput;
2987
2988    status_t err = mOMX->getParameter(
2989            mNode, OMX_IndexParamVideoErrorCorrection,
2990            &errorCorrectionType, sizeof(errorCorrectionType));
2991
2992    if (err != OK) {
2993        return OK;  // Optional feature. Ignore this failure
2994    }
2995
2996    errorCorrectionType.bEnableHEC = OMX_FALSE;
2997    errorCorrectionType.bEnableResync = OMX_TRUE;
2998    errorCorrectionType.nResynchMarkerSpacing = 256;
2999    errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
3000    errorCorrectionType.bEnableRVLC = OMX_FALSE;
3001
3002    return mOMX->setParameter(
3003            mNode, OMX_IndexParamVideoErrorCorrection,
3004            &errorCorrectionType, sizeof(errorCorrectionType));
3005}
3006
3007status_t ACodec::setVideoFormatOnPort(
3008        OMX_U32 portIndex,
3009        int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat,
3010        float frameRate) {
3011    OMX_PARAM_PORTDEFINITIONTYPE def;
3012    InitOMXParams(&def);
3013    def.nPortIndex = portIndex;
3014
3015    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
3016
3017    status_t err = mOMX->getParameter(
3018            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
3019
3020    CHECK_EQ(err, (status_t)OK);
3021
3022    if (portIndex == kPortIndexInput) {
3023        // XXX Need a (much) better heuristic to compute input buffer sizes.
3024        const size_t X = 64 * 1024;
3025        if (def.nBufferSize < X) {
3026            def.nBufferSize = X;
3027        }
3028    }
3029
3030    CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
3031
3032    video_def->nFrameWidth = width;
3033    video_def->nFrameHeight = height;
3034
3035    if (portIndex == kPortIndexInput) {
3036        video_def->eCompressionFormat = compressionFormat;
3037        video_def->eColorFormat = OMX_COLOR_FormatUnused;
3038        if (frameRate >= 0) {
3039            video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f);
3040        }
3041    }
3042
3043    err = mOMX->setParameter(
3044            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
3045
3046    return err;
3047}
3048
3049status_t ACodec::initNativeWindow() {
3050    if (mNativeWindow != NULL) {
3051        return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE);
3052    }
3053
3054    mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE);
3055    return OK;
3056}
3057
3058size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const {
3059    size_t n = 0;
3060
3061    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
3062        const BufferInfo &info = mBuffers[portIndex].itemAt(i);
3063
3064        if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) {
3065            ++n;
3066        }
3067    }
3068
3069    return n;
3070}
3071
3072size_t ACodec::countBuffersOwnedByNativeWindow() const {
3073    size_t n = 0;
3074
3075    for (size_t i = 0; i < mBuffers[kPortIndexOutput].size(); ++i) {
3076        const BufferInfo &info = mBuffers[kPortIndexOutput].itemAt(i);
3077
3078        if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
3079            ++n;
3080        }
3081    }
3082
3083    return n;
3084}
3085
3086void ACodec::waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs() {
3087    if (mNativeWindow == NULL) {
3088        return;
3089    }
3090
3091    while (countBuffersOwnedByNativeWindow() > mNumUndequeuedBuffers
3092            && dequeueBufferFromNativeWindow() != NULL) {
3093        // these buffers will be submitted as regular buffers; account for this
3094        if (mStoreMetaDataInOutputBuffers && mMetaDataBuffersToSubmit > 0) {
3095            --mMetaDataBuffersToSubmit;
3096        }
3097    }
3098}
3099
3100bool ACodec::allYourBuffersAreBelongToUs(
3101        OMX_U32 portIndex) {
3102    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
3103        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
3104
3105        if (info->mStatus != BufferInfo::OWNED_BY_US
3106                && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
3107            ALOGV("[%s] Buffer %u on port %u still has status %d",
3108                    mComponentName.c_str(),
3109                    info->mBufferID, portIndex, info->mStatus);
3110            return false;
3111        }
3112    }
3113
3114    return true;
3115}
3116
3117bool ACodec::allYourBuffersAreBelongToUs() {
3118    return allYourBuffersAreBelongToUs(kPortIndexInput)
3119        && allYourBuffersAreBelongToUs(kPortIndexOutput);
3120}
3121
3122void ACodec::deferMessage(const sp<AMessage> &msg) {
3123    mDeferredQueue.push_back(msg);
3124}
3125
3126void ACodec::processDeferredMessages() {
3127    List<sp<AMessage> > queue = mDeferredQueue;
3128    mDeferredQueue.clear();
3129
3130    List<sp<AMessage> >::iterator it = queue.begin();
3131    while (it != queue.end()) {
3132        onMessageReceived(*it++);
3133    }
3134}
3135
3136// static
3137bool ACodec::describeDefaultColorFormat(DescribeColorFormatParams &params) {
3138    MediaImage &image = params.sMediaImage;
3139    memset(&image, 0, sizeof(image));
3140
3141    image.mType = MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
3142    image.mNumPlanes = 0;
3143
3144    const OMX_COLOR_FORMATTYPE fmt = params.eColorFormat;
3145    image.mWidth = params.nFrameWidth;
3146    image.mHeight = params.nFrameHeight;
3147
3148    // only supporting YUV420
3149    if (fmt != OMX_COLOR_FormatYUV420Planar &&
3150        fmt != OMX_COLOR_FormatYUV420PackedPlanar &&
3151        fmt != OMX_COLOR_FormatYUV420SemiPlanar &&
3152        fmt != OMX_COLOR_FormatYUV420PackedSemiPlanar) {
3153        ALOGW("do not know color format 0x%x = %d", fmt, fmt);
3154        return false;
3155    }
3156
3157    // TEMPORARY FIX for some vendors that advertise sliceHeight as 0
3158    if (params.nStride != 0 && params.nSliceHeight == 0) {
3159        ALOGW("using sliceHeight=%u instead of what codec advertised (=0)",
3160                params.nFrameHeight);
3161        params.nSliceHeight = params.nFrameHeight;
3162    }
3163
3164    // we need stride and slice-height to be non-zero
3165    if (params.nStride == 0 || params.nSliceHeight == 0) {
3166        ALOGW("cannot describe color format 0x%x = %d with stride=%u and sliceHeight=%u",
3167                fmt, fmt, params.nStride, params.nSliceHeight);
3168        return false;
3169    }
3170
3171    // set-up YUV format
3172    image.mType = MediaImage::MEDIA_IMAGE_TYPE_YUV;
3173    image.mNumPlanes = 3;
3174    image.mBitDepth = 8;
3175    image.mPlane[image.Y].mOffset = 0;
3176    image.mPlane[image.Y].mColInc = 1;
3177    image.mPlane[image.Y].mRowInc = params.nStride;
3178    image.mPlane[image.Y].mHorizSubsampling = 1;
3179    image.mPlane[image.Y].mVertSubsampling = 1;
3180
3181    switch (fmt) {
3182        case OMX_COLOR_FormatYUV420Planar: // used for YV12
3183        case OMX_COLOR_FormatYUV420PackedPlanar:
3184            image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight;
3185            image.mPlane[image.U].mColInc = 1;
3186            image.mPlane[image.U].mRowInc = params.nStride / 2;
3187            image.mPlane[image.U].mHorizSubsampling = 2;
3188            image.mPlane[image.U].mVertSubsampling = 2;
3189
3190            image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset
3191                    + (params.nStride * params.nSliceHeight / 4);
3192            image.mPlane[image.V].mColInc = 1;
3193            image.mPlane[image.V].mRowInc = params.nStride / 2;
3194            image.mPlane[image.V].mHorizSubsampling = 2;
3195            image.mPlane[image.V].mVertSubsampling = 2;
3196            break;
3197
3198        case OMX_COLOR_FormatYUV420SemiPlanar:
3199            // FIXME: NV21 for sw-encoder, NV12 for decoder and hw-encoder
3200        case OMX_COLOR_FormatYUV420PackedSemiPlanar:
3201            // NV12
3202            image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight;
3203            image.mPlane[image.U].mColInc = 2;
3204            image.mPlane[image.U].mRowInc = params.nStride;
3205            image.mPlane[image.U].mHorizSubsampling = 2;
3206            image.mPlane[image.U].mVertSubsampling = 2;
3207
3208            image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset + 1;
3209            image.mPlane[image.V].mColInc = 2;
3210            image.mPlane[image.V].mRowInc = params.nStride;
3211            image.mPlane[image.V].mHorizSubsampling = 2;
3212            image.mPlane[image.V].mVertSubsampling = 2;
3213            break;
3214
3215        default:
3216            TRESPASS();
3217    }
3218    return true;
3219}
3220
3221// static
3222bool ACodec::describeColorFormat(
3223        const sp<IOMX> &omx, IOMX::node_id node,
3224        DescribeColorFormatParams &describeParams)
3225{
3226    OMX_INDEXTYPE describeColorFormatIndex;
3227    if (omx->getExtensionIndex(
3228            node, "OMX.google.android.index.describeColorFormat",
3229            &describeColorFormatIndex) != OK ||
3230        omx->getParameter(
3231            node, describeColorFormatIndex,
3232            &describeParams, sizeof(describeParams)) != OK) {
3233        return describeDefaultColorFormat(describeParams);
3234    }
3235    return describeParams.sMediaImage.mType !=
3236            MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
3237}
3238
3239// static
3240bool ACodec::isFlexibleColorFormat(
3241         const sp<IOMX> &omx, IOMX::node_id node,
3242         uint32_t colorFormat, OMX_U32 *flexibleEquivalent) {
3243    DescribeColorFormatParams describeParams;
3244    InitOMXParams(&describeParams);
3245    describeParams.eColorFormat = (OMX_COLOR_FORMATTYPE)colorFormat;
3246    // reasonable dummy values
3247    describeParams.nFrameWidth = 128;
3248    describeParams.nFrameHeight = 128;
3249    describeParams.nStride = 128;
3250    describeParams.nSliceHeight = 128;
3251
3252    CHECK(flexibleEquivalent != NULL);
3253
3254    if (!describeColorFormat(omx, node, describeParams)) {
3255        return false;
3256    }
3257
3258    const MediaImage &img = describeParams.sMediaImage;
3259    if (img.mType == MediaImage::MEDIA_IMAGE_TYPE_YUV) {
3260        if (img.mNumPlanes != 3 ||
3261            img.mPlane[img.Y].mHorizSubsampling != 1 ||
3262            img.mPlane[img.Y].mVertSubsampling != 1) {
3263            return false;
3264        }
3265
3266        // YUV 420
3267        if (img.mPlane[img.U].mHorizSubsampling == 2
3268                && img.mPlane[img.U].mVertSubsampling == 2
3269                && img.mPlane[img.V].mHorizSubsampling == 2
3270                && img.mPlane[img.V].mVertSubsampling == 2) {
3271            // possible flexible YUV420 format
3272            if (img.mBitDepth <= 8) {
3273               *flexibleEquivalent = OMX_COLOR_FormatYUV420Flexible;
3274               return true;
3275            }
3276        }
3277    }
3278    return false;
3279}
3280
3281status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> &notify) {
3282    // TODO: catch errors an return them instead of using CHECK
3283    OMX_PARAM_PORTDEFINITIONTYPE def;
3284    InitOMXParams(&def);
3285    def.nPortIndex = portIndex;
3286
3287    CHECK_EQ(mOMX->getParameter(
3288                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)),
3289             (status_t)OK);
3290
3291    CHECK_EQ((int)def.eDir,
3292            (int)(portIndex == kPortIndexOutput ? OMX_DirOutput : OMX_DirInput));
3293
3294    switch (def.eDomain) {
3295        case OMX_PortDomainVideo:
3296        {
3297            OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
3298            switch ((int)videoDef->eCompressionFormat) {
3299                case OMX_VIDEO_CodingUnused:
3300                {
3301                    CHECK(mIsEncoder ^ (portIndex == kPortIndexOutput));
3302                    notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW);
3303
3304                    notify->setInt32("stride", videoDef->nStride);
3305                    notify->setInt32("slice-height", videoDef->nSliceHeight);
3306                    notify->setInt32("color-format", videoDef->eColorFormat);
3307
3308                    DescribeColorFormatParams describeParams;
3309                    InitOMXParams(&describeParams);
3310                    describeParams.eColorFormat = videoDef->eColorFormat;
3311                    describeParams.nFrameWidth = videoDef->nFrameWidth;
3312                    describeParams.nFrameHeight = videoDef->nFrameHeight;
3313                    describeParams.nStride = videoDef->nStride;
3314                    describeParams.nSliceHeight = videoDef->nSliceHeight;
3315
3316                    if (describeColorFormat(mOMX, mNode, describeParams)) {
3317                        notify->setBuffer(
3318                                "image-data",
3319                                ABuffer::CreateAsCopy(
3320                                        &describeParams.sMediaImage,
3321                                        sizeof(describeParams.sMediaImage)));
3322                    }
3323
3324                    if (portIndex != kPortIndexOutput) {
3325                        // TODO: also get input crop
3326                        break;
3327                    }
3328
3329                    OMX_CONFIG_RECTTYPE rect;
3330                    InitOMXParams(&rect);
3331                    rect.nPortIndex = portIndex;
3332
3333                    if (mOMX->getConfig(
3334                                mNode,
3335                                (portIndex == kPortIndexOutput ?
3336                                        OMX_IndexConfigCommonOutputCrop :
3337                                        OMX_IndexConfigCommonInputCrop),
3338                                &rect, sizeof(rect)) != OK) {
3339                        rect.nLeft = 0;
3340                        rect.nTop = 0;
3341                        rect.nWidth = videoDef->nFrameWidth;
3342                        rect.nHeight = videoDef->nFrameHeight;
3343                    }
3344
3345                    CHECK_GE(rect.nLeft, 0);
3346                    CHECK_GE(rect.nTop, 0);
3347                    CHECK_GE(rect.nWidth, 0u);
3348                    CHECK_GE(rect.nHeight, 0u);
3349                    CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth);
3350                    CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight);
3351
3352                    notify->setRect(
3353                            "crop",
3354                            rect.nLeft,
3355                            rect.nTop,
3356                            rect.nLeft + rect.nWidth - 1,
3357                            rect.nTop + rect.nHeight - 1);
3358
3359                    break;
3360                }
3361
3362                case OMX_VIDEO_CodingVP8:
3363                case OMX_VIDEO_CodingVP9:
3364                {
3365                    OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type;
3366                    InitOMXParams(&vp8type);
3367                    vp8type.nPortIndex = kPortIndexOutput;
3368                    status_t err = mOMX->getParameter(
3369                            mNode,
3370                            (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
3371                            &vp8type,
3372                            sizeof(vp8type));
3373
3374                    if (err == OK) {
3375                        AString tsSchema = "none";
3376                        if (vp8type.eTemporalPattern
3377                                == OMX_VIDEO_VPXTemporalLayerPatternWebRTC) {
3378                            switch (vp8type.nTemporalLayerCount) {
3379                                case 1:
3380                                {
3381                                    tsSchema = "webrtc.vp8.1-layer";
3382                                    break;
3383                                }
3384                                case 2:
3385                                {
3386                                    tsSchema = "webrtc.vp8.2-layer";
3387                                    break;
3388                                }
3389                                case 3:
3390                                {
3391                                    tsSchema = "webrtc.vp8.3-layer";
3392                                    break;
3393                                }
3394                                default:
3395                                {
3396                                    break;
3397                                }
3398                            }
3399                        }
3400                        notify->setString("ts-schema", tsSchema);
3401                    }
3402                    // Fall through to set up mime.
3403                }
3404
3405                default:
3406                {
3407                    CHECK(mIsEncoder ^ (portIndex == kPortIndexInput));
3408                    AString mime;
3409                    if (GetMimeTypeForVideoCoding(
3410                        videoDef->eCompressionFormat, &mime) != OK) {
3411                        notify->setString("mime", "application/octet-stream");
3412                    } else {
3413                        notify->setString("mime", mime.c_str());
3414                    }
3415                    break;
3416                }
3417            }
3418
3419            notify->setInt32("width", videoDef->nFrameWidth);
3420            notify->setInt32("height", videoDef->nFrameHeight);
3421            break;
3422        }
3423
3424        case OMX_PortDomainAudio:
3425        {
3426            OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
3427
3428            switch ((int)audioDef->eEncoding) {
3429                case OMX_AUDIO_CodingPCM:
3430                {
3431                    OMX_AUDIO_PARAM_PCMMODETYPE params;
3432                    InitOMXParams(&params);
3433                    params.nPortIndex = portIndex;
3434
3435                    CHECK_EQ(mOMX->getParameter(
3436                                mNode, OMX_IndexParamAudioPcm,
3437                                &params, sizeof(params)),
3438                             (status_t)OK);
3439
3440                    CHECK_GT(params.nChannels, 0);
3441                    CHECK(params.nChannels == 1 || params.bInterleaved);
3442                    CHECK_EQ(params.nBitPerSample, 16u);
3443
3444                    CHECK_EQ((int)params.eNumData,
3445                             (int)OMX_NumericalDataSigned);
3446
3447                    CHECK_EQ((int)params.ePCMMode,
3448                             (int)OMX_AUDIO_PCMModeLinear);
3449
3450                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
3451                    notify->setInt32("channel-count", params.nChannels);
3452                    notify->setInt32("sample-rate", params.nSamplingRate);
3453
3454                    if (mChannelMaskPresent) {
3455                        notify->setInt32("channel-mask", mChannelMask);
3456                    }
3457                    break;
3458                }
3459
3460                case OMX_AUDIO_CodingAAC:
3461                {
3462                    OMX_AUDIO_PARAM_AACPROFILETYPE params;
3463                    InitOMXParams(&params);
3464                    params.nPortIndex = portIndex;
3465
3466                    CHECK_EQ(mOMX->getParameter(
3467                                mNode, OMX_IndexParamAudioAac,
3468                                &params, sizeof(params)),
3469                             (status_t)OK);
3470
3471                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
3472                    notify->setInt32("channel-count", params.nChannels);
3473                    notify->setInt32("sample-rate", params.nSampleRate);
3474                    break;
3475                }
3476
3477                case OMX_AUDIO_CodingAMR:
3478                {
3479                    OMX_AUDIO_PARAM_AMRTYPE params;
3480                    InitOMXParams(&params);
3481                    params.nPortIndex = portIndex;
3482
3483                    CHECK_EQ(mOMX->getParameter(
3484                                mNode, OMX_IndexParamAudioAmr,
3485                                &params, sizeof(params)),
3486                             (status_t)OK);
3487
3488                    notify->setInt32("channel-count", 1);
3489                    if (params.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0) {
3490                        notify->setString(
3491                                "mime", MEDIA_MIMETYPE_AUDIO_AMR_WB);
3492
3493                        notify->setInt32("sample-rate", 16000);
3494                    } else {
3495                        notify->setString(
3496                                "mime", MEDIA_MIMETYPE_AUDIO_AMR_NB);
3497
3498                        notify->setInt32("sample-rate", 8000);
3499                    }
3500                    break;
3501                }
3502
3503                case OMX_AUDIO_CodingFLAC:
3504                {
3505                    OMX_AUDIO_PARAM_FLACTYPE params;
3506                    InitOMXParams(&params);
3507                    params.nPortIndex = portIndex;
3508
3509                    CHECK_EQ(mOMX->getParameter(
3510                                mNode, OMX_IndexParamAudioFlac,
3511                                &params, sizeof(params)),
3512                             (status_t)OK);
3513
3514                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_FLAC);
3515                    notify->setInt32("channel-count", params.nChannels);
3516                    notify->setInt32("sample-rate", params.nSampleRate);
3517                    break;
3518                }
3519
3520                case OMX_AUDIO_CodingMP3:
3521                {
3522                    OMX_AUDIO_PARAM_MP3TYPE params;
3523                    InitOMXParams(&params);
3524                    params.nPortIndex = portIndex;
3525
3526                    CHECK_EQ(mOMX->getParameter(
3527                                mNode, OMX_IndexParamAudioMp3,
3528                                &params, sizeof(params)),
3529                             (status_t)OK);
3530
3531                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MPEG);
3532                    notify->setInt32("channel-count", params.nChannels);
3533                    notify->setInt32("sample-rate", params.nSampleRate);
3534                    break;
3535                }
3536
3537                case OMX_AUDIO_CodingVORBIS:
3538                {
3539                    OMX_AUDIO_PARAM_VORBISTYPE params;
3540                    InitOMXParams(&params);
3541                    params.nPortIndex = portIndex;
3542
3543                    CHECK_EQ(mOMX->getParameter(
3544                                mNode, OMX_IndexParamAudioVorbis,
3545                                &params, sizeof(params)),
3546                             (status_t)OK);
3547
3548                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_VORBIS);
3549                    notify->setInt32("channel-count", params.nChannels);
3550                    notify->setInt32("sample-rate", params.nSampleRate);
3551                    break;
3552                }
3553
3554                case OMX_AUDIO_CodingAndroidAC3:
3555                {
3556                    OMX_AUDIO_PARAM_ANDROID_AC3TYPE params;
3557                    InitOMXParams(&params);
3558                    params.nPortIndex = portIndex;
3559
3560                    CHECK_EQ((status_t)OK, mOMX->getParameter(
3561                            mNode,
3562                            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
3563                            &params,
3564                            sizeof(params)));
3565
3566                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AC3);
3567                    notify->setInt32("channel-count", params.nChannels);
3568                    notify->setInt32("sample-rate", params.nSampleRate);
3569                    break;
3570                }
3571
3572                case OMX_AUDIO_CodingAndroidEAC3:
3573                {
3574                    OMX_AUDIO_PARAM_ANDROID_EAC3TYPE params;
3575                    InitOMXParams(&params);
3576                    params.nPortIndex = portIndex;
3577
3578                    CHECK_EQ((status_t)OK, mOMX->getParameter(
3579                            mNode,
3580                            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
3581                            &params,
3582                            sizeof(params)));
3583
3584                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_EAC3);
3585                    notify->setInt32("channel-count", params.nChannels);
3586                    notify->setInt32("sample-rate", params.nSampleRate);
3587                    break;
3588                }
3589
3590                case OMX_AUDIO_CodingAndroidOPUS:
3591                {
3592                    OMX_AUDIO_PARAM_ANDROID_OPUSTYPE params;
3593                    InitOMXParams(&params);
3594                    params.nPortIndex = portIndex;
3595
3596                    CHECK_EQ((status_t)OK, mOMX->getParameter(
3597                            mNode,
3598                            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus,
3599                            &params,
3600                            sizeof(params)));
3601
3602                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_OPUS);
3603                    notify->setInt32("channel-count", params.nChannels);
3604                    notify->setInt32("sample-rate", params.nSampleRate);
3605                    break;
3606                }
3607
3608                case OMX_AUDIO_CodingG711:
3609                {
3610                    OMX_AUDIO_PARAM_PCMMODETYPE params;
3611                    InitOMXParams(&params);
3612                    params.nPortIndex = portIndex;
3613
3614                    CHECK_EQ((status_t)OK, mOMX->getParameter(
3615                            mNode,
3616                            (OMX_INDEXTYPE)OMX_IndexParamAudioPcm,
3617                            &params,
3618                            sizeof(params)));
3619
3620                    const char *mime = NULL;
3621                    if (params.ePCMMode == OMX_AUDIO_PCMModeMULaw) {
3622                        mime = MEDIA_MIMETYPE_AUDIO_G711_MLAW;
3623                    } else if (params.ePCMMode == OMX_AUDIO_PCMModeALaw) {
3624                        mime = MEDIA_MIMETYPE_AUDIO_G711_ALAW;
3625                    } else { // params.ePCMMode == OMX_AUDIO_PCMModeLinear
3626                        mime = MEDIA_MIMETYPE_AUDIO_RAW;
3627                    }
3628                    notify->setString("mime", mime);
3629                    notify->setInt32("channel-count", params.nChannels);
3630                    notify->setInt32("sample-rate", params.nSamplingRate);
3631                    break;
3632                }
3633
3634                default:
3635                    ALOGE("UNKNOWN AUDIO CODING: %d\n", audioDef->eEncoding);
3636                    TRESPASS();
3637            }
3638            break;
3639        }
3640
3641        default:
3642            TRESPASS();
3643    }
3644
3645    return OK;
3646}
3647
3648void ACodec::sendFormatChange(const sp<AMessage> &reply) {
3649    sp<AMessage> notify = mBaseOutputFormat->dup();
3650    notify->setInt32("what", kWhatOutputFormatChanged);
3651
3652    CHECK_EQ(getPortFormat(kPortIndexOutput, notify), (status_t)OK);
3653
3654    AString mime;
3655    CHECK(notify->findString("mime", &mime));
3656
3657    int32_t left, top, right, bottom;
3658    if (mime == MEDIA_MIMETYPE_VIDEO_RAW &&
3659        mNativeWindow != NULL &&
3660        notify->findRect("crop", &left, &top, &right, &bottom)) {
3661        // notify renderer of the crop change
3662        // NOTE: native window uses extended right-bottom coordinate
3663        reply->setRect("crop", left, top, right + 1, bottom + 1);
3664    } else if (mime == MEDIA_MIMETYPE_AUDIO_RAW &&
3665               (mEncoderDelay || mEncoderPadding)) {
3666        int32_t channelCount;
3667        CHECK(notify->findInt32("channel-count", &channelCount));
3668        size_t frameSize = channelCount * sizeof(int16_t);
3669        if (mSkipCutBuffer != NULL) {
3670            size_t prevbufsize = mSkipCutBuffer->size();
3671            if (prevbufsize != 0) {
3672                ALOGW("Replacing SkipCutBuffer holding %d "
3673                      "bytes",
3674                      prevbufsize);
3675            }
3676        }
3677        mSkipCutBuffer = new SkipCutBuffer(
3678                mEncoderDelay * frameSize,
3679                mEncoderPadding * frameSize);
3680    }
3681
3682    notify->post();
3683
3684    mSentFormat = true;
3685}
3686
3687void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) {
3688    sp<AMessage> notify = mNotify->dup();
3689    notify->setInt32("what", CodecBase::kWhatError);
3690    ALOGE("signalError(omxError %#x, internalError %d)", error, internalError);
3691
3692    if (internalError == UNKNOWN_ERROR) { // find better error code
3693        const status_t omxStatus = statusFromOMXError(error);
3694        if (omxStatus != 0) {
3695            internalError = omxStatus;
3696        } else {
3697            ALOGW("Invalid OMX error %#x", error);
3698        }
3699    }
3700    notify->setInt32("err", internalError);
3701    notify->setInt32("actionCode", ACTION_CODE_FATAL); // could translate from OMX error.
3702    notify->post();
3703}
3704
3705status_t ACodec::pushBlankBuffersToNativeWindow() {
3706    status_t err = NO_ERROR;
3707    ANativeWindowBuffer* anb = NULL;
3708    int numBufs = 0;
3709    int minUndequeuedBufs = 0;
3710
3711    // We need to reconnect to the ANativeWindow as a CPU client to ensure that
3712    // no frames get dropped by SurfaceFlinger assuming that these are video
3713    // frames.
3714    err = native_window_api_disconnect(mNativeWindow.get(),
3715            NATIVE_WINDOW_API_MEDIA);
3716    if (err != NO_ERROR) {
3717        ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
3718                strerror(-err), -err);
3719        return err;
3720    }
3721
3722    err = native_window_api_connect(mNativeWindow.get(),
3723            NATIVE_WINDOW_API_CPU);
3724    if (err != NO_ERROR) {
3725        ALOGE("error pushing blank frames: api_connect failed: %s (%d)",
3726                strerror(-err), -err);
3727        return err;
3728    }
3729
3730    err = native_window_set_buffers_geometry(mNativeWindow.get(), 1, 1,
3731            HAL_PIXEL_FORMAT_RGBX_8888);
3732    if (err != NO_ERROR) {
3733        ALOGE("error pushing blank frames: set_buffers_geometry failed: %s (%d)",
3734                strerror(-err), -err);
3735        goto error;
3736    }
3737
3738    err = native_window_set_scaling_mode(mNativeWindow.get(),
3739                NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
3740    if (err != NO_ERROR) {
3741        ALOGE("error pushing blank_frames: set_scaling_mode failed: %s (%d)",
3742              strerror(-err), -err);
3743        goto error;
3744    }
3745
3746    err = native_window_set_usage(mNativeWindow.get(),
3747            GRALLOC_USAGE_SW_WRITE_OFTEN);
3748    if (err != NO_ERROR) {
3749        ALOGE("error pushing blank frames: set_usage failed: %s (%d)",
3750                strerror(-err), -err);
3751        goto error;
3752    }
3753
3754    err = mNativeWindow->query(mNativeWindow.get(),
3755            NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs);
3756    if (err != NO_ERROR) {
3757        ALOGE("error pushing blank frames: MIN_UNDEQUEUED_BUFFERS query "
3758                "failed: %s (%d)", strerror(-err), -err);
3759        goto error;
3760    }
3761
3762    numBufs = minUndequeuedBufs + 1;
3763    err = native_window_set_buffer_count(mNativeWindow.get(), numBufs);
3764    if (err != NO_ERROR) {
3765        ALOGE("error pushing blank frames: set_buffer_count failed: %s (%d)",
3766                strerror(-err), -err);
3767        goto error;
3768    }
3769
3770    // We  push numBufs + 1 buffers to ensure that we've drawn into the same
3771    // buffer twice.  This should guarantee that the buffer has been displayed
3772    // on the screen and then been replaced, so an previous video frames are
3773    // guaranteed NOT to be currently displayed.
3774    for (int i = 0; i < numBufs + 1; i++) {
3775        err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &anb);
3776        if (err != NO_ERROR) {
3777            ALOGE("error pushing blank frames: dequeueBuffer failed: %s (%d)",
3778                    strerror(-err), -err);
3779            goto error;
3780        }
3781
3782        sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
3783
3784        // Fill the buffer with the a 1x1 checkerboard pattern ;)
3785        uint32_t* img = NULL;
3786        err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
3787        if (err != NO_ERROR) {
3788            ALOGE("error pushing blank frames: lock failed: %s (%d)",
3789                    strerror(-err), -err);
3790            goto error;
3791        }
3792
3793        *img = 0;
3794
3795        err = buf->unlock();
3796        if (err != NO_ERROR) {
3797            ALOGE("error pushing blank frames: unlock failed: %s (%d)",
3798                    strerror(-err), -err);
3799            goto error;
3800        }
3801
3802        err = mNativeWindow->queueBuffer(mNativeWindow.get(),
3803                buf->getNativeBuffer(), -1);
3804        if (err != NO_ERROR) {
3805            ALOGE("error pushing blank frames: queueBuffer failed: %s (%d)",
3806                    strerror(-err), -err);
3807            goto error;
3808        }
3809
3810        anb = NULL;
3811    }
3812
3813error:
3814
3815    if (err != NO_ERROR) {
3816        // Clean up after an error.
3817        if (anb != NULL) {
3818            mNativeWindow->cancelBuffer(mNativeWindow.get(), anb, -1);
3819        }
3820
3821        native_window_api_disconnect(mNativeWindow.get(),
3822                NATIVE_WINDOW_API_CPU);
3823        native_window_api_connect(mNativeWindow.get(),
3824                NATIVE_WINDOW_API_MEDIA);
3825
3826        return err;
3827    } else {
3828        // Clean up after success.
3829        err = native_window_api_disconnect(mNativeWindow.get(),
3830                NATIVE_WINDOW_API_CPU);
3831        if (err != NO_ERROR) {
3832            ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
3833                    strerror(-err), -err);
3834            return err;
3835        }
3836
3837        err = native_window_api_connect(mNativeWindow.get(),
3838                NATIVE_WINDOW_API_MEDIA);
3839        if (err != NO_ERROR) {
3840            ALOGE("error pushing blank frames: api_connect failed: %s (%d)",
3841                    strerror(-err), -err);
3842            return err;
3843        }
3844
3845        return NO_ERROR;
3846    }
3847}
3848
3849////////////////////////////////////////////////////////////////////////////////
3850
3851ACodec::PortDescription::PortDescription() {
3852}
3853
3854status_t ACodec::requestIDRFrame() {
3855    if (!mIsEncoder) {
3856        return ERROR_UNSUPPORTED;
3857    }
3858
3859    OMX_CONFIG_INTRAREFRESHVOPTYPE params;
3860    InitOMXParams(&params);
3861
3862    params.nPortIndex = kPortIndexOutput;
3863    params.IntraRefreshVOP = OMX_TRUE;
3864
3865    return mOMX->setConfig(
3866            mNode,
3867            OMX_IndexConfigVideoIntraVOPRefresh,
3868            &params,
3869            sizeof(params));
3870}
3871
3872void ACodec::PortDescription::addBuffer(
3873        IOMX::buffer_id id, const sp<ABuffer> &buffer) {
3874    mBufferIDs.push_back(id);
3875    mBuffers.push_back(buffer);
3876}
3877
3878size_t ACodec::PortDescription::countBuffers() {
3879    return mBufferIDs.size();
3880}
3881
3882IOMX::buffer_id ACodec::PortDescription::bufferIDAt(size_t index) const {
3883    return mBufferIDs.itemAt(index);
3884}
3885
3886sp<ABuffer> ACodec::PortDescription::bufferAt(size_t index) const {
3887    return mBuffers.itemAt(index);
3888}
3889
3890////////////////////////////////////////////////////////////////////////////////
3891
3892ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
3893    : AState(parentState),
3894      mCodec(codec) {
3895}
3896
3897ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(
3898        OMX_U32 /* portIndex */) {
3899    return KEEP_BUFFERS;
3900}
3901
3902bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) {
3903    switch (msg->what()) {
3904        case kWhatInputBufferFilled:
3905        {
3906            onInputBufferFilled(msg);
3907            break;
3908        }
3909
3910        case kWhatOutputBufferDrained:
3911        {
3912            onOutputBufferDrained(msg);
3913            break;
3914        }
3915
3916        case ACodec::kWhatOMXMessage:
3917        {
3918            return onOMXMessage(msg);
3919        }
3920
3921        case ACodec::kWhatCreateInputSurface:
3922        case ACodec::kWhatSignalEndOfInputStream:
3923        {
3924            // This may result in an app illegal state exception.
3925            ALOGE("Message 0x%x was not handled", msg->what());
3926            mCodec->signalError(OMX_ErrorUndefined, INVALID_OPERATION);
3927            return true;
3928        }
3929
3930        case ACodec::kWhatOMXDied:
3931        {
3932            // This will result in kFlagSawMediaServerDie handling in MediaCodec.
3933            ALOGE("OMX/mediaserver died, signalling error!");
3934            mCodec->signalError(OMX_ErrorResourcesLost, DEAD_OBJECT);
3935            break;
3936        }
3937
3938        case ACodec::kWhatReleaseCodecInstance:
3939        {
3940            ALOGI("[%s] forcing the release of codec",
3941                    mCodec->mComponentName.c_str());
3942            status_t err = mCodec->mOMX->freeNode(mCodec->mNode);
3943            ALOGE_IF("[%s] failed to release codec instance: err=%d",
3944                       mCodec->mComponentName.c_str(), err);
3945            sp<AMessage> notify = mCodec->mNotify->dup();
3946            notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
3947            notify->post();
3948            break;
3949        }
3950
3951        default:
3952            return false;
3953    }
3954
3955    return true;
3956}
3957
3958bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) {
3959    int32_t type;
3960    CHECK(msg->findInt32("type", &type));
3961
3962    // there is a possibility that this is an outstanding message for a
3963    // codec that we have already destroyed
3964    if (mCodec->mNode == NULL) {
3965        ALOGI("ignoring message as already freed component: %s",
3966                msg->debugString().c_str());
3967        return true;
3968    }
3969
3970    IOMX::node_id nodeID;
3971    CHECK(msg->findInt32("node", (int32_t*)&nodeID));
3972    CHECK_EQ(nodeID, mCodec->mNode);
3973
3974    switch (type) {
3975        case omx_message::EVENT:
3976        {
3977            int32_t event, data1, data2;
3978            CHECK(msg->findInt32("event", &event));
3979            CHECK(msg->findInt32("data1", &data1));
3980            CHECK(msg->findInt32("data2", &data2));
3981
3982            if (event == OMX_EventCmdComplete
3983                    && data1 == OMX_CommandFlush
3984                    && data2 == (int32_t)OMX_ALL) {
3985                // Use of this notification is not consistent across
3986                // implementations. We'll drop this notification and rely
3987                // on flush-complete notifications on the individual port
3988                // indices instead.
3989
3990                return true;
3991            }
3992
3993            return onOMXEvent(
3994                    static_cast<OMX_EVENTTYPE>(event),
3995                    static_cast<OMX_U32>(data1),
3996                    static_cast<OMX_U32>(data2));
3997        }
3998
3999        case omx_message::EMPTY_BUFFER_DONE:
4000        {
4001            IOMX::buffer_id bufferID;
4002            CHECK(msg->findInt32("buffer", (int32_t*)&bufferID));
4003
4004            return onOMXEmptyBufferDone(bufferID);
4005        }
4006
4007        case omx_message::FILL_BUFFER_DONE:
4008        {
4009            IOMX::buffer_id bufferID;
4010            CHECK(msg->findInt32("buffer", (int32_t*)&bufferID));
4011
4012            int32_t rangeOffset, rangeLength, flags;
4013            int64_t timeUs;
4014
4015            CHECK(msg->findInt32("range_offset", &rangeOffset));
4016            CHECK(msg->findInt32("range_length", &rangeLength));
4017            CHECK(msg->findInt32("flags", &flags));
4018            CHECK(msg->findInt64("timestamp", &timeUs));
4019
4020            return onOMXFillBufferDone(
4021                    bufferID,
4022                    (size_t)rangeOffset, (size_t)rangeLength,
4023                    (OMX_U32)flags,
4024                    timeUs);
4025        }
4026
4027        default:
4028            TRESPASS();
4029            break;
4030    }
4031}
4032
4033bool ACodec::BaseState::onOMXEvent(
4034        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
4035    if (event != OMX_EventError) {
4036        ALOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)",
4037             mCodec->mComponentName.c_str(), event, data1, data2);
4038
4039        return false;
4040    }
4041
4042    ALOGE("[%s] ERROR(0x%08lx)", mCodec->mComponentName.c_str(), data1);
4043
4044    // verify OMX component sends back an error we expect.
4045    OMX_ERRORTYPE omxError = (OMX_ERRORTYPE)data1;
4046    if (!isOMXError(omxError)) {
4047        ALOGW("Invalid OMX error %#x", omxError);
4048        omxError = OMX_ErrorUndefined;
4049    }
4050    mCodec->signalError(omxError);
4051
4052    return true;
4053}
4054
4055bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) {
4056    ALOGV("[%s] onOMXEmptyBufferDone %p",
4057         mCodec->mComponentName.c_str(), bufferID);
4058
4059    BufferInfo *info =
4060        mCodec->findBufferByID(kPortIndexInput, bufferID);
4061
4062    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
4063    info->mStatus = BufferInfo::OWNED_BY_US;
4064
4065    // We're in "store-metadata-in-buffers" mode, the underlying
4066    // OMX component had access to data that's implicitly refcounted
4067    // by this "MediaBuffer" object. Now that the OMX component has
4068    // told us that it's done with the input buffer, we can decrement
4069    // the mediaBuffer's reference count.
4070    info->mData->setMediaBufferBase(NULL);
4071
4072    PortMode mode = getPortMode(kPortIndexInput);
4073
4074    switch (mode) {
4075        case KEEP_BUFFERS:
4076            break;
4077
4078        case RESUBMIT_BUFFERS:
4079            postFillThisBuffer(info);
4080            break;
4081
4082        default:
4083        {
4084            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
4085            TRESPASS();  // Not currently used
4086            break;
4087        }
4088    }
4089
4090    return true;
4091}
4092
4093void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) {
4094    if (mCodec->mPortEOS[kPortIndexInput]) {
4095        return;
4096    }
4097
4098    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
4099
4100    sp<AMessage> notify = mCodec->mNotify->dup();
4101    notify->setInt32("what", CodecBase::kWhatFillThisBuffer);
4102    notify->setInt32("buffer-id", info->mBufferID);
4103
4104    info->mData->meta()->clear();
4105    notify->setBuffer("buffer", info->mData);
4106
4107    sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id());
4108    reply->setInt32("buffer-id", info->mBufferID);
4109
4110    notify->setMessage("reply", reply);
4111
4112    notify->post();
4113
4114    info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
4115}
4116
4117void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
4118    IOMX::buffer_id bufferID;
4119    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
4120    sp<ABuffer> buffer;
4121    int32_t err = OK;
4122    bool eos = false;
4123    PortMode mode = getPortMode(kPortIndexInput);
4124
4125    if (!msg->findBuffer("buffer", &buffer)) {
4126        /* these are unfilled buffers returned by client */
4127        CHECK(msg->findInt32("err", &err));
4128
4129        if (err == OK) {
4130            /* buffers with no errors are returned on MediaCodec.flush */
4131            mode = KEEP_BUFFERS;
4132        } else {
4133            ALOGV("[%s] saw error %d instead of an input buffer",
4134                 mCodec->mComponentName.c_str(), err);
4135            eos = true;
4136        }
4137
4138        buffer.clear();
4139    }
4140
4141    int32_t tmp;
4142    if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) {
4143        eos = true;
4144        err = ERROR_END_OF_STREAM;
4145    }
4146
4147    BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
4148    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM);
4149
4150    info->mStatus = BufferInfo::OWNED_BY_US;
4151
4152    switch (mode) {
4153        case KEEP_BUFFERS:
4154        {
4155            if (eos) {
4156                if (!mCodec->mPortEOS[kPortIndexInput]) {
4157                    mCodec->mPortEOS[kPortIndexInput] = true;
4158                    mCodec->mInputEOSResult = err;
4159                }
4160            }
4161            break;
4162        }
4163
4164        case RESUBMIT_BUFFERS:
4165        {
4166            if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) {
4167                int64_t timeUs;
4168                CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
4169
4170                OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
4171
4172                int32_t isCSD;
4173                if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) {
4174                    flags |= OMX_BUFFERFLAG_CODECCONFIG;
4175                }
4176
4177                if (eos) {
4178                    flags |= OMX_BUFFERFLAG_EOS;
4179                }
4180
4181                if (buffer != info->mData) {
4182                    ALOGV("[%s] Needs to copy input data for buffer %p. (%p != %p)",
4183                         mCodec->mComponentName.c_str(),
4184                         bufferID,
4185                         buffer.get(), info->mData.get());
4186
4187                    CHECK_LE(buffer->size(), info->mData->capacity());
4188                    memcpy(info->mData->data(), buffer->data(), buffer->size());
4189                }
4190
4191                if (flags & OMX_BUFFERFLAG_CODECCONFIG) {
4192                    ALOGV("[%s] calling emptyBuffer %p w/ codec specific data",
4193                         mCodec->mComponentName.c_str(), bufferID);
4194                } else if (flags & OMX_BUFFERFLAG_EOS) {
4195                    ALOGV("[%s] calling emptyBuffer %p w/ EOS",
4196                         mCodec->mComponentName.c_str(), bufferID);
4197                } else {
4198#if TRACK_BUFFER_TIMING
4199                    ALOGI("[%s] calling emptyBuffer %p w/ time %lld us",
4200                         mCodec->mComponentName.c_str(), bufferID, timeUs);
4201#else
4202                    ALOGV("[%s] calling emptyBuffer %p w/ time %lld us",
4203                         mCodec->mComponentName.c_str(), bufferID, timeUs);
4204#endif
4205                }
4206
4207#if TRACK_BUFFER_TIMING
4208                ACodec::BufferStats stats;
4209                stats.mEmptyBufferTimeUs = ALooper::GetNowUs();
4210                stats.mFillBufferDoneTimeUs = -1ll;
4211                mCodec->mBufferStats.add(timeUs, stats);
4212#endif
4213
4214                if (mCodec->mStoreMetaDataInOutputBuffers) {
4215                    // try to submit an output buffer for each input buffer
4216                    PortMode outputMode = getPortMode(kPortIndexOutput);
4217
4218                    ALOGV("MetaDataBuffersToSubmit=%u portMode=%s",
4219                            mCodec->mMetaDataBuffersToSubmit,
4220                            (outputMode == FREE_BUFFERS ? "FREE" :
4221                             outputMode == KEEP_BUFFERS ? "KEEP" : "RESUBMIT"));
4222                    if (outputMode == RESUBMIT_BUFFERS) {
4223                        mCodec->submitOutputMetaDataBuffer();
4224                    }
4225                }
4226
4227                CHECK_EQ(mCodec->mOMX->emptyBuffer(
4228                            mCodec->mNode,
4229                            bufferID,
4230                            0,
4231                            buffer->size(),
4232                            flags,
4233                            timeUs),
4234                         (status_t)OK);
4235
4236                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4237
4238                if (!eos) {
4239                    getMoreInputDataIfPossible();
4240                } else {
4241                    ALOGV("[%s] Signalled EOS on the input port",
4242                         mCodec->mComponentName.c_str());
4243
4244                    mCodec->mPortEOS[kPortIndexInput] = true;
4245                    mCodec->mInputEOSResult = err;
4246                }
4247            } else if (!mCodec->mPortEOS[kPortIndexInput]) {
4248                if (err != ERROR_END_OF_STREAM) {
4249                    ALOGV("[%s] Signalling EOS on the input port "
4250                         "due to error %d",
4251                         mCodec->mComponentName.c_str(), err);
4252                } else {
4253                    ALOGV("[%s] Signalling EOS on the input port",
4254                         mCodec->mComponentName.c_str());
4255                }
4256
4257                ALOGV("[%s] calling emptyBuffer %p signalling EOS",
4258                     mCodec->mComponentName.c_str(), bufferID);
4259
4260                CHECK_EQ(mCodec->mOMX->emptyBuffer(
4261                            mCodec->mNode,
4262                            bufferID,
4263                            0,
4264                            0,
4265                            OMX_BUFFERFLAG_EOS,
4266                            0),
4267                         (status_t)OK);
4268
4269                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4270
4271                mCodec->mPortEOS[kPortIndexInput] = true;
4272                mCodec->mInputEOSResult = err;
4273            }
4274            break;
4275        }
4276
4277        default:
4278            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
4279            break;
4280    }
4281}
4282
4283void ACodec::BaseState::getMoreInputDataIfPossible() {
4284    if (mCodec->mPortEOS[kPortIndexInput]) {
4285        return;
4286    }
4287
4288    BufferInfo *eligible = NULL;
4289
4290    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
4291        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
4292
4293#if 0
4294        if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) {
4295            // There's already a "read" pending.
4296            return;
4297        }
4298#endif
4299
4300        if (info->mStatus == BufferInfo::OWNED_BY_US) {
4301            eligible = info;
4302        }
4303    }
4304
4305    if (eligible == NULL) {
4306        return;
4307    }
4308
4309    postFillThisBuffer(eligible);
4310}
4311
4312bool ACodec::BaseState::onOMXFillBufferDone(
4313        IOMX::buffer_id bufferID,
4314        size_t rangeOffset, size_t rangeLength,
4315        OMX_U32 flags,
4316        int64_t timeUs) {
4317    ALOGV("[%s] onOMXFillBufferDone %u time %" PRId64 " us, flags = 0x%08x",
4318         mCodec->mComponentName.c_str(), bufferID, timeUs, flags);
4319
4320    ssize_t index;
4321
4322#if TRACK_BUFFER_TIMING
4323    index = mCodec->mBufferStats.indexOfKey(timeUs);
4324    if (index >= 0) {
4325        ACodec::BufferStats *stats = &mCodec->mBufferStats.editValueAt(index);
4326        stats->mFillBufferDoneTimeUs = ALooper::GetNowUs();
4327
4328        ALOGI("frame PTS %lld: %lld",
4329                timeUs,
4330                stats->mFillBufferDoneTimeUs - stats->mEmptyBufferTimeUs);
4331
4332        mCodec->mBufferStats.removeItemsAt(index);
4333        stats = NULL;
4334    }
4335#endif
4336
4337    BufferInfo *info =
4338        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
4339
4340    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
4341
4342    info->mDequeuedAt = ++mCodec->mDequeueCounter;
4343    info->mStatus = BufferInfo::OWNED_BY_US;
4344
4345    PortMode mode = getPortMode(kPortIndexOutput);
4346
4347    switch (mode) {
4348        case KEEP_BUFFERS:
4349            break;
4350
4351        case RESUBMIT_BUFFERS:
4352        {
4353            if (rangeLength == 0 && (!(flags & OMX_BUFFERFLAG_EOS)
4354                    || mCodec->mPortEOS[kPortIndexOutput])) {
4355                ALOGV("[%s] calling fillBuffer %u",
4356                     mCodec->mComponentName.c_str(), info->mBufferID);
4357
4358                CHECK_EQ(mCodec->mOMX->fillBuffer(
4359                            mCodec->mNode, info->mBufferID),
4360                         (status_t)OK);
4361
4362                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4363                break;
4364            }
4365
4366            sp<AMessage> reply =
4367                new AMessage(kWhatOutputBufferDrained, mCodec->id());
4368
4369            if (!mCodec->mSentFormat && rangeLength > 0) {
4370                mCodec->sendFormatChange(reply);
4371            }
4372
4373            if (mCodec->mUseMetadataOnEncoderOutput) {
4374                native_handle_t* handle =
4375                        *(native_handle_t**)(info->mData->data() + 4);
4376                info->mData->meta()->setPointer("handle", handle);
4377                info->mData->meta()->setInt32("rangeOffset", rangeOffset);
4378                info->mData->meta()->setInt32("rangeLength", rangeLength);
4379            } else {
4380                info->mData->setRange(rangeOffset, rangeLength);
4381            }
4382#if 0
4383            if (mCodec->mNativeWindow == NULL) {
4384                if (IsIDR(info->mData)) {
4385                    ALOGI("IDR frame");
4386                }
4387            }
4388#endif
4389
4390            if (mCodec->mSkipCutBuffer != NULL) {
4391                mCodec->mSkipCutBuffer->submit(info->mData);
4392            }
4393            info->mData->meta()->setInt64("timeUs", timeUs);
4394
4395            sp<AMessage> notify = mCodec->mNotify->dup();
4396            notify->setInt32("what", CodecBase::kWhatDrainThisBuffer);
4397            notify->setInt32("buffer-id", info->mBufferID);
4398            notify->setBuffer("buffer", info->mData);
4399            notify->setInt32("flags", flags);
4400
4401            reply->setInt32("buffer-id", info->mBufferID);
4402
4403            notify->setMessage("reply", reply);
4404
4405            notify->post();
4406
4407            info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;
4408
4409            if (flags & OMX_BUFFERFLAG_EOS) {
4410                ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str());
4411
4412                sp<AMessage> notify = mCodec->mNotify->dup();
4413                notify->setInt32("what", CodecBase::kWhatEOS);
4414                notify->setInt32("err", mCodec->mInputEOSResult);
4415                notify->post();
4416
4417                mCodec->mPortEOS[kPortIndexOutput] = true;
4418            }
4419            break;
4420        }
4421
4422        default:
4423        {
4424            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
4425
4426            CHECK_EQ((status_t)OK,
4427                     mCodec->freeBuffer(kPortIndexOutput, index));
4428            break;
4429        }
4430    }
4431
4432    return true;
4433}
4434
4435void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
4436    IOMX::buffer_id bufferID;
4437    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
4438    ssize_t index;
4439    BufferInfo *info =
4440        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
4441    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
4442
4443    android_native_rect_t crop;
4444    if (msg->findRect("crop",
4445            &crop.left, &crop.top, &crop.right, &crop.bottom)) {
4446        CHECK_EQ(0, native_window_set_crop(
4447                mCodec->mNativeWindow.get(), &crop));
4448    }
4449
4450    int32_t render;
4451    if (mCodec->mNativeWindow != NULL
4452            && msg->findInt32("render", &render) && render != 0
4453            && info->mData != NULL && info->mData->size() != 0) {
4454        ATRACE_NAME("render");
4455        // The client wants this buffer to be rendered.
4456
4457        int64_t timestampNs = 0;
4458        if (!msg->findInt64("timestampNs", &timestampNs)) {
4459            // TODO: it seems like we should use the timestamp
4460            // in the (media)buffer as it potentially came from
4461            // an input surface, but we did not propagate it prior to
4462            // API 20.  Perhaps check for target SDK version.
4463#if 0
4464            if (info->mData->meta()->findInt64("timeUs", &timestampNs)) {
4465                ALOGV("using buffer PTS of %" PRId64, timestampNs);
4466                timestampNs *= 1000;
4467            }
4468#endif
4469        }
4470
4471        status_t err;
4472        err = native_window_set_buffers_timestamp(mCodec->mNativeWindow.get(), timestampNs);
4473        if (err != OK) {
4474            ALOGW("failed to set buffer timestamp: %d", err);
4475        }
4476
4477        if ((err = mCodec->mNativeWindow->queueBuffer(
4478                    mCodec->mNativeWindow.get(),
4479                    info->mGraphicBuffer.get(), -1)) == OK) {
4480            info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
4481        } else {
4482            mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
4483            info->mStatus = BufferInfo::OWNED_BY_US;
4484        }
4485    } else {
4486        if (mCodec->mNativeWindow != NULL &&
4487            (info->mData == NULL || info->mData->size() != 0)) {
4488            ATRACE_NAME("frame-drop");
4489        }
4490        info->mStatus = BufferInfo::OWNED_BY_US;
4491    }
4492
4493    PortMode mode = getPortMode(kPortIndexOutput);
4494
4495    switch (mode) {
4496        case KEEP_BUFFERS:
4497        {
4498            // XXX fishy, revisit!!! What about the FREE_BUFFERS case below?
4499
4500            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
4501                // We cannot resubmit the buffer we just rendered, dequeue
4502                // the spare instead.
4503
4504                info = mCodec->dequeueBufferFromNativeWindow();
4505            }
4506            break;
4507        }
4508
4509        case RESUBMIT_BUFFERS:
4510        {
4511            if (!mCodec->mPortEOS[kPortIndexOutput]) {
4512                if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
4513                    // We cannot resubmit the buffer we just rendered, dequeue
4514                    // the spare instead.
4515
4516                    info = mCodec->dequeueBufferFromNativeWindow();
4517                }
4518
4519                if (info != NULL) {
4520                    ALOGV("[%s] calling fillBuffer %u",
4521                         mCodec->mComponentName.c_str(), info->mBufferID);
4522
4523                    CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
4524                             (status_t)OK);
4525
4526                    info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4527                }
4528            }
4529            break;
4530        }
4531
4532        default:
4533        {
4534            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
4535
4536            CHECK_EQ((status_t)OK,
4537                     mCodec->freeBuffer(kPortIndexOutput, index));
4538            break;
4539        }
4540    }
4541}
4542
4543////////////////////////////////////////////////////////////////////////////////
4544
4545ACodec::UninitializedState::UninitializedState(ACodec *codec)
4546    : BaseState(codec) {
4547}
4548
4549void ACodec::UninitializedState::stateEntered() {
4550    ALOGV("Now uninitialized");
4551
4552    if (mDeathNotifier != NULL) {
4553        IInterface::asBinder(mCodec->mOMX)->unlinkToDeath(mDeathNotifier);
4554        mDeathNotifier.clear();
4555    }
4556
4557    mCodec->mNativeWindow.clear();
4558    mCodec->mNode = NULL;
4559    mCodec->mOMX.clear();
4560    mCodec->mQuirks = 0;
4561    mCodec->mFlags = 0;
4562    mCodec->mUseMetadataOnEncoderOutput = 0;
4563    mCodec->mComponentName.clear();
4564}
4565
4566bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
4567    bool handled = false;
4568
4569    switch (msg->what()) {
4570        case ACodec::kWhatSetup:
4571        {
4572            onSetup(msg);
4573
4574            handled = true;
4575            break;
4576        }
4577
4578        case ACodec::kWhatAllocateComponent:
4579        {
4580            onAllocateComponent(msg);
4581            handled = true;
4582            break;
4583        }
4584
4585        case ACodec::kWhatShutdown:
4586        {
4587            int32_t keepComponentAllocated;
4588            CHECK(msg->findInt32(
4589                        "keepComponentAllocated", &keepComponentAllocated));
4590            ALOGW_IF(keepComponentAllocated,
4591                     "cannot keep component allocated on shutdown in Uninitialized state");
4592
4593            sp<AMessage> notify = mCodec->mNotify->dup();
4594            notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
4595            notify->post();
4596
4597            handled = true;
4598            break;
4599        }
4600
4601        case ACodec::kWhatFlush:
4602        {
4603            sp<AMessage> notify = mCodec->mNotify->dup();
4604            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
4605            notify->post();
4606
4607            handled = true;
4608            break;
4609        }
4610
4611        case ACodec::kWhatReleaseCodecInstance:
4612        {
4613            // nothing to do, as we have already signaled shutdown
4614            handled = true;
4615            break;
4616        }
4617
4618        default:
4619            return BaseState::onMessageReceived(msg);
4620    }
4621
4622    return handled;
4623}
4624
4625void ACodec::UninitializedState::onSetup(
4626        const sp<AMessage> &msg) {
4627    if (onAllocateComponent(msg)
4628            && mCodec->mLoadedState->onConfigureComponent(msg)) {
4629        mCodec->mLoadedState->onStart();
4630    }
4631}
4632
4633bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
4634    ALOGV("onAllocateComponent");
4635
4636    CHECK(mCodec->mNode == NULL);
4637
4638    OMXClient client;
4639    CHECK_EQ(client.connect(), (status_t)OK);
4640
4641    sp<IOMX> omx = client.interface();
4642
4643    sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec->id());
4644
4645    mDeathNotifier = new DeathNotifier(notify);
4646    if (IInterface::asBinder(omx)->linkToDeath(mDeathNotifier) != OK) {
4647        // This was a local binder, if it dies so do we, we won't care
4648        // about any notifications in the afterlife.
4649        mDeathNotifier.clear();
4650    }
4651
4652    Vector<OMXCodec::CodecNameAndQuirks> matchingCodecs;
4653
4654    AString mime;
4655
4656    AString componentName;
4657    uint32_t quirks = 0;
4658    int32_t encoder = false;
4659    if (msg->findString("componentName", &componentName)) {
4660        ssize_t index = matchingCodecs.add();
4661        OMXCodec::CodecNameAndQuirks *entry = &matchingCodecs.editItemAt(index);
4662        entry->mName = String8(componentName.c_str());
4663
4664        if (!OMXCodec::findCodecQuirks(
4665                    componentName.c_str(), &entry->mQuirks)) {
4666            entry->mQuirks = 0;
4667        }
4668    } else {
4669        CHECK(msg->findString("mime", &mime));
4670
4671        if (!msg->findInt32("encoder", &encoder)) {
4672            encoder = false;
4673        }
4674
4675        OMXCodec::findMatchingCodecs(
4676                mime.c_str(),
4677                encoder, // createEncoder
4678                NULL,  // matchComponentName
4679                0,     // flags
4680                &matchingCodecs);
4681    }
4682
4683    sp<CodecObserver> observer = new CodecObserver;
4684    IOMX::node_id node = NULL;
4685
4686    for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
4687            ++matchIndex) {
4688        componentName = matchingCodecs.itemAt(matchIndex).mName.string();
4689        quirks = matchingCodecs.itemAt(matchIndex).mQuirks;
4690
4691        pid_t tid = gettid();
4692        int prevPriority = androidGetThreadPriority(tid);
4693        androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
4694        status_t err = omx->allocateNode(componentName.c_str(), observer, &node);
4695        androidSetThreadPriority(tid, prevPriority);
4696
4697        if (err == OK) {
4698            break;
4699        } else {
4700            ALOGW("Allocating component '%s' failed, try next one.", componentName.c_str());
4701        }
4702
4703        node = NULL;
4704    }
4705
4706    if (node == NULL) {
4707        if (!mime.empty()) {
4708            ALOGE("Unable to instantiate a %scoder for type '%s'.",
4709                    encoder ? "en" : "de", mime.c_str());
4710        } else {
4711            ALOGE("Unable to instantiate codec '%s'.", componentName.c_str());
4712        }
4713
4714        mCodec->signalError(OMX_ErrorComponentNotFound);
4715        return false;
4716    }
4717
4718    notify = new AMessage(kWhatOMXMessage, mCodec->id());
4719    observer->setNotificationMessage(notify);
4720
4721    mCodec->mComponentName = componentName;
4722    mCodec->mFlags = 0;
4723
4724    if (componentName.endsWith(".secure")) {
4725        mCodec->mFlags |= kFlagIsSecure;
4726        mCodec->mFlags |= kFlagIsGrallocUsageProtected;
4727        mCodec->mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
4728    }
4729
4730    mCodec->mQuirks = quirks;
4731    mCodec->mOMX = omx;
4732    mCodec->mNode = node;
4733
4734    {
4735        sp<AMessage> notify = mCodec->mNotify->dup();
4736        notify->setInt32("what", CodecBase::kWhatComponentAllocated);
4737        notify->setString("componentName", mCodec->mComponentName.c_str());
4738        notify->post();
4739    }
4740
4741    mCodec->changeState(mCodec->mLoadedState);
4742
4743    return true;
4744}
4745
4746////////////////////////////////////////////////////////////////////////////////
4747
4748ACodec::LoadedState::LoadedState(ACodec *codec)
4749    : BaseState(codec) {
4750}
4751
4752void ACodec::LoadedState::stateEntered() {
4753    ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
4754
4755    mCodec->mPortEOS[kPortIndexInput] =
4756        mCodec->mPortEOS[kPortIndexOutput] = false;
4757
4758    mCodec->mInputEOSResult = OK;
4759
4760    mCodec->mDequeueCounter = 0;
4761    mCodec->mMetaDataBuffersToSubmit = 0;
4762    mCodec->mRepeatFrameDelayUs = -1ll;
4763    mCodec->mInputFormat.clear();
4764    mCodec->mOutputFormat.clear();
4765    mCodec->mBaseOutputFormat.clear();
4766
4767    if (mCodec->mShutdownInProgress) {
4768        bool keepComponentAllocated = mCodec->mKeepComponentAllocated;
4769
4770        mCodec->mShutdownInProgress = false;
4771        mCodec->mKeepComponentAllocated = false;
4772
4773        onShutdown(keepComponentAllocated);
4774    }
4775    mCodec->mExplicitShutdown = false;
4776
4777    mCodec->processDeferredMessages();
4778}
4779
4780void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) {
4781    if (!keepComponentAllocated) {
4782        CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
4783
4784        mCodec->changeState(mCodec->mUninitializedState);
4785    }
4786
4787    if (mCodec->mExplicitShutdown) {
4788        sp<AMessage> notify = mCodec->mNotify->dup();
4789        notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
4790        notify->post();
4791        mCodec->mExplicitShutdown = false;
4792    }
4793}
4794
4795bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) {
4796    bool handled = false;
4797
4798    switch (msg->what()) {
4799        case ACodec::kWhatConfigureComponent:
4800        {
4801            onConfigureComponent(msg);
4802            handled = true;
4803            break;
4804        }
4805
4806        case ACodec::kWhatCreateInputSurface:
4807        {
4808            onCreateInputSurface(msg);
4809            handled = true;
4810            break;
4811        }
4812
4813        case ACodec::kWhatStart:
4814        {
4815            onStart();
4816            handled = true;
4817            break;
4818        }
4819
4820        case ACodec::kWhatShutdown:
4821        {
4822            int32_t keepComponentAllocated;
4823            CHECK(msg->findInt32(
4824                        "keepComponentAllocated", &keepComponentAllocated));
4825
4826            mCodec->mExplicitShutdown = true;
4827            onShutdown(keepComponentAllocated);
4828
4829            handled = true;
4830            break;
4831        }
4832
4833        case ACodec::kWhatFlush:
4834        {
4835            sp<AMessage> notify = mCodec->mNotify->dup();
4836            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
4837            notify->post();
4838
4839            handled = true;
4840            break;
4841        }
4842
4843        default:
4844            return BaseState::onMessageReceived(msg);
4845    }
4846
4847    return handled;
4848}
4849
4850bool ACodec::LoadedState::onConfigureComponent(
4851        const sp<AMessage> &msg) {
4852    ALOGV("onConfigureComponent");
4853
4854    CHECK(mCodec->mNode != NULL);
4855
4856    AString mime;
4857    CHECK(msg->findString("mime", &mime));
4858
4859    status_t err = mCodec->configureCodec(mime.c_str(), msg);
4860
4861    if (err != OK) {
4862        ALOGE("[%s] configureCodec returning error %d",
4863              mCodec->mComponentName.c_str(), err);
4864
4865        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
4866        return false;
4867    }
4868
4869    sp<RefBase> obj;
4870    if (msg->findObject("native-window", &obj)
4871            && strncmp("OMX.google.", mCodec->mComponentName.c_str(), 11)) {
4872        sp<NativeWindowWrapper> nativeWindow(
4873                static_cast<NativeWindowWrapper *>(obj.get()));
4874        CHECK(nativeWindow != NULL);
4875        mCodec->mNativeWindow = nativeWindow->getNativeWindow();
4876
4877        native_window_set_scaling_mode(
4878                mCodec->mNativeWindow.get(),
4879                NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
4880    }
4881    CHECK_EQ((status_t)OK, mCodec->initNativeWindow());
4882
4883    {
4884        sp<AMessage> notify = mCodec->mNotify->dup();
4885        notify->setInt32("what", CodecBase::kWhatComponentConfigured);
4886        notify->setMessage("input-format", mCodec->mInputFormat);
4887        notify->setMessage("output-format", mCodec->mOutputFormat);
4888        notify->post();
4889    }
4890
4891    return true;
4892}
4893
4894void ACodec::LoadedState::onCreateInputSurface(
4895        const sp<AMessage> & /* msg */) {
4896    ALOGV("onCreateInputSurface");
4897
4898    sp<AMessage> notify = mCodec->mNotify->dup();
4899    notify->setInt32("what", CodecBase::kWhatInputSurfaceCreated);
4900
4901    sp<IGraphicBufferProducer> bufferProducer;
4902    status_t err;
4903
4904    err = mCodec->mOMX->createInputSurface(mCodec->mNode, kPortIndexInput,
4905            &bufferProducer);
4906
4907    if (err == OK && mCodec->mRepeatFrameDelayUs > 0ll) {
4908        err = mCodec->mOMX->setInternalOption(
4909                mCodec->mNode,
4910                kPortIndexInput,
4911                IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY,
4912                &mCodec->mRepeatFrameDelayUs,
4913                sizeof(mCodec->mRepeatFrameDelayUs));
4914
4915        if (err != OK) {
4916            ALOGE("[%s] Unable to configure option to repeat previous "
4917                  "frames (err %d)",
4918                  mCodec->mComponentName.c_str(),
4919                  err);
4920        }
4921    }
4922
4923    if (err == OK && mCodec->mMaxPtsGapUs > 0ll) {
4924        err = mCodec->mOMX->setInternalOption(
4925                mCodec->mNode,
4926                kPortIndexInput,
4927                IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP,
4928                &mCodec->mMaxPtsGapUs,
4929                sizeof(mCodec->mMaxPtsGapUs));
4930
4931        if (err != OK) {
4932            ALOGE("[%s] Unable to configure max timestamp gap (err %d)",
4933                    mCodec->mComponentName.c_str(),
4934                    err);
4935        }
4936    }
4937
4938    if (err == OK && mCodec->mTimePerCaptureUs > 0ll
4939            && mCodec->mTimePerFrameUs > 0ll) {
4940        int64_t timeLapse[2];
4941        timeLapse[0] = mCodec->mTimePerFrameUs;
4942        timeLapse[1] = mCodec->mTimePerCaptureUs;
4943        err = mCodec->mOMX->setInternalOption(
4944                mCodec->mNode,
4945                kPortIndexInput,
4946                IOMX::INTERNAL_OPTION_TIME_LAPSE,
4947                &timeLapse[0],
4948                sizeof(timeLapse));
4949
4950        if (err != OK) {
4951            ALOGE("[%s] Unable to configure time lapse (err %d)",
4952                    mCodec->mComponentName.c_str(),
4953                    err);
4954        }
4955    }
4956
4957    if (err == OK && mCodec->mCreateInputBuffersSuspended) {
4958        bool suspend = true;
4959        err = mCodec->mOMX->setInternalOption(
4960                mCodec->mNode,
4961                kPortIndexInput,
4962                IOMX::INTERNAL_OPTION_SUSPEND,
4963                &suspend,
4964                sizeof(suspend));
4965
4966        if (err != OK) {
4967            ALOGE("[%s] Unable to configure option to suspend (err %d)",
4968                  mCodec->mComponentName.c_str(),
4969                  err);
4970        }
4971    }
4972
4973    if (err == OK) {
4974        notify->setObject("input-surface",
4975                new BufferProducerWrapper(bufferProducer));
4976    } else {
4977        // Can't use mCodec->signalError() here -- MediaCodec won't forward
4978        // the error through because it's in the "configured" state.  We
4979        // send a kWhatInputSurfaceCreated with an error value instead.
4980        ALOGE("[%s] onCreateInputSurface returning error %d",
4981                mCodec->mComponentName.c_str(), err);
4982        notify->setInt32("err", err);
4983    }
4984    notify->post();
4985}
4986
4987void ACodec::LoadedState::onStart() {
4988    ALOGV("onStart");
4989
4990    CHECK_EQ(mCodec->mOMX->sendCommand(
4991                mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
4992             (status_t)OK);
4993
4994    mCodec->changeState(mCodec->mLoadedToIdleState);
4995}
4996
4997////////////////////////////////////////////////////////////////////////////////
4998
4999ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec)
5000    : BaseState(codec) {
5001}
5002
5003void ACodec::LoadedToIdleState::stateEntered() {
5004    ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
5005
5006    status_t err;
5007    if ((err = allocateBuffers()) != OK) {
5008        ALOGE("Failed to allocate buffers after transitioning to IDLE state "
5009             "(error 0x%08x)",
5010             err);
5011
5012        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5013
5014        mCodec->changeState(mCodec->mLoadedState);
5015    }
5016}
5017
5018status_t ACodec::LoadedToIdleState::allocateBuffers() {
5019    status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput);
5020
5021    if (err != OK) {
5022        return err;
5023    }
5024
5025    return mCodec->allocateBuffersOnPort(kPortIndexOutput);
5026}
5027
5028bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
5029    switch (msg->what()) {
5030        case kWhatSetParameters:
5031        case kWhatShutdown:
5032        {
5033            mCodec->deferMessage(msg);
5034            return true;
5035        }
5036
5037        case kWhatSignalEndOfInputStream:
5038        {
5039            mCodec->onSignalEndOfInputStream();
5040            return true;
5041        }
5042
5043        case kWhatResume:
5044        {
5045            // We'll be active soon enough.
5046            return true;
5047        }
5048
5049        case kWhatFlush:
5050        {
5051            // We haven't even started yet, so we're flushed alright...
5052            sp<AMessage> notify = mCodec->mNotify->dup();
5053            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
5054            notify->post();
5055            return true;
5056        }
5057
5058        default:
5059            return BaseState::onMessageReceived(msg);
5060    }
5061}
5062
5063bool ACodec::LoadedToIdleState::onOMXEvent(
5064        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5065    switch (event) {
5066        case OMX_EventCmdComplete:
5067        {
5068            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
5069            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
5070
5071            CHECK_EQ(mCodec->mOMX->sendCommand(
5072                        mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting),
5073                     (status_t)OK);
5074
5075            mCodec->changeState(mCodec->mIdleToExecutingState);
5076
5077            return true;
5078        }
5079
5080        default:
5081            return BaseState::onOMXEvent(event, data1, data2);
5082    }
5083}
5084
5085////////////////////////////////////////////////////////////////////////////////
5086
5087ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec)
5088    : BaseState(codec) {
5089}
5090
5091void ACodec::IdleToExecutingState::stateEntered() {
5092    ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
5093}
5094
5095bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
5096    switch (msg->what()) {
5097        case kWhatSetParameters:
5098        case kWhatShutdown:
5099        {
5100            mCodec->deferMessage(msg);
5101            return true;
5102        }
5103
5104        case kWhatResume:
5105        {
5106            // We'll be active soon enough.
5107            return true;
5108        }
5109
5110        case kWhatFlush:
5111        {
5112            // We haven't even started yet, so we're flushed alright...
5113            sp<AMessage> notify = mCodec->mNotify->dup();
5114            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
5115            notify->post();
5116
5117            return true;
5118        }
5119
5120        case kWhatSignalEndOfInputStream:
5121        {
5122            mCodec->onSignalEndOfInputStream();
5123            return true;
5124        }
5125
5126        default:
5127            return BaseState::onMessageReceived(msg);
5128    }
5129}
5130
5131bool ACodec::IdleToExecutingState::onOMXEvent(
5132        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5133    switch (event) {
5134        case OMX_EventCmdComplete:
5135        {
5136            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
5137            CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting);
5138
5139            mCodec->mExecutingState->resume();
5140            mCodec->changeState(mCodec->mExecutingState);
5141
5142            return true;
5143        }
5144
5145        default:
5146            return BaseState::onOMXEvent(event, data1, data2);
5147    }
5148}
5149
5150////////////////////////////////////////////////////////////////////////////////
5151
5152ACodec::ExecutingState::ExecutingState(ACodec *codec)
5153    : BaseState(codec),
5154      mActive(false) {
5155}
5156
5157ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode(
5158        OMX_U32 /* portIndex */) {
5159    return RESUBMIT_BUFFERS;
5160}
5161
5162void ACodec::ExecutingState::submitOutputMetaBuffers() {
5163    // submit as many buffers as there are input buffers with the codec
5164    // in case we are in port reconfiguring
5165    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
5166        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
5167
5168        if (info->mStatus == BufferInfo::OWNED_BY_COMPONENT) {
5169            if (mCodec->submitOutputMetaDataBuffer() != OK)
5170                break;
5171        }
5172    }
5173
5174    // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
5175    mCodec->signalSubmitOutputMetaDataBufferIfEOS_workaround();
5176}
5177
5178void ACodec::ExecutingState::submitRegularOutputBuffers() {
5179    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
5180        BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
5181
5182        if (mCodec->mNativeWindow != NULL) {
5183            CHECK(info->mStatus == BufferInfo::OWNED_BY_US
5184                    || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
5185
5186            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
5187                continue;
5188            }
5189        } else {
5190            CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
5191        }
5192
5193        ALOGV("[%s] calling fillBuffer %p",
5194             mCodec->mComponentName.c_str(), info->mBufferID);
5195
5196        CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
5197                 (status_t)OK);
5198
5199        info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
5200    }
5201}
5202
5203void ACodec::ExecutingState::submitOutputBuffers() {
5204    submitRegularOutputBuffers();
5205    if (mCodec->mStoreMetaDataInOutputBuffers) {
5206        submitOutputMetaBuffers();
5207    }
5208}
5209
5210void ACodec::ExecutingState::resume() {
5211    if (mActive) {
5212        ALOGV("[%s] We're already active, no need to resume.",
5213             mCodec->mComponentName.c_str());
5214
5215        return;
5216    }
5217
5218    submitOutputBuffers();
5219
5220    // Post all available input buffers
5221    CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u);
5222    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); i++) {
5223        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
5224        if (info->mStatus == BufferInfo::OWNED_BY_US) {
5225            postFillThisBuffer(info);
5226        }
5227    }
5228
5229    mActive = true;
5230}
5231
5232void ACodec::ExecutingState::stateEntered() {
5233    ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
5234
5235    mCodec->processDeferredMessages();
5236}
5237
5238bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) {
5239    bool handled = false;
5240
5241    switch (msg->what()) {
5242        case kWhatShutdown:
5243        {
5244            int32_t keepComponentAllocated;
5245            CHECK(msg->findInt32(
5246                        "keepComponentAllocated", &keepComponentAllocated));
5247
5248            mCodec->mShutdownInProgress = true;
5249            mCodec->mExplicitShutdown = true;
5250            mCodec->mKeepComponentAllocated = keepComponentAllocated;
5251
5252            mActive = false;
5253
5254            CHECK_EQ(mCodec->mOMX->sendCommand(
5255                        mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
5256                     (status_t)OK);
5257
5258            mCodec->changeState(mCodec->mExecutingToIdleState);
5259
5260            handled = true;
5261            break;
5262        }
5263
5264        case kWhatFlush:
5265        {
5266            ALOGV("[%s] ExecutingState flushing now "
5267                 "(codec owns %d/%d input, %d/%d output).",
5268                    mCodec->mComponentName.c_str(),
5269                    mCodec->countBuffersOwnedByComponent(kPortIndexInput),
5270                    mCodec->mBuffers[kPortIndexInput].size(),
5271                    mCodec->countBuffersOwnedByComponent(kPortIndexOutput),
5272                    mCodec->mBuffers[kPortIndexOutput].size());
5273
5274            mActive = false;
5275
5276            CHECK_EQ(mCodec->mOMX->sendCommand(
5277                        mCodec->mNode, OMX_CommandFlush, OMX_ALL),
5278                     (status_t)OK);
5279
5280            mCodec->changeState(mCodec->mFlushingState);
5281            handled = true;
5282            break;
5283        }
5284
5285        case kWhatResume:
5286        {
5287            resume();
5288
5289            handled = true;
5290            break;
5291        }
5292
5293        case kWhatRequestIDRFrame:
5294        {
5295            status_t err = mCodec->requestIDRFrame();
5296            if (err != OK) {
5297                ALOGW("Requesting an IDR frame failed.");
5298            }
5299
5300            handled = true;
5301            break;
5302        }
5303
5304        case kWhatSetParameters:
5305        {
5306            sp<AMessage> params;
5307            CHECK(msg->findMessage("params", &params));
5308
5309            status_t err = mCodec->setParameters(params);
5310
5311            sp<AMessage> reply;
5312            if (msg->findMessage("reply", &reply)) {
5313                reply->setInt32("err", err);
5314                reply->post();
5315            }
5316
5317            handled = true;
5318            break;
5319        }
5320
5321        case ACodec::kWhatSignalEndOfInputStream:
5322        {
5323            mCodec->onSignalEndOfInputStream();
5324            handled = true;
5325            break;
5326        }
5327
5328        // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
5329        case kWhatSubmitOutputMetaDataBufferIfEOS:
5330        {
5331            if (mCodec->mPortEOS[kPortIndexInput] &&
5332                    !mCodec->mPortEOS[kPortIndexOutput]) {
5333                status_t err = mCodec->submitOutputMetaDataBuffer();
5334                if (err == OK) {
5335                    mCodec->signalSubmitOutputMetaDataBufferIfEOS_workaround();
5336                }
5337            }
5338            return true;
5339        }
5340
5341        default:
5342            handled = BaseState::onMessageReceived(msg);
5343            break;
5344    }
5345
5346    return handled;
5347}
5348
5349status_t ACodec::setParameters(const sp<AMessage> &params) {
5350    int32_t videoBitrate;
5351    if (params->findInt32("video-bitrate", &videoBitrate)) {
5352        OMX_VIDEO_CONFIG_BITRATETYPE configParams;
5353        InitOMXParams(&configParams);
5354        configParams.nPortIndex = kPortIndexOutput;
5355        configParams.nEncodeBitrate = videoBitrate;
5356
5357        status_t err = mOMX->setConfig(
5358                mNode,
5359                OMX_IndexConfigVideoBitrate,
5360                &configParams,
5361                sizeof(configParams));
5362
5363        if (err != OK) {
5364            ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d",
5365                   videoBitrate, err);
5366
5367            return err;
5368        }
5369    }
5370
5371    int64_t skipFramesBeforeUs;
5372    if (params->findInt64("skip-frames-before", &skipFramesBeforeUs)) {
5373        status_t err =
5374            mOMX->setInternalOption(
5375                     mNode,
5376                     kPortIndexInput,
5377                     IOMX::INTERNAL_OPTION_START_TIME,
5378                     &skipFramesBeforeUs,
5379                     sizeof(skipFramesBeforeUs));
5380
5381        if (err != OK) {
5382            ALOGE("Failed to set parameter 'skip-frames-before' (err %d)", err);
5383            return err;
5384        }
5385    }
5386
5387    int32_t dropInputFrames;
5388    if (params->findInt32("drop-input-frames", &dropInputFrames)) {
5389        bool suspend = dropInputFrames != 0;
5390
5391        status_t err =
5392            mOMX->setInternalOption(
5393                     mNode,
5394                     kPortIndexInput,
5395                     IOMX::INTERNAL_OPTION_SUSPEND,
5396                     &suspend,
5397                     sizeof(suspend));
5398
5399        if (err != OK) {
5400            ALOGE("Failed to set parameter 'drop-input-frames' (err %d)", err);
5401            return err;
5402        }
5403    }
5404
5405    int32_t dummy;
5406    if (params->findInt32("request-sync", &dummy)) {
5407        status_t err = requestIDRFrame();
5408
5409        if (err != OK) {
5410            ALOGE("Requesting a sync frame failed w/ err %d", err);
5411            return err;
5412        }
5413    }
5414
5415    return OK;
5416}
5417
5418void ACodec::onSignalEndOfInputStream() {
5419    sp<AMessage> notify = mNotify->dup();
5420    notify->setInt32("what", CodecBase::kWhatSignaledInputEOS);
5421
5422    status_t err = mOMX->signalEndOfInputStream(mNode);
5423    if (err != OK) {
5424        notify->setInt32("err", err);
5425    }
5426    notify->post();
5427}
5428
5429bool ACodec::ExecutingState::onOMXEvent(
5430        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5431    switch (event) {
5432        case OMX_EventPortSettingsChanged:
5433        {
5434            CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
5435
5436            if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
5437                mCodec->mMetaDataBuffersToSubmit = 0;
5438                CHECK_EQ(mCodec->mOMX->sendCommand(
5439                            mCodec->mNode,
5440                            OMX_CommandPortDisable, kPortIndexOutput),
5441                         (status_t)OK);
5442
5443                mCodec->freeOutputBuffersNotOwnedByComponent();
5444
5445                mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
5446            } else if (data2 == OMX_IndexConfigCommonOutputCrop) {
5447                mCodec->mSentFormat = false;
5448            } else {
5449                ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx",
5450                     mCodec->mComponentName.c_str(), data2);
5451            }
5452
5453            return true;
5454        }
5455
5456        case OMX_EventBufferFlag:
5457        {
5458            return true;
5459        }
5460
5461        default:
5462            return BaseState::onOMXEvent(event, data1, data2);
5463    }
5464}
5465
5466////////////////////////////////////////////////////////////////////////////////
5467
5468ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState(
5469        ACodec *codec)
5470    : BaseState(codec) {
5471}
5472
5473ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode(
5474        OMX_U32 portIndex) {
5475    if (portIndex == kPortIndexOutput) {
5476        return FREE_BUFFERS;
5477    }
5478
5479    CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput);
5480
5481    return RESUBMIT_BUFFERS;
5482}
5483
5484bool ACodec::OutputPortSettingsChangedState::onMessageReceived(
5485        const sp<AMessage> &msg) {
5486    bool handled = false;
5487
5488    switch (msg->what()) {
5489        case kWhatFlush:
5490        case kWhatShutdown:
5491        case kWhatResume:
5492        case kWhatSetParameters:
5493        {
5494            if (msg->what() == kWhatResume) {
5495                ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
5496            }
5497
5498            mCodec->deferMessage(msg);
5499            handled = true;
5500            break;
5501        }
5502
5503        default:
5504            handled = BaseState::onMessageReceived(msg);
5505            break;
5506    }
5507
5508    return handled;
5509}
5510
5511void ACodec::OutputPortSettingsChangedState::stateEntered() {
5512    ALOGV("[%s] Now handling output port settings change",
5513         mCodec->mComponentName.c_str());
5514}
5515
5516bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
5517        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5518    switch (event) {
5519        case OMX_EventCmdComplete:
5520        {
5521            if (data1 == (OMX_U32)OMX_CommandPortDisable) {
5522                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
5523
5524                ALOGV("[%s] Output port now disabled.",
5525                        mCodec->mComponentName.c_str());
5526
5527                CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty());
5528                mCodec->mDealer[kPortIndexOutput].clear();
5529
5530                CHECK_EQ(mCodec->mOMX->sendCommand(
5531                            mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput),
5532                         (status_t)OK);
5533
5534                status_t err;
5535                if ((err = mCodec->allocateBuffersOnPort(
5536                                kPortIndexOutput)) != OK) {
5537                    ALOGE("Failed to allocate output port buffers after "
5538                         "port reconfiguration (error 0x%08x)",
5539                         err);
5540
5541                    mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5542
5543                    // This is technically not correct, but appears to be
5544                    // the only way to free the component instance.
5545                    // Controlled transitioning from excecuting->idle
5546                    // and idle->loaded seem impossible probably because
5547                    // the output port never finishes re-enabling.
5548                    mCodec->mShutdownInProgress = true;
5549                    mCodec->mKeepComponentAllocated = false;
5550                    mCodec->changeState(mCodec->mLoadedState);
5551                }
5552
5553                return true;
5554            } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
5555                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
5556
5557                mCodec->mSentFormat = false;
5558
5559                ALOGV("[%s] Output port now reenabled.",
5560                        mCodec->mComponentName.c_str());
5561
5562                if (mCodec->mExecutingState->active()) {
5563                    mCodec->mExecutingState->submitOutputBuffers();
5564                }
5565
5566                mCodec->changeState(mCodec->mExecutingState);
5567
5568                return true;
5569            }
5570
5571            return false;
5572        }
5573
5574        default:
5575            return false;
5576    }
5577}
5578
5579////////////////////////////////////////////////////////////////////////////////
5580
5581ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec)
5582    : BaseState(codec),
5583      mComponentNowIdle(false) {
5584}
5585
5586bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) {
5587    bool handled = false;
5588
5589    switch (msg->what()) {
5590        case kWhatFlush:
5591        {
5592            // Don't send me a flush request if you previously wanted me
5593            // to shutdown.
5594            TRESPASS();
5595            break;
5596        }
5597
5598        case kWhatShutdown:
5599        {
5600            // We're already doing that...
5601
5602            handled = true;
5603            break;
5604        }
5605
5606        default:
5607            handled = BaseState::onMessageReceived(msg);
5608            break;
5609    }
5610
5611    return handled;
5612}
5613
5614void ACodec::ExecutingToIdleState::stateEntered() {
5615    ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
5616
5617    mComponentNowIdle = false;
5618    mCodec->mSentFormat = false;
5619}
5620
5621bool ACodec::ExecutingToIdleState::onOMXEvent(
5622        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5623    switch (event) {
5624        case OMX_EventCmdComplete:
5625        {
5626            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
5627            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
5628
5629            mComponentNowIdle = true;
5630
5631            changeStateIfWeOwnAllBuffers();
5632
5633            return true;
5634        }
5635
5636        case OMX_EventPortSettingsChanged:
5637        case OMX_EventBufferFlag:
5638        {
5639            // We're shutting down and don't care about this anymore.
5640            return true;
5641        }
5642
5643        default:
5644            return BaseState::onOMXEvent(event, data1, data2);
5645    }
5646}
5647
5648void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
5649    if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) {
5650        CHECK_EQ(mCodec->mOMX->sendCommand(
5651                    mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded),
5652                 (status_t)OK);
5653
5654        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK);
5655        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK);
5656
5657        if ((mCodec->mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown)
5658                && mCodec->mNativeWindow != NULL) {
5659            // We push enough 1x1 blank buffers to ensure that one of
5660            // them has made it to the display.  This allows the OMX
5661            // component teardown to zero out any protected buffers
5662            // without the risk of scanning out one of those buffers.
5663            mCodec->pushBlankBuffersToNativeWindow();
5664        }
5665
5666        mCodec->changeState(mCodec->mIdleToLoadedState);
5667    }
5668}
5669
5670void ACodec::ExecutingToIdleState::onInputBufferFilled(
5671        const sp<AMessage> &msg) {
5672    BaseState::onInputBufferFilled(msg);
5673
5674    changeStateIfWeOwnAllBuffers();
5675}
5676
5677void ACodec::ExecutingToIdleState::onOutputBufferDrained(
5678        const sp<AMessage> &msg) {
5679    BaseState::onOutputBufferDrained(msg);
5680
5681    changeStateIfWeOwnAllBuffers();
5682}
5683
5684////////////////////////////////////////////////////////////////////////////////
5685
5686ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec)
5687    : BaseState(codec) {
5688}
5689
5690bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) {
5691    bool handled = false;
5692
5693    switch (msg->what()) {
5694        case kWhatShutdown:
5695        {
5696            // We're already doing that...
5697
5698            handled = true;
5699            break;
5700        }
5701
5702        case kWhatFlush:
5703        {
5704            // Don't send me a flush request if you previously wanted me
5705            // to shutdown.
5706            TRESPASS();
5707            break;
5708        }
5709
5710        default:
5711            handled = BaseState::onMessageReceived(msg);
5712            break;
5713    }
5714
5715    return handled;
5716}
5717
5718void ACodec::IdleToLoadedState::stateEntered() {
5719    ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
5720}
5721
5722bool ACodec::IdleToLoadedState::onOMXEvent(
5723        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5724    switch (event) {
5725        case OMX_EventCmdComplete:
5726        {
5727            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
5728            CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded);
5729
5730            mCodec->changeState(mCodec->mLoadedState);
5731
5732            return true;
5733        }
5734
5735        default:
5736            return BaseState::onOMXEvent(event, data1, data2);
5737    }
5738}
5739
5740////////////////////////////////////////////////////////////////////////////////
5741
5742ACodec::FlushingState::FlushingState(ACodec *codec)
5743    : BaseState(codec) {
5744}
5745
5746void ACodec::FlushingState::stateEntered() {
5747    ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());
5748
5749    mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
5750}
5751
5752bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) {
5753    bool handled = false;
5754
5755    switch (msg->what()) {
5756        case kWhatShutdown:
5757        {
5758            mCodec->deferMessage(msg);
5759            break;
5760        }
5761
5762        case kWhatFlush:
5763        {
5764            // We're already doing this right now.
5765            handled = true;
5766            break;
5767        }
5768
5769        default:
5770            handled = BaseState::onMessageReceived(msg);
5771            break;
5772    }
5773
5774    return handled;
5775}
5776
5777bool ACodec::FlushingState::onOMXEvent(
5778        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5779    ALOGV("[%s] FlushingState onOMXEvent(%d,%ld)",
5780            mCodec->mComponentName.c_str(), event, data1);
5781
5782    switch (event) {
5783        case OMX_EventCmdComplete:
5784        {
5785            CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush);
5786
5787            if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
5788                CHECK(!mFlushComplete[data2]);
5789                mFlushComplete[data2] = true;
5790
5791                if (mFlushComplete[kPortIndexInput]
5792                        && mFlushComplete[kPortIndexOutput]) {
5793                    changeStateIfWeOwnAllBuffers();
5794                }
5795            } else {
5796                CHECK_EQ(data2, OMX_ALL);
5797                CHECK(mFlushComplete[kPortIndexInput]);
5798                CHECK(mFlushComplete[kPortIndexOutput]);
5799
5800                changeStateIfWeOwnAllBuffers();
5801            }
5802
5803            return true;
5804        }
5805
5806        case OMX_EventPortSettingsChanged:
5807        {
5808            sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id());
5809            msg->setInt32("type", omx_message::EVENT);
5810            msg->setInt32("node", mCodec->mNode);
5811            msg->setInt32("event", event);
5812            msg->setInt32("data1", data1);
5813            msg->setInt32("data2", data2);
5814
5815            ALOGV("[%s] Deferring OMX_EventPortSettingsChanged",
5816                 mCodec->mComponentName.c_str());
5817
5818            mCodec->deferMessage(msg);
5819
5820            return true;
5821        }
5822
5823        default:
5824            return BaseState::onOMXEvent(event, data1, data2);
5825    }
5826
5827    return true;
5828}
5829
5830void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) {
5831    BaseState::onOutputBufferDrained(msg);
5832
5833    changeStateIfWeOwnAllBuffers();
5834}
5835
5836void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) {
5837    BaseState::onInputBufferFilled(msg);
5838
5839    changeStateIfWeOwnAllBuffers();
5840}
5841
5842void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() {
5843    if (mFlushComplete[kPortIndexInput]
5844            && mFlushComplete[kPortIndexOutput]
5845            && mCodec->allYourBuffersAreBelongToUs()) {
5846        // We now own all buffers except possibly those still queued with
5847        // the native window for rendering. Let's get those back as well.
5848        mCodec->waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs();
5849
5850        sp<AMessage> notify = mCodec->mNotify->dup();
5851        notify->setInt32("what", CodecBase::kWhatFlushCompleted);
5852        notify->post();
5853
5854        mCodec->mPortEOS[kPortIndexInput] =
5855            mCodec->mPortEOS[kPortIndexOutput] = false;
5856
5857        mCodec->mInputEOSResult = OK;
5858
5859        if (mCodec->mSkipCutBuffer != NULL) {
5860            mCodec->mSkipCutBuffer->clear();
5861        }
5862
5863        mCodec->changeState(mCodec->mExecutingState);
5864    }
5865}
5866
5867}  // namespace android
5868