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