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