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