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