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