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