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 <media/stagefright/foundation/avc_utils.h>
32#include <media/stagefright/foundation/hexdump.h>
33#include <media/stagefright/foundation/ABuffer.h>
34#include <media/stagefright/foundation/ADebug.h>
35#include <media/stagefright/foundation/AMessage.h>
36#include <media/stagefright/foundation/AUtils.h>
37
38#include <media/stagefright/BufferProducerWrapper.h>
39#include <media/stagefright/MediaCodec.h>
40#include <media/stagefright/MediaDefs.h>
41#include <media/stagefright/OMXClient.h>
42#include <media/stagefright/PersistentSurface.h>
43#include <media/stagefright/SurfaceUtils.h>
44#include <media/hardware/HardwareAPI.h>
45#include <media/MediaBufferHolder.h>
46#include <media/OMXBuffer.h>
47#include <media/omx/1.0/WOmxNode.h>
48
49#include <hidlmemory/mapping.h>
50
51#include <media/openmax/OMX_AudioExt.h>
52#include <media/openmax/OMX_VideoExt.h>
53#include <media/openmax/OMX_Component.h>
54#include <media/openmax/OMX_IndexExt.h>
55#include <media/openmax/OMX_AsString.h>
56
57#include "include/ACodecBufferChannel.h"
58#include "include/DataConverter.h"
59#include "include/SecureBuffer.h"
60#include "include/SharedMemoryBuffer.h"
61#include <media/stagefright/omx/OMXUtils.h>
62
63namespace android {
64
65using binder::Status;
66
67enum {
68    kMaxIndicesToCheck = 32, // used when enumerating supported formats and profiles
69};
70
71// OMX errors are directly mapped into status_t range if
72// there is no corresponding MediaError status code.
73// Use the statusFromOMXError(int32_t omxError) function.
74//
75// Currently this is a direct map.
76// See frameworks/native/include/media/openmax/OMX_Core.h
77//
78// Vendor OMX errors     from 0x90000000 - 0x9000FFFF
79// Extension OMX errors  from 0x8F000000 - 0x90000000
80// Standard OMX errors   from 0x80001000 - 0x80001024 (0x80001024 current)
81//
82
83// returns true if err is a recognized OMX error code.
84// as OMX error is OMX_S32, this is an int32_t type
85static inline bool isOMXError(int32_t err) {
86    return (ERROR_CODEC_MIN <= err && err <= ERROR_CODEC_MAX);
87}
88
89// converts an OMX error to a status_t
90static inline status_t statusFromOMXError(int32_t omxError) {
91    switch (omxError) {
92    case OMX_ErrorInvalidComponentName:
93    case OMX_ErrorComponentNotFound:
94        return NAME_NOT_FOUND; // can trigger illegal argument error for provided names.
95    default:
96        return isOMXError(omxError) ? omxError : 0; // no translation required
97    }
98}
99
100static inline status_t statusFromBinderStatus(const Status &status) {
101    if (status.isOk()) {
102        return OK;
103    }
104    status_t err;
105    if ((err = status.serviceSpecificErrorCode()) != OK) {
106        return err;
107    }
108    if ((err = status.transactionError()) != OK) {
109        return err;
110    }
111    // Other exception
112    return UNKNOWN_ERROR;
113}
114
115// checks and converts status_t to a non-side-effect status_t
116static inline status_t makeNoSideEffectStatus(status_t err) {
117    switch (err) {
118    // the following errors have side effects and may come
119    // from other code modules. Remap for safety reasons.
120    case INVALID_OPERATION:
121    case DEAD_OBJECT:
122        return UNKNOWN_ERROR;
123    default:
124        return err;
125    }
126}
127
128static OMX_VIDEO_CONTROLRATETYPE getVideoBitrateMode(const sp<AMessage> &msg) {
129    int32_t tmp;
130    if (msg->findInt32("bitrate-mode", &tmp)) {
131        // explicitly translate from MediaCodecInfo.EncoderCapabilities.
132        // BITRATE_MODE_* into OMX bitrate mode.
133        switch (tmp) {
134            //BITRATE_MODE_CQ
135            case 0: return OMX_Video_ControlRateConstantQuality;
136            //BITRATE_MODE_VBR
137            case 1: return OMX_Video_ControlRateVariable;
138            //BITRATE_MODE_CBR
139            case 2: return OMX_Video_ControlRateConstant;
140            default: break;
141        }
142    }
143    return OMX_Video_ControlRateVariable;
144}
145
146static bool findVideoBitrateControlInfo(const sp<AMessage> &msg,
147        OMX_VIDEO_CONTROLRATETYPE *mode, int32_t *bitrate, int32_t *quality) {
148    *mode = getVideoBitrateMode(msg);
149    bool isCQ = (*mode == OMX_Video_ControlRateConstantQuality);
150    return (!isCQ && msg->findInt32("bitrate", bitrate))
151         || (isCQ && msg->findInt32("quality", quality));
152}
153
154struct MessageList : public RefBase {
155    MessageList() {
156    }
157    virtual ~MessageList() {
158    }
159    std::list<sp<AMessage> > &getList() { return mList; }
160private:
161    std::list<sp<AMessage> > mList;
162
163    DISALLOW_EVIL_CONSTRUCTORS(MessageList);
164};
165
166static sp<DataConverter> getCopyConverter() {
167    static pthread_once_t once = PTHREAD_ONCE_INIT; // const-inited
168    static sp<DataConverter> sCopyConverter;        // zero-inited
169    pthread_once(&once, [](){ sCopyConverter = new DataConverter(); });
170    return sCopyConverter;
171}
172
173struct CodecObserver : public BnOMXObserver {
174    CodecObserver() {}
175
176    void setNotificationMessage(const sp<AMessage> &msg) {
177        mNotify = msg;
178    }
179
180    // from IOMXObserver
181    virtual void onMessages(const std::list<omx_message> &messages) {
182        if (messages.empty()) {
183            return;
184        }
185
186        sp<AMessage> notify = mNotify->dup();
187        sp<MessageList> msgList = new MessageList();
188        for (std::list<omx_message>::const_iterator it = messages.cbegin();
189              it != messages.cend(); ++it) {
190            const omx_message &omx_msg = *it;
191
192            sp<AMessage> msg = new AMessage;
193            msg->setInt32("type", omx_msg.type);
194            switch (omx_msg.type) {
195                case omx_message::EVENT:
196                {
197                    msg->setInt32("event", omx_msg.u.event_data.event);
198                    msg->setInt32("data1", omx_msg.u.event_data.data1);
199                    msg->setInt32("data2", omx_msg.u.event_data.data2);
200                    break;
201                }
202
203                case omx_message::EMPTY_BUFFER_DONE:
204                {
205                    msg->setInt32("buffer", omx_msg.u.buffer_data.buffer);
206                    msg->setInt32("fence_fd", omx_msg.fenceFd);
207                    break;
208                }
209
210                case omx_message::FILL_BUFFER_DONE:
211                {
212                    msg->setInt32(
213                            "buffer", omx_msg.u.extended_buffer_data.buffer);
214                    msg->setInt32(
215                            "range_offset",
216                            omx_msg.u.extended_buffer_data.range_offset);
217                    msg->setInt32(
218                            "range_length",
219                            omx_msg.u.extended_buffer_data.range_length);
220                    msg->setInt32(
221                            "flags",
222                            omx_msg.u.extended_buffer_data.flags);
223                    msg->setInt64(
224                            "timestamp",
225                            omx_msg.u.extended_buffer_data.timestamp);
226                    msg->setInt32(
227                            "fence_fd", omx_msg.fenceFd);
228                    break;
229                }
230
231                case omx_message::FRAME_RENDERED:
232                {
233                    msg->setInt64(
234                            "media_time_us", omx_msg.u.render_data.timestamp);
235                    msg->setInt64(
236                            "system_nano", omx_msg.u.render_data.nanoTime);
237                    break;
238                }
239
240                default:
241                    ALOGE("Unrecognized message type: %d", omx_msg.type);
242                    break;
243            }
244            msgList->getList().push_back(msg);
245        }
246        notify->setObject("messages", msgList);
247        notify->post();
248    }
249
250protected:
251    virtual ~CodecObserver() {}
252
253private:
254    sp<AMessage> mNotify;
255
256    DISALLOW_EVIL_CONSTRUCTORS(CodecObserver);
257};
258
259////////////////////////////////////////////////////////////////////////////////
260
261struct ACodec::BaseState : public AState {
262    explicit BaseState(ACodec *codec, const sp<AState> &parentState = NULL);
263
264protected:
265    enum PortMode {
266        KEEP_BUFFERS,
267        RESUBMIT_BUFFERS,
268        FREE_BUFFERS,
269    };
270
271    ACodec *mCodec;
272
273    virtual PortMode getPortMode(OMX_U32 portIndex);
274
275    virtual void stateExited();
276    virtual bool onMessageReceived(const sp<AMessage> &msg);
277
278    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
279
280    virtual void onOutputBufferDrained(const sp<AMessage> &msg);
281    virtual void onInputBufferFilled(const sp<AMessage> &msg);
282
283    void postFillThisBuffer(BufferInfo *info);
284
285private:
286    // Handles an OMX message. Returns true iff message was handled.
287    bool onOMXMessage(const sp<AMessage> &msg);
288
289    // Handles a list of messages. Returns true iff messages were handled.
290    bool onOMXMessageList(const sp<AMessage> &msg);
291
292    // returns true iff this message is for this component and the component is alive
293    bool checkOMXMessage(const sp<AMessage> &msg);
294
295    bool onOMXEmptyBufferDone(IOMX::buffer_id bufferID, int fenceFd);
296
297    bool onOMXFillBufferDone(
298            IOMX::buffer_id bufferID,
299            size_t rangeOffset, size_t rangeLength,
300            OMX_U32 flags,
301            int64_t timeUs,
302            int fenceFd);
303
304    virtual bool onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano);
305
306    void getMoreInputDataIfPossible();
307
308    DISALLOW_EVIL_CONSTRUCTORS(BaseState);
309};
310
311////////////////////////////////////////////////////////////////////////////////
312
313struct ACodec::DeathNotifier :
314        public IBinder::DeathRecipient,
315        public ::android::hardware::hidl_death_recipient {
316    explicit DeathNotifier(const sp<AMessage> &notify)
317        : mNotify(notify) {
318    }
319
320    virtual void binderDied(const wp<IBinder> &) {
321        mNotify->post();
322    }
323
324    virtual void serviceDied(
325            uint64_t /* cookie */,
326            const wp<::android::hidl::base::V1_0::IBase>& /* who */) {
327        mNotify->post();
328    }
329
330protected:
331    virtual ~DeathNotifier() {}
332
333private:
334    sp<AMessage> mNotify;
335
336    DISALLOW_EVIL_CONSTRUCTORS(DeathNotifier);
337};
338
339struct ACodec::UninitializedState : public ACodec::BaseState {
340    explicit UninitializedState(ACodec *codec);
341
342protected:
343    virtual bool onMessageReceived(const sp<AMessage> &msg);
344    virtual void stateEntered();
345
346private:
347    void onSetup(const sp<AMessage> &msg);
348    bool onAllocateComponent(const sp<AMessage> &msg);
349
350    sp<DeathNotifier> mDeathNotifier;
351
352    DISALLOW_EVIL_CONSTRUCTORS(UninitializedState);
353};
354
355////////////////////////////////////////////////////////////////////////////////
356
357struct ACodec::LoadedState : public ACodec::BaseState {
358    explicit LoadedState(ACodec *codec);
359
360protected:
361    virtual bool onMessageReceived(const sp<AMessage> &msg);
362    virtual void stateEntered();
363
364private:
365    friend struct ACodec::UninitializedState;
366
367    bool onConfigureComponent(const sp<AMessage> &msg);
368    void onCreateInputSurface(const sp<AMessage> &msg);
369    void onSetInputSurface(const sp<AMessage> &msg);
370    void onStart();
371    void onShutdown(bool keepComponentAllocated);
372
373    status_t setupInputSurface();
374
375    DISALLOW_EVIL_CONSTRUCTORS(LoadedState);
376};
377
378////////////////////////////////////////////////////////////////////////////////
379
380struct ACodec::LoadedToIdleState : public ACodec::BaseState {
381    explicit LoadedToIdleState(ACodec *codec);
382
383protected:
384    virtual bool onMessageReceived(const sp<AMessage> &msg);
385    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
386    virtual void stateEntered();
387
388private:
389    status_t allocateBuffers();
390
391    DISALLOW_EVIL_CONSTRUCTORS(LoadedToIdleState);
392};
393
394////////////////////////////////////////////////////////////////////////////////
395
396struct ACodec::IdleToExecutingState : public ACodec::BaseState {
397    explicit IdleToExecutingState(ACodec *codec);
398
399protected:
400    virtual bool onMessageReceived(const sp<AMessage> &msg);
401    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
402    virtual void stateEntered();
403
404private:
405    DISALLOW_EVIL_CONSTRUCTORS(IdleToExecutingState);
406};
407
408////////////////////////////////////////////////////////////////////////////////
409
410struct ACodec::ExecutingState : public ACodec::BaseState {
411    explicit ExecutingState(ACodec *codec);
412
413    void submitRegularOutputBuffers();
414    void submitOutputMetaBuffers();
415    void submitOutputBuffers();
416
417    // Submit output buffers to the decoder, submit input buffers to client
418    // to fill with data.
419    void resume();
420
421    // Returns true iff input and output buffers are in play.
422    bool active() const { return mActive; }
423
424protected:
425    virtual PortMode getPortMode(OMX_U32 portIndex);
426    virtual bool onMessageReceived(const sp<AMessage> &msg);
427    virtual void stateEntered();
428
429    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
430    virtual bool onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano);
431
432private:
433    bool mActive;
434
435    DISALLOW_EVIL_CONSTRUCTORS(ExecutingState);
436};
437
438////////////////////////////////////////////////////////////////////////////////
439
440struct ACodec::OutputPortSettingsChangedState : public ACodec::BaseState {
441    explicit OutputPortSettingsChangedState(ACodec *codec);
442
443protected:
444    virtual PortMode getPortMode(OMX_U32 portIndex);
445    virtual bool onMessageReceived(const sp<AMessage> &msg);
446    virtual void stateEntered();
447
448    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
449    virtual bool onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano);
450
451private:
452    DISALLOW_EVIL_CONSTRUCTORS(OutputPortSettingsChangedState);
453};
454
455////////////////////////////////////////////////////////////////////////////////
456
457struct ACodec::ExecutingToIdleState : public ACodec::BaseState {
458    explicit ExecutingToIdleState(ACodec *codec);
459
460protected:
461    virtual bool onMessageReceived(const sp<AMessage> &msg);
462    virtual void stateEntered();
463
464    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
465
466    virtual void onOutputBufferDrained(const sp<AMessage> &msg);
467    virtual void onInputBufferFilled(const sp<AMessage> &msg);
468
469private:
470    void changeStateIfWeOwnAllBuffers();
471
472    bool mComponentNowIdle;
473
474    DISALLOW_EVIL_CONSTRUCTORS(ExecutingToIdleState);
475};
476
477////////////////////////////////////////////////////////////////////////////////
478
479struct ACodec::IdleToLoadedState : public ACodec::BaseState {
480    explicit IdleToLoadedState(ACodec *codec);
481
482protected:
483    virtual bool onMessageReceived(const sp<AMessage> &msg);
484    virtual void stateEntered();
485
486    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
487
488private:
489    DISALLOW_EVIL_CONSTRUCTORS(IdleToLoadedState);
490};
491
492////////////////////////////////////////////////////////////////////////////////
493
494struct ACodec::FlushingState : public ACodec::BaseState {
495    explicit FlushingState(ACodec *codec);
496
497protected:
498    virtual bool onMessageReceived(const sp<AMessage> &msg);
499    virtual void stateEntered();
500
501    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
502
503    virtual void onOutputBufferDrained(const sp<AMessage> &msg);
504    virtual void onInputBufferFilled(const sp<AMessage> &msg);
505
506private:
507    bool mFlushComplete[2];
508
509    void changeStateIfWeOwnAllBuffers();
510
511    DISALLOW_EVIL_CONSTRUCTORS(FlushingState);
512};
513
514////////////////////////////////////////////////////////////////////////////////
515
516void ACodec::BufferInfo::setWriteFence(int fenceFd, const char *dbg) {
517    if (mFenceFd >= 0) {
518        ALOGW("OVERWRITE OF %s fence %d by write fence %d in %s",
519                mIsReadFence ? "read" : "write", mFenceFd, fenceFd, dbg);
520    }
521    mFenceFd = fenceFd;
522    mIsReadFence = false;
523}
524
525void ACodec::BufferInfo::setReadFence(int fenceFd, const char *dbg) {
526    if (mFenceFd >= 0) {
527        ALOGW("OVERWRITE OF %s fence %d by read fence %d in %s",
528                mIsReadFence ? "read" : "write", mFenceFd, fenceFd, dbg);
529    }
530    mFenceFd = fenceFd;
531    mIsReadFence = true;
532}
533
534void ACodec::BufferInfo::checkWriteFence(const char *dbg) {
535    if (mFenceFd >= 0 && mIsReadFence) {
536        ALOGD("REUSING read fence %d as write fence in %s", mFenceFd, dbg);
537    }
538}
539
540void ACodec::BufferInfo::checkReadFence(const char *dbg) {
541    if (mFenceFd >= 0 && !mIsReadFence) {
542        ALOGD("REUSING write fence %d as read fence in %s", mFenceFd, dbg);
543    }
544}
545
546////////////////////////////////////////////////////////////////////////////////
547
548ACodec::ACodec()
549    : mSampleRate(0),
550      mNodeGeneration(0),
551      mUsingNativeWindow(false),
552      mNativeWindowUsageBits(0),
553      mLastNativeWindowDataSpace(HAL_DATASPACE_UNKNOWN),
554      mIsVideo(false),
555      mIsImage(false),
556      mIsEncoder(false),
557      mFatalError(false),
558      mShutdownInProgress(false),
559      mExplicitShutdown(false),
560      mIsLegacyVP9Decoder(false),
561      mEncoderDelay(0),
562      mEncoderPadding(0),
563      mRotationDegrees(0),
564      mChannelMaskPresent(false),
565      mChannelMask(0),
566      mDequeueCounter(0),
567      mMetadataBuffersToSubmit(0),
568      mNumUndequeuedBuffers(0),
569      mRepeatFrameDelayUs(-1ll),
570      mMaxPtsGapUs(0ll),
571      mMaxFps(-1),
572      mFps(-1.0),
573      mCaptureFps(-1.0),
574      mCreateInputBuffersSuspended(false),
575      mLatency(0),
576      mTunneled(false),
577      mDescribeColorAspectsIndex((OMX_INDEXTYPE)0),
578      mDescribeHDRStaticInfoIndex((OMX_INDEXTYPE)0),
579      mStateGeneration(0),
580      mVendorExtensionsStatus(kExtensionsUnchecked) {
581    memset(&mLastHDRStaticInfo, 0, sizeof(mLastHDRStaticInfo));
582
583    mUninitializedState = new UninitializedState(this);
584    mLoadedState = new LoadedState(this);
585    mLoadedToIdleState = new LoadedToIdleState(this);
586    mIdleToExecutingState = new IdleToExecutingState(this);
587    mExecutingState = new ExecutingState(this);
588
589    mOutputPortSettingsChangedState =
590        new OutputPortSettingsChangedState(this);
591
592    mExecutingToIdleState = new ExecutingToIdleState(this);
593    mIdleToLoadedState = new IdleToLoadedState(this);
594    mFlushingState = new FlushingState(this);
595
596    mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false;
597    mInputEOSResult = OK;
598
599    mPortMode[kPortIndexInput] = IOMX::kPortModePresetByteBuffer;
600    mPortMode[kPortIndexOutput] = IOMX::kPortModePresetByteBuffer;
601
602    memset(&mLastNativeWindowCrop, 0, sizeof(mLastNativeWindowCrop));
603
604    changeState(mUninitializedState);
605}
606
607ACodec::~ACodec() {
608}
609
610void ACodec::initiateSetup(const sp<AMessage> &msg) {
611    msg->setWhat(kWhatSetup);
612    msg->setTarget(this);
613    msg->post();
614}
615
616std::shared_ptr<BufferChannelBase> ACodec::getBufferChannel() {
617    if (!mBufferChannel) {
618        mBufferChannel = std::make_shared<ACodecBufferChannel>(
619                new AMessage(kWhatInputBufferFilled, this),
620                new AMessage(kWhatOutputBufferDrained, this));
621    }
622    return mBufferChannel;
623}
624
625void ACodec::signalSetParameters(const sp<AMessage> &params) {
626    sp<AMessage> msg = new AMessage(kWhatSetParameters, this);
627    msg->setMessage("params", params);
628    msg->post();
629}
630
631void ACodec::initiateAllocateComponent(const sp<AMessage> &msg) {
632    msg->setWhat(kWhatAllocateComponent);
633    msg->setTarget(this);
634    msg->post();
635}
636
637void ACodec::initiateConfigureComponent(const sp<AMessage> &msg) {
638    msg->setWhat(kWhatConfigureComponent);
639    msg->setTarget(this);
640    msg->post();
641}
642
643status_t ACodec::setSurface(const sp<Surface> &surface) {
644    sp<AMessage> msg = new AMessage(kWhatSetSurface, this);
645    msg->setObject("surface", surface);
646
647    sp<AMessage> response;
648    status_t err = msg->postAndAwaitResponse(&response);
649
650    if (err == OK) {
651        (void)response->findInt32("err", &err);
652    }
653    return err;
654}
655
656void ACodec::initiateCreateInputSurface() {
657    (new AMessage(kWhatCreateInputSurface, this))->post();
658}
659
660void ACodec::initiateSetInputSurface(
661        const sp<PersistentSurface> &surface) {
662    sp<AMessage> msg = new AMessage(kWhatSetInputSurface, this);
663    msg->setObject("input-surface", surface);
664    msg->post();
665}
666
667void ACodec::signalEndOfInputStream() {
668    (new AMessage(kWhatSignalEndOfInputStream, this))->post();
669}
670
671void ACodec::initiateStart() {
672    (new AMessage(kWhatStart, this))->post();
673}
674
675void ACodec::signalFlush() {
676    ALOGV("[%s] signalFlush", mComponentName.c_str());
677    (new AMessage(kWhatFlush, this))->post();
678}
679
680void ACodec::signalResume() {
681    (new AMessage(kWhatResume, this))->post();
682}
683
684void ACodec::initiateShutdown(bool keepComponentAllocated) {
685    sp<AMessage> msg = new AMessage(kWhatShutdown, this);
686    msg->setInt32("keepComponentAllocated", keepComponentAllocated);
687    msg->post();
688    if (!keepComponentAllocated) {
689        // ensure shutdown completes in 3 seconds
690        (new AMessage(kWhatReleaseCodecInstance, this))->post(3000000);
691    }
692}
693
694void ACodec::signalRequestIDRFrame() {
695    (new AMessage(kWhatRequestIDRFrame, this))->post();
696}
697
698// *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
699// Some codecs may return input buffers before having them processed.
700// This causes a halt if we already signaled an EOS on the input
701// port.  For now keep submitting an output buffer if there was an
702// EOS on the input port, but not yet on the output port.
703void ACodec::signalSubmitOutputMetadataBufferIfEOS_workaround() {
704    if (mPortEOS[kPortIndexInput] && !mPortEOS[kPortIndexOutput] &&
705            mMetadataBuffersToSubmit > 0) {
706        (new AMessage(kWhatSubmitOutputMetadataBufferIfEOS, this))->post();
707    }
708}
709
710status_t ACodec::handleSetSurface(const sp<Surface> &surface) {
711    // allow keeping unset surface
712    if (surface == NULL) {
713        if (mNativeWindow != NULL) {
714            ALOGW("cannot unset a surface");
715            return INVALID_OPERATION;
716        }
717        return OK;
718    }
719
720    // cannot switch from bytebuffers to surface
721    if (mNativeWindow == NULL) {
722        ALOGW("component was not configured with a surface");
723        return INVALID_OPERATION;
724    }
725
726    ANativeWindow *nativeWindow = surface.get();
727    // if we have not yet started the codec, we can simply set the native window
728    if (mBuffers[kPortIndexInput].size() == 0) {
729        mNativeWindow = surface;
730        return OK;
731    }
732
733    // we do not support changing a tunneled surface after start
734    if (mTunneled) {
735        ALOGW("cannot change tunneled surface");
736        return INVALID_OPERATION;
737    }
738
739    int usageBits = 0;
740    // no need to reconnect as we will not dequeue all buffers
741    status_t err = setupNativeWindowSizeFormatAndUsage(
742            nativeWindow, &usageBits, !storingMetadataInDecodedBuffers());
743    if (err != OK) {
744        return err;
745    }
746
747    int ignoredFlags = kVideoGrallocUsage;
748    // New output surface is not allowed to add new usage flag except ignored ones.
749    if ((usageBits & ~(mNativeWindowUsageBits | ignoredFlags)) != 0) {
750        ALOGW("cannot change usage from %#x to %#x", mNativeWindowUsageBits, usageBits);
751        return BAD_VALUE;
752    }
753
754    // get min undequeued count. We cannot switch to a surface that has a higher
755    // undequeued count than we allocated.
756    int minUndequeuedBuffers = 0;
757    err = nativeWindow->query(
758            nativeWindow, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
759            &minUndequeuedBuffers);
760    if (err != 0) {
761        ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)",
762                strerror(-err), -err);
763        return err;
764    }
765    if (minUndequeuedBuffers > (int)mNumUndequeuedBuffers) {
766        ALOGE("new surface holds onto more buffers (%d) than planned for (%zu)",
767                minUndequeuedBuffers, mNumUndequeuedBuffers);
768        return BAD_VALUE;
769    }
770
771    // we cannot change the number of output buffers while OMX is running
772    // set up surface to the same count
773    Vector<BufferInfo> &buffers = mBuffers[kPortIndexOutput];
774    ALOGV("setting up surface for %zu buffers", buffers.size());
775
776    err = native_window_set_buffer_count(nativeWindow, buffers.size());
777    if (err != 0) {
778        ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err),
779                -err);
780        return err;
781    }
782
783    // need to enable allocation when attaching
784    surface->getIGraphicBufferProducer()->allowAllocation(true);
785
786    // for meta data mode, we move dequeud buffers to the new surface.
787    // for non-meta mode, we must move all registered buffers
788    for (size_t i = 0; i < buffers.size(); ++i) {
789        const BufferInfo &info = buffers[i];
790        // skip undequeued buffers for meta data mode
791        if (storingMetadataInDecodedBuffers()
792                && info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
793            ALOGV("skipping buffer");
794            continue;
795        }
796        ALOGV("attaching buffer %p", info.mGraphicBuffer->getNativeBuffer());
797
798        err = surface->attachBuffer(info.mGraphicBuffer->getNativeBuffer());
799        if (err != OK) {
800            ALOGE("failed to attach buffer %p to the new surface: %s (%d)",
801                    info.mGraphicBuffer->getNativeBuffer(),
802                    strerror(-err), -err);
803            return err;
804        }
805    }
806
807    // cancel undequeued buffers to new surface
808    if (!storingMetadataInDecodedBuffers()) {
809        for (size_t i = 0; i < buffers.size(); ++i) {
810            BufferInfo &info = buffers.editItemAt(i);
811            if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
812                ALOGV("canceling buffer %p", info.mGraphicBuffer->getNativeBuffer());
813                err = nativeWindow->cancelBuffer(
814                        nativeWindow, info.mGraphicBuffer->getNativeBuffer(), info.mFenceFd);
815                info.mFenceFd = -1;
816                if (err != OK) {
817                    ALOGE("failed to cancel buffer %p to the new surface: %s (%d)",
818                            info.mGraphicBuffer->getNativeBuffer(),
819                            strerror(-err), -err);
820                    return err;
821                }
822            }
823        }
824        // disallow further allocation
825        (void)surface->getIGraphicBufferProducer()->allowAllocation(false);
826    }
827
828    // push blank buffers to previous window if requested
829    if (mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown) {
830        pushBlankBuffersToNativeWindow(mNativeWindow.get());
831    }
832
833    mNativeWindow = nativeWindow;
834    mNativeWindowUsageBits = usageBits;
835    return OK;
836}
837
838status_t ACodec::setPortMode(int32_t portIndex, IOMX::PortMode mode) {
839    status_t err = mOMXNode->setPortMode(portIndex, mode);
840    if (err != OK) {
841        ALOGE("[%s] setPortMode on %s to %s failed w/ err %d",
842                mComponentName.c_str(),
843                portIndex == kPortIndexInput ? "input" : "output",
844                asString(mode),
845                err);
846        return err;
847    }
848
849    mPortMode[portIndex] = mode;
850    return OK;
851}
852
853status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) {
854    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
855
856    CHECK(mAllocator[portIndex] == NULL);
857    CHECK(mBuffers[portIndex].isEmpty());
858
859    status_t err;
860    if (mNativeWindow != NULL && portIndex == kPortIndexOutput) {
861        if (storingMetadataInDecodedBuffers()) {
862            err = allocateOutputMetadataBuffers();
863        } else {
864            err = allocateOutputBuffersFromNativeWindow();
865        }
866    } else {
867        OMX_PARAM_PORTDEFINITIONTYPE def;
868        InitOMXParams(&def);
869        def.nPortIndex = portIndex;
870
871        err = mOMXNode->getParameter(
872                OMX_IndexParamPortDefinition, &def, sizeof(def));
873
874        if (err == OK) {
875            const IOMX::PortMode &mode = mPortMode[portIndex];
876            size_t bufSize = def.nBufferSize;
877            // Always allocate VideoNativeMetadata if using ANWBuffer.
878            // OMX might use gralloc source internally, but we don't share
879            // metadata buffer with OMX, OMX has its own headers.
880            if (mode == IOMX::kPortModeDynamicANWBuffer) {
881                bufSize = sizeof(VideoNativeMetadata);
882            } else if (mode == IOMX::kPortModeDynamicNativeHandle) {
883                bufSize = sizeof(VideoNativeHandleMetadata);
884            }
885
886            size_t conversionBufferSize = 0;
887
888            sp<DataConverter> converter = mConverter[portIndex];
889            if (converter != NULL) {
890                // here we assume sane conversions of max 4:1, so result fits in int32
891                if (portIndex == kPortIndexInput) {
892                    conversionBufferSize = converter->sourceSize(bufSize);
893                } else {
894                    conversionBufferSize = converter->targetSize(bufSize);
895                }
896            }
897
898            size_t alignment = 32; // This is the value currently returned by
899                                   // MemoryDealer::getAllocationAlignment().
900                                   // TODO: Fix this when Treble has
901                                   // MemoryHeap/MemoryDealer.
902
903            ALOGV("[%s] Allocating %u buffers of size %zu (from %u using %s) on %s port",
904                    mComponentName.c_str(),
905                    def.nBufferCountActual, bufSize, def.nBufferSize, asString(mode),
906                    portIndex == kPortIndexInput ? "input" : "output");
907
908            // verify buffer sizes to avoid overflow in align()
909            if (bufSize == 0 || max(bufSize, conversionBufferSize) > kMaxCodecBufferSize) {
910                ALOGE("b/22885421");
911                return NO_MEMORY;
912            }
913
914            // don't modify bufSize as OMX may not expect it to increase after negotiation
915            size_t alignedSize = align(bufSize, alignment);
916            size_t alignedConvSize = align(conversionBufferSize, alignment);
917            if (def.nBufferCountActual > SIZE_MAX / (alignedSize + alignedConvSize)) {
918                ALOGE("b/22885421");
919                return NO_MEMORY;
920            }
921
922            if (mode != IOMX::kPortModePresetSecureBuffer) {
923                mAllocator[portIndex] = TAllocator::getService("ashmem");
924                if (mAllocator[portIndex] == nullptr) {
925                    ALOGE("hidl allocator on port %d is null",
926                            (int)portIndex);
927                    return NO_MEMORY;
928                }
929                // TODO: When Treble has MemoryHeap/MemoryDealer, we should
930                // specify the heap size to be
931                // def.nBufferCountActual * (alignedSize + alignedConvSize).
932            }
933
934            const sp<AMessage> &format =
935                    portIndex == kPortIndexInput ? mInputFormat : mOutputFormat;
936            for (OMX_U32 i = 0; i < def.nBufferCountActual && err == OK; ++i) {
937                hidl_memory hidlMemToken;
938                sp<TMemory> hidlMem;
939                sp<IMemory> mem;
940
941                BufferInfo info;
942                info.mStatus = BufferInfo::OWNED_BY_US;
943                info.mFenceFd = -1;
944                info.mRenderInfo = NULL;
945                info.mGraphicBuffer = NULL;
946                info.mNewGraphicBuffer = false;
947
948                if (mode == IOMX::kPortModePresetSecureBuffer) {
949                    void *ptr = NULL;
950                    sp<NativeHandle> native_handle;
951                    err = mOMXNode->allocateSecureBuffer(
952                            portIndex, bufSize, &info.mBufferID,
953                            &ptr, &native_handle);
954
955                    info.mData = (native_handle == NULL)
956                            ? new SecureBuffer(format, ptr, bufSize)
957                            : new SecureBuffer(format, native_handle, bufSize);
958                    info.mCodecData = info.mData;
959                } else {
960                    bool success;
961                    auto transStatus = mAllocator[portIndex]->allocate(
962                            bufSize,
963                            [&success, &hidlMemToken](
964                                    bool s,
965                                    hidl_memory const& m) {
966                                success = s;
967                                hidlMemToken = m;
968                            });
969
970                    if (!transStatus.isOk()) {
971                        ALOGE("hidl's AshmemAllocator failed at the "
972                                "transport: %s",
973                                transStatus.description().c_str());
974                        return NO_MEMORY;
975                    }
976                    if (!success) {
977                        return NO_MEMORY;
978                    }
979                    hidlMem = mapMemory(hidlMemToken);
980                    if (hidlMem == nullptr) {
981                        return NO_MEMORY;
982                    }
983                    err = mOMXNode->useBuffer(
984                            portIndex, hidlMemToken, &info.mBufferID);
985
986                    if (mode == IOMX::kPortModeDynamicANWBuffer) {
987                        VideoNativeMetadata* metaData = (VideoNativeMetadata*)(
988                                (void*)hidlMem->getPointer());
989                        metaData->nFenceFd = -1;
990                    }
991
992                    info.mCodecData = new SharedMemoryBuffer(
993                            format, hidlMem);
994                    info.mCodecRef = hidlMem;
995
996                    // if we require conversion, allocate conversion buffer for client use;
997                    // otherwise, reuse codec buffer
998                    if (mConverter[portIndex] != NULL) {
999                        CHECK_GT(conversionBufferSize, (size_t)0);
1000                        bool success;
1001                        mAllocator[portIndex]->allocate(
1002                                conversionBufferSize,
1003                                [&success, &hidlMemToken](
1004                                        bool s,
1005                                        hidl_memory const& m) {
1006                                    success = s;
1007                                    hidlMemToken = m;
1008                                });
1009                        if (!success) {
1010                            return NO_MEMORY;
1011                        }
1012                        hidlMem = mapMemory(hidlMemToken);
1013                        if (hidlMem == nullptr) {
1014                            return NO_MEMORY;
1015                        }
1016                        info.mData = new SharedMemoryBuffer(format, hidlMem);
1017                        info.mMemRef = hidlMem;
1018                    } else {
1019                        info.mData = info.mCodecData;
1020                        info.mMemRef = info.mCodecRef;
1021                    }
1022                }
1023
1024                mBuffers[portIndex].push(info);
1025            }
1026        }
1027    }
1028
1029    if (err != OK) {
1030        return err;
1031    }
1032
1033    std::vector<ACodecBufferChannel::BufferAndId> array(mBuffers[portIndex].size());
1034    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
1035        array[i] = {mBuffers[portIndex][i].mData, mBuffers[portIndex][i].mBufferID};
1036    }
1037    if (portIndex == kPortIndexInput) {
1038        mBufferChannel->setInputBufferArray(array);
1039    } else if (portIndex == kPortIndexOutput) {
1040        mBufferChannel->setOutputBufferArray(array);
1041    } else {
1042        TRESPASS();
1043    }
1044
1045    return OK;
1046}
1047
1048status_t ACodec::setupNativeWindowSizeFormatAndUsage(
1049        ANativeWindow *nativeWindow /* nonnull */, int *finalUsage /* nonnull */,
1050        bool reconnect) {
1051    OMX_PARAM_PORTDEFINITIONTYPE def;
1052    InitOMXParams(&def);
1053    def.nPortIndex = kPortIndexOutput;
1054
1055    status_t err = mOMXNode->getParameter(
1056            OMX_IndexParamPortDefinition, &def, sizeof(def));
1057
1058    if (err != OK) {
1059        return err;
1060    }
1061
1062    OMX_INDEXTYPE index;
1063    err = mOMXNode->getExtensionIndex(
1064            "OMX.google.android.index.AndroidNativeBufferConsumerUsage",
1065            &index);
1066
1067    if (err != OK) {
1068        // allow failure
1069        err = OK;
1070    } else {
1071        int usageBits = 0;
1072        if (nativeWindow->query(
1073                nativeWindow,
1074                NATIVE_WINDOW_CONSUMER_USAGE_BITS,
1075                &usageBits) == OK) {
1076            OMX_PARAM_U32TYPE params;
1077            InitOMXParams(&params);
1078            params.nPortIndex = kPortIndexOutput;
1079            params.nU32 = (OMX_U32)usageBits;
1080
1081            err = mOMXNode->setParameter(index, &params, sizeof(params));
1082
1083            if (err != OK) {
1084                ALOGE("Fail to set AndroidNativeBufferConsumerUsage: %d", err);
1085                return err;
1086            }
1087        }
1088    }
1089
1090    OMX_U32 usage = 0;
1091    err = mOMXNode->getGraphicBufferUsage(kPortIndexOutput, &usage);
1092    if (err != 0) {
1093        ALOGW("querying usage flags from OMX IL component failed: %d", err);
1094        // XXX: Currently this error is logged, but not fatal.
1095        usage = 0;
1096    }
1097    int omxUsage = usage;
1098
1099    if (mFlags & kFlagIsGrallocUsageProtected) {
1100        usage |= GRALLOC_USAGE_PROTECTED;
1101    }
1102
1103    usage |= kVideoGrallocUsage;
1104    *finalUsage = usage;
1105
1106    memset(&mLastNativeWindowCrop, 0, sizeof(mLastNativeWindowCrop));
1107    mLastNativeWindowDataSpace = HAL_DATASPACE_UNKNOWN;
1108
1109    ALOGV("gralloc usage: %#x(OMX) => %#x(ACodec)", omxUsage, usage);
1110    return setNativeWindowSizeFormatAndUsage(
1111            nativeWindow,
1112            def.format.video.nFrameWidth,
1113            def.format.video.nFrameHeight,
1114            def.format.video.eColorFormat,
1115            mRotationDegrees,
1116            usage,
1117            reconnect);
1118}
1119
1120status_t ACodec::configureOutputBuffersFromNativeWindow(
1121        OMX_U32 *bufferCount, OMX_U32 *bufferSize,
1122        OMX_U32 *minUndequeuedBuffers, bool preregister) {
1123
1124    OMX_PARAM_PORTDEFINITIONTYPE def;
1125    InitOMXParams(&def);
1126    def.nPortIndex = kPortIndexOutput;
1127
1128    status_t err = mOMXNode->getParameter(
1129            OMX_IndexParamPortDefinition, &def, sizeof(def));
1130
1131    if (err == OK) {
1132        err = setupNativeWindowSizeFormatAndUsage(
1133                mNativeWindow.get(), &mNativeWindowUsageBits,
1134                preregister && !mTunneled /* reconnect */);
1135    }
1136    if (err != OK) {
1137        mNativeWindowUsageBits = 0;
1138        return err;
1139    }
1140
1141    // Exits here for tunneled video playback codecs -- i.e. skips native window
1142    // buffer allocation step as this is managed by the tunneled OMX omponent
1143    // itself and explicitly sets def.nBufferCountActual to 0.
1144    if (mTunneled) {
1145        ALOGV("Tunneled Playback: skipping native window buffer allocation.");
1146        def.nBufferCountActual = 0;
1147        err = mOMXNode->setParameter(
1148                OMX_IndexParamPortDefinition, &def, sizeof(def));
1149
1150        *minUndequeuedBuffers = 0;
1151        *bufferCount = 0;
1152        *bufferSize = 0;
1153        return err;
1154    }
1155
1156    *minUndequeuedBuffers = 0;
1157    err = mNativeWindow->query(
1158            mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
1159            (int *)minUndequeuedBuffers);
1160
1161    if (err != 0) {
1162        ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)",
1163                strerror(-err), -err);
1164        return err;
1165    }
1166
1167    // FIXME: assume that surface is controlled by app (native window
1168    // returns the number for the case when surface is not controlled by app)
1169    // FIXME2: This means that minUndeqeueudBufs can be 1 larger than reported
1170    // For now, try to allocate 1 more buffer, but don't fail if unsuccessful
1171
1172    // Use conservative allocation while also trying to reduce starvation
1173    //
1174    // 1. allocate at least nBufferCountMin + minUndequeuedBuffers - that is the
1175    //    minimum needed for the consumer to be able to work
1176    // 2. try to allocate two (2) additional buffers to reduce starvation from
1177    //    the consumer
1178    //    plus an extra buffer to account for incorrect minUndequeuedBufs
1179    for (OMX_U32 extraBuffers = 2 + 1; /* condition inside loop */; extraBuffers--) {
1180        OMX_U32 newBufferCount =
1181            def.nBufferCountMin + *minUndequeuedBuffers + extraBuffers;
1182        def.nBufferCountActual = newBufferCount;
1183        err = mOMXNode->setParameter(
1184                OMX_IndexParamPortDefinition, &def, sizeof(def));
1185
1186        if (err == OK) {
1187            *minUndequeuedBuffers += extraBuffers;
1188            break;
1189        }
1190
1191        ALOGW("[%s] setting nBufferCountActual to %u failed: %d",
1192                mComponentName.c_str(), newBufferCount, err);
1193        /* exit condition */
1194        if (extraBuffers == 0) {
1195            return err;
1196        }
1197    }
1198
1199    err = native_window_set_buffer_count(
1200            mNativeWindow.get(), def.nBufferCountActual);
1201
1202    if (err != 0) {
1203        ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err),
1204                -err);
1205        return err;
1206    }
1207
1208    *bufferCount = def.nBufferCountActual;
1209    *bufferSize =  def.nBufferSize;
1210    return err;
1211}
1212
1213status_t ACodec::allocateOutputBuffersFromNativeWindow() {
1214    // This method only handles the non-metadata mode (or simulating legacy
1215    // mode with metadata, which is transparent to ACodec).
1216    CHECK(!storingMetadataInDecodedBuffers());
1217
1218    OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers;
1219    status_t err = configureOutputBuffersFromNativeWindow(
1220            &bufferCount, &bufferSize, &minUndequeuedBuffers, true /* preregister */);
1221    if (err != 0)
1222        return err;
1223    mNumUndequeuedBuffers = minUndequeuedBuffers;
1224
1225    static_cast<Surface*>(mNativeWindow.get())
1226            ->getIGraphicBufferProducer()->allowAllocation(true);
1227
1228    ALOGV("[%s] Allocating %u buffers from a native window of size %u on "
1229         "output port",
1230         mComponentName.c_str(), bufferCount, bufferSize);
1231
1232    // Dequeue buffers and send them to OMX
1233    for (OMX_U32 i = 0; i < bufferCount; i++) {
1234        ANativeWindowBuffer *buf;
1235        int fenceFd;
1236        err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf, &fenceFd);
1237        if (err != 0) {
1238            ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
1239            break;
1240        }
1241
1242        sp<GraphicBuffer> graphicBuffer(GraphicBuffer::from(buf));
1243        BufferInfo info;
1244        info.mStatus = BufferInfo::OWNED_BY_US;
1245        info.mFenceFd = fenceFd;
1246        info.mIsReadFence = false;
1247        info.mRenderInfo = NULL;
1248        info.mGraphicBuffer = graphicBuffer;
1249        info.mNewGraphicBuffer = false;
1250
1251        // TODO: We shouln't need to create MediaCodecBuffer. In metadata mode
1252        //       OMX doesn't use the shared memory buffer, but some code still
1253        //       access info.mData. Create an ABuffer as a placeholder.
1254        info.mData = new MediaCodecBuffer(mOutputFormat, new ABuffer(bufferSize));
1255        info.mCodecData = info.mData;
1256
1257        mBuffers[kPortIndexOutput].push(info);
1258
1259        IOMX::buffer_id bufferId;
1260        err = mOMXNode->useBuffer(kPortIndexOutput, graphicBuffer, &bufferId);
1261        if (err != 0) {
1262            ALOGE("registering GraphicBuffer %u with OMX IL component failed: "
1263                 "%d", i, err);
1264            break;
1265        }
1266
1267        mBuffers[kPortIndexOutput].editItemAt(i).mBufferID = bufferId;
1268
1269        ALOGV("[%s] Registered graphic buffer with ID %u (pointer = %p)",
1270             mComponentName.c_str(),
1271             bufferId, graphicBuffer.get());
1272    }
1273
1274    OMX_U32 cancelStart;
1275    OMX_U32 cancelEnd;
1276
1277    if (err != OK) {
1278        // If an error occurred while dequeuing we need to cancel any buffers
1279        // that were dequeued. Also cancel all if we're in legacy metadata mode.
1280        cancelStart = 0;
1281        cancelEnd = mBuffers[kPortIndexOutput].size();
1282    } else {
1283        // Return the required minimum undequeued buffers to the native window.
1284        cancelStart = bufferCount - minUndequeuedBuffers;
1285        cancelEnd = bufferCount;
1286    }
1287
1288    for (OMX_U32 i = cancelStart; i < cancelEnd; i++) {
1289        BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
1290        if (info->mStatus == BufferInfo::OWNED_BY_US) {
1291            status_t error = cancelBufferToNativeWindow(info);
1292            if (err == 0) {
1293                err = error;
1294            }
1295        }
1296    }
1297
1298    static_cast<Surface*>(mNativeWindow.get())
1299            ->getIGraphicBufferProducer()->allowAllocation(false);
1300
1301    return err;
1302}
1303
1304status_t ACodec::allocateOutputMetadataBuffers() {
1305    CHECK(storingMetadataInDecodedBuffers());
1306
1307    OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers;
1308    status_t err = configureOutputBuffersFromNativeWindow(
1309            &bufferCount, &bufferSize, &minUndequeuedBuffers,
1310            false /* preregister */);
1311    if (err != OK)
1312        return err;
1313    mNumUndequeuedBuffers = minUndequeuedBuffers;
1314
1315    ALOGV("[%s] Allocating %u meta buffers on output port",
1316         mComponentName.c_str(), bufferCount);
1317
1318    for (OMX_U32 i = 0; i < bufferCount; i++) {
1319        BufferInfo info;
1320        info.mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
1321        info.mFenceFd = -1;
1322        info.mRenderInfo = NULL;
1323        info.mGraphicBuffer = NULL;
1324        info.mNewGraphicBuffer = false;
1325        info.mDequeuedAt = mDequeueCounter;
1326
1327        info.mData = new MediaCodecBuffer(mOutputFormat, new ABuffer(bufferSize));
1328
1329        // Initialize fence fd to -1 to avoid warning in freeBuffer().
1330        ((VideoNativeMetadata *)info.mData->base())->nFenceFd = -1;
1331
1332        info.mCodecData = info.mData;
1333
1334        err = mOMXNode->useBuffer(kPortIndexOutput, OMXBuffer::sPreset, &info.mBufferID);
1335        mBuffers[kPortIndexOutput].push(info);
1336
1337        ALOGV("[%s] allocated meta buffer with ID %u",
1338                mComponentName.c_str(), info.mBufferID);
1339    }
1340
1341    mMetadataBuffersToSubmit = bufferCount - minUndequeuedBuffers;
1342    return err;
1343}
1344
1345status_t ACodec::submitOutputMetadataBuffer() {
1346    CHECK(storingMetadataInDecodedBuffers());
1347    if (mMetadataBuffersToSubmit == 0)
1348        return OK;
1349
1350    BufferInfo *info = dequeueBufferFromNativeWindow();
1351    if (info == NULL) {
1352        return ERROR_IO;
1353    }
1354
1355    ALOGV("[%s] submitting output meta buffer ID %u for graphic buffer %p",
1356          mComponentName.c_str(), info->mBufferID, info->mGraphicBuffer->handle);
1357
1358    --mMetadataBuffersToSubmit;
1359    info->checkWriteFence("submitOutputMetadataBuffer");
1360    return fillBuffer(info);
1361}
1362
1363status_t ACodec::waitForFence(int fd, const char *dbg ) {
1364    status_t res = OK;
1365    if (fd >= 0) {
1366        sp<Fence> fence = new Fence(fd);
1367        res = fence->wait(IOMX::kFenceTimeoutMs);
1368        ALOGW_IF(res != OK, "FENCE TIMEOUT for %d in %s", fd, dbg);
1369    }
1370    return res;
1371}
1372
1373// static
1374const char *ACodec::_asString(BufferInfo::Status s) {
1375    switch (s) {
1376        case BufferInfo::OWNED_BY_US:            return "OUR";
1377        case BufferInfo::OWNED_BY_COMPONENT:     return "COMPONENT";
1378        case BufferInfo::OWNED_BY_UPSTREAM:      return "UPSTREAM";
1379        case BufferInfo::OWNED_BY_DOWNSTREAM:    return "DOWNSTREAM";
1380        case BufferInfo::OWNED_BY_NATIVE_WINDOW: return "SURFACE";
1381        case BufferInfo::UNRECOGNIZED:           return "UNRECOGNIZED";
1382        default:                                 return "?";
1383    }
1384}
1385
1386void ACodec::dumpBuffers(OMX_U32 portIndex) {
1387    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
1388    ALOGI("[%s] %s port has %zu buffers:", mComponentName.c_str(),
1389            portIndex == kPortIndexInput ? "input" : "output", mBuffers[portIndex].size());
1390    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
1391        const BufferInfo &info = mBuffers[portIndex][i];
1392        ALOGI("  slot %2zu: #%8u %p/%p %s(%d) dequeued:%u",
1393                i, info.mBufferID, info.mGraphicBuffer.get(),
1394                info.mGraphicBuffer == NULL ? NULL : info.mGraphicBuffer->getNativeBuffer(),
1395                _asString(info.mStatus), info.mStatus, info.mDequeuedAt);
1396    }
1397}
1398
1399status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) {
1400    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
1401
1402    ALOGV("[%s] Calling cancelBuffer on buffer %u",
1403         mComponentName.c_str(), info->mBufferID);
1404
1405    info->checkWriteFence("cancelBufferToNativeWindow");
1406    int err = mNativeWindow->cancelBuffer(
1407        mNativeWindow.get(), info->mGraphicBuffer.get(), info->mFenceFd);
1408    info->mFenceFd = -1;
1409
1410    ALOGW_IF(err != 0, "[%s] can not return buffer %u to native window",
1411            mComponentName.c_str(), info->mBufferID);
1412    // change ownership even if cancelBuffer fails
1413    info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
1414
1415    return err;
1416}
1417
1418void ACodec::updateRenderInfoForDequeuedBuffer(
1419        ANativeWindowBuffer *buf, int fenceFd, BufferInfo *info) {
1420
1421    info->mRenderInfo =
1422        mRenderTracker.updateInfoForDequeuedBuffer(
1423                buf, fenceFd, info - &mBuffers[kPortIndexOutput][0]);
1424
1425    // check for any fences already signaled
1426    notifyOfRenderedFrames(false /* dropIncomplete */, info->mRenderInfo);
1427}
1428
1429void ACodec::onFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano) {
1430    if (mRenderTracker.onFrameRendered(mediaTimeUs, systemNano) != OK) {
1431        mRenderTracker.dumpRenderQueue();
1432    }
1433}
1434
1435void ACodec::notifyOfRenderedFrames(bool dropIncomplete, FrameRenderTracker::Info *until) {
1436    std::list<FrameRenderTracker::Info> done =
1437        mRenderTracker.checkFencesAndGetRenderedFrames(until, dropIncomplete);
1438
1439    // unlink untracked frames
1440    for (std::list<FrameRenderTracker::Info>::const_iterator it = done.cbegin();
1441            it != done.cend(); ++it) {
1442        ssize_t index = it->getIndex();
1443        if (index >= 0 && (size_t)index < mBuffers[kPortIndexOutput].size()) {
1444            mBuffers[kPortIndexOutput].editItemAt(index).mRenderInfo = NULL;
1445        } else if (index >= 0) {
1446            // THIS SHOULD NEVER HAPPEN
1447            ALOGE("invalid index %zd in %zu", index, mBuffers[kPortIndexOutput].size());
1448        }
1449    }
1450
1451    mCallback->onOutputFramesRendered(done);
1452}
1453
1454ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() {
1455    ANativeWindowBuffer *buf;
1456    CHECK(mNativeWindow.get() != NULL);
1457
1458    if (mTunneled) {
1459        ALOGW("dequeueBufferFromNativeWindow() should not be called in tunnel"
1460              " video playback mode mode!");
1461        return NULL;
1462    }
1463
1464    if (mFatalError) {
1465        ALOGW("not dequeuing from native window due to fatal error");
1466        return NULL;
1467    }
1468
1469    int fenceFd = -1;
1470    do {
1471        status_t err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf, &fenceFd);
1472        if (err != 0) {
1473            ALOGE("dequeueBuffer failed: %s(%d).", asString(err), err);
1474            return NULL;
1475        }
1476
1477        bool stale = false;
1478        for (size_t i = mBuffers[kPortIndexOutput].size(); i > 0;) {
1479            i--;
1480            BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
1481
1482            if (info->mGraphicBuffer != NULL &&
1483                    info->mGraphicBuffer->handle == buf->handle) {
1484                // Since consumers can attach buffers to BufferQueues, it is possible
1485                // that a known yet stale buffer can return from a surface that we
1486                // once used.  We can simply ignore this as we have already dequeued
1487                // this buffer properly.  NOTE: this does not eliminate all cases,
1488                // e.g. it is possible that we have queued the valid buffer to the
1489                // NW, and a stale copy of the same buffer gets dequeued - which will
1490                // be treated as the valid buffer by ACodec.
1491                if (info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
1492                    ALOGI("dequeued stale buffer %p. discarding", buf);
1493                    stale = true;
1494                    break;
1495                }
1496
1497                ALOGV("dequeued buffer #%u with age %u, graphicBuffer %p",
1498                        (unsigned)(info - &mBuffers[kPortIndexOutput][0]),
1499                        mDequeueCounter - info->mDequeuedAt,
1500                        info->mGraphicBuffer->handle);
1501
1502                info->mStatus = BufferInfo::OWNED_BY_US;
1503                info->setWriteFence(fenceFd, "dequeueBufferFromNativeWindow");
1504                updateRenderInfoForDequeuedBuffer(buf, fenceFd, info);
1505                return info;
1506            }
1507        }
1508
1509        // It is also possible to receive a previously unregistered buffer
1510        // in non-meta mode. These should be treated as stale buffers. The
1511        // same is possible in meta mode, in which case, it will be treated
1512        // as a normal buffer, which is not desirable.
1513        // TODO: fix this.
1514        if (!stale && !storingMetadataInDecodedBuffers()) {
1515            ALOGI("dequeued unrecognized (stale) buffer %p. discarding", buf);
1516            stale = true;
1517        }
1518        if (stale) {
1519            // TODO: detach stale buffer, but there is no API yet to do it.
1520            buf = NULL;
1521        }
1522    } while (buf == NULL);
1523
1524    // get oldest undequeued buffer
1525    BufferInfo *oldest = NULL;
1526    for (size_t i = mBuffers[kPortIndexOutput].size(); i > 0;) {
1527        i--;
1528        BufferInfo *info =
1529            &mBuffers[kPortIndexOutput].editItemAt(i);
1530        if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW &&
1531            (oldest == NULL ||
1532             // avoid potential issues from counter rolling over
1533             mDequeueCounter - info->mDequeuedAt >
1534                    mDequeueCounter - oldest->mDequeuedAt)) {
1535            oldest = info;
1536        }
1537    }
1538
1539    // it is impossible dequeue a buffer when there are no buffers with ANW
1540    CHECK(oldest != NULL);
1541    // it is impossible to dequeue an unknown buffer in non-meta mode, as the
1542    // while loop above does not complete
1543    CHECK(storingMetadataInDecodedBuffers());
1544
1545    // discard buffer in LRU info and replace with new buffer
1546    oldest->mGraphicBuffer = GraphicBuffer::from(buf);
1547    oldest->mNewGraphicBuffer = true;
1548    oldest->mStatus = BufferInfo::OWNED_BY_US;
1549    oldest->setWriteFence(fenceFd, "dequeueBufferFromNativeWindow for oldest");
1550    mRenderTracker.untrackFrame(oldest->mRenderInfo);
1551    oldest->mRenderInfo = NULL;
1552
1553    ALOGV("replaced oldest buffer #%u with age %u, graphicBuffer %p",
1554            (unsigned)(oldest - &mBuffers[kPortIndexOutput][0]),
1555            mDequeueCounter - oldest->mDequeuedAt,
1556            oldest->mGraphicBuffer->handle);
1557
1558    updateRenderInfoForDequeuedBuffer(buf, fenceFd, oldest);
1559    return oldest;
1560}
1561
1562status_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) {
1563    if (portIndex == kPortIndexInput) {
1564        mBufferChannel->setInputBufferArray({});
1565    } else {
1566        mBufferChannel->setOutputBufferArray({});
1567    }
1568
1569    status_t err = OK;
1570    for (size_t i = mBuffers[portIndex].size(); i > 0;) {
1571        i--;
1572        status_t err2 = freeBuffer(portIndex, i);
1573        if (err == OK) {
1574            err = err2;
1575        }
1576    }
1577
1578    mAllocator[portIndex].clear();
1579    return err;
1580}
1581
1582status_t ACodec::freeOutputBuffersNotOwnedByComponent() {
1583    status_t err = OK;
1584    for (size_t i = mBuffers[kPortIndexOutput].size(); i > 0;) {
1585        i--;
1586        BufferInfo *info =
1587            &mBuffers[kPortIndexOutput].editItemAt(i);
1588
1589        // At this time some buffers may still be with the component
1590        // or being drained.
1591        if (info->mStatus != BufferInfo::OWNED_BY_COMPONENT &&
1592            info->mStatus != BufferInfo::OWNED_BY_DOWNSTREAM) {
1593            status_t err2 = freeBuffer(kPortIndexOutput, i);
1594            if (err == OK) {
1595                err = err2;
1596            }
1597        }
1598    }
1599
1600    return err;
1601}
1602
1603status_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) {
1604    BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
1605    status_t err = OK;
1606
1607    // there should not be any fences in the metadata
1608    if (mPortMode[portIndex] == IOMX::kPortModeDynamicANWBuffer && info->mCodecData != NULL
1609            && info->mCodecData->size() >= sizeof(VideoNativeMetadata)) {
1610        int fenceFd = ((VideoNativeMetadata *)info->mCodecData->base())->nFenceFd;
1611        if (fenceFd >= 0) {
1612            ALOGW("unreleased fence (%d) in %s metadata buffer %zu",
1613                    fenceFd, portIndex == kPortIndexInput ? "input" : "output", i);
1614        }
1615    }
1616
1617    switch (info->mStatus) {
1618        case BufferInfo::OWNED_BY_US:
1619            if (portIndex == kPortIndexOutput && mNativeWindow != NULL) {
1620                (void)cancelBufferToNativeWindow(info);
1621            }
1622            // fall through
1623
1624        case BufferInfo::OWNED_BY_NATIVE_WINDOW:
1625            err = mOMXNode->freeBuffer(portIndex, info->mBufferID);
1626            break;
1627
1628        default:
1629            ALOGE("trying to free buffer not owned by us or ANW (%d)", info->mStatus);
1630            err = FAILED_TRANSACTION;
1631            break;
1632    }
1633
1634    if (info->mFenceFd >= 0) {
1635        ::close(info->mFenceFd);
1636    }
1637
1638    if (portIndex == kPortIndexOutput) {
1639        mRenderTracker.untrackFrame(info->mRenderInfo, i);
1640        info->mRenderInfo = NULL;
1641    }
1642
1643    // remove buffer even if mOMXNode->freeBuffer fails
1644    mBuffers[portIndex].removeAt(i);
1645    return err;
1646}
1647
1648ACodec::BufferInfo *ACodec::findBufferByID(
1649        uint32_t portIndex, IOMX::buffer_id bufferID, ssize_t *index) {
1650    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
1651        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
1652
1653        if (info->mBufferID == bufferID) {
1654            if (index != NULL) {
1655                *index = i;
1656            }
1657            return info;
1658        }
1659    }
1660
1661    ALOGE("Could not find buffer with ID %u", bufferID);
1662    return NULL;
1663}
1664
1665status_t ACodec::fillBuffer(BufferInfo *info) {
1666    status_t err;
1667    // Even in dynamic ANW buffer mode, if the graphic buffer is not changing,
1668    // send sPreset instead of the same graphic buffer, so that OMX server
1669    // side doesn't update the meta. In theory it should make no difference,
1670    // however when the same buffer is parcelled again, a new handle could be
1671    // created on server side, and some decoder doesn't recognize the handle
1672    // even if it's the same buffer.
1673    if (!storingMetadataInDecodedBuffers() || !info->mNewGraphicBuffer) {
1674        err = mOMXNode->fillBuffer(
1675            info->mBufferID, OMXBuffer::sPreset, info->mFenceFd);
1676    } else {
1677        err = mOMXNode->fillBuffer(
1678            info->mBufferID, info->mGraphicBuffer, info->mFenceFd);
1679    }
1680
1681    info->mNewGraphicBuffer = false;
1682    info->mFenceFd = -1;
1683    if (err == OK) {
1684        info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1685    }
1686    return err;
1687}
1688
1689status_t ACodec::setComponentRole(
1690        bool isEncoder, const char *mime) {
1691    const char *role = GetComponentRole(isEncoder, mime);
1692    if (role == NULL) {
1693        return BAD_VALUE;
1694    }
1695    status_t err = SetComponentRole(mOMXNode, role);
1696    if (err != OK) {
1697        ALOGW("[%s] Failed to set standard component role '%s'.",
1698             mComponentName.c_str(), role);
1699    }
1700    return err;
1701}
1702
1703status_t ACodec::configureCodec(
1704        const char *mime, const sp<AMessage> &msg) {
1705    int32_t encoder;
1706    if (!msg->findInt32("encoder", &encoder)) {
1707        encoder = false;
1708    }
1709
1710    sp<AMessage> inputFormat = new AMessage;
1711    sp<AMessage> outputFormat = new AMessage;
1712    mConfigFormat = msg;
1713
1714    mIsEncoder = encoder;
1715    mIsVideo = !strncasecmp(mime, "video/", 6);
1716    mIsImage = !strncasecmp(mime, "image/", 6);
1717
1718    mPortMode[kPortIndexInput] = IOMX::kPortModePresetByteBuffer;
1719    mPortMode[kPortIndexOutput] = IOMX::kPortModePresetByteBuffer;
1720
1721    status_t err = setComponentRole(encoder /* isEncoder */, mime);
1722
1723    if (err != OK) {
1724        return err;
1725    }
1726
1727    OMX_VIDEO_CONTROLRATETYPE bitrateMode;
1728    int32_t bitrate = 0, quality;
1729    // FLAC encoder or video encoder in constant quality mode doesn't need a
1730    // bitrate, other encoders do.
1731    if (encoder) {
1732        if (mIsVideo || mIsImage) {
1733            if (!findVideoBitrateControlInfo(msg, &bitrateMode, &bitrate, &quality)) {
1734                return INVALID_OPERATION;
1735            }
1736        } else if (strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)
1737            && !msg->findInt32("bitrate", &bitrate)) {
1738            return INVALID_OPERATION;
1739        }
1740    }
1741
1742    // propagate bitrate to the output so that the muxer has it
1743    if (encoder && msg->findInt32("bitrate", &bitrate)) {
1744        // Technically ISO spec says that 'bitrate' should be 0 for VBR even though it is the
1745        // average bitrate. We've been setting both bitrate and max-bitrate to this same value.
1746        outputFormat->setInt32("bitrate", bitrate);
1747        outputFormat->setInt32("max-bitrate", bitrate);
1748    }
1749
1750    int32_t storeMeta;
1751    if (encoder
1752            && msg->findInt32("android._input-metadata-buffer-type", &storeMeta)
1753            && storeMeta != kMetadataBufferTypeInvalid) {
1754        IOMX::PortMode mode;
1755        if (storeMeta == kMetadataBufferTypeNativeHandleSource) {
1756            mode = IOMX::kPortModeDynamicNativeHandle;
1757        } else if (storeMeta == kMetadataBufferTypeANWBuffer ||
1758                storeMeta == kMetadataBufferTypeGrallocSource) {
1759            mode = IOMX::kPortModeDynamicANWBuffer;
1760        } else {
1761            return BAD_VALUE;
1762        }
1763        err = setPortMode(kPortIndexInput, mode);
1764        if (err != OK) {
1765            return err;
1766        }
1767
1768        uint32_t usageBits;
1769        if (mOMXNode->getParameter(
1770                (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
1771                &usageBits, sizeof(usageBits)) == OK) {
1772            inputFormat->setInt32(
1773                    "using-sw-read-often", !!(usageBits & GRALLOC_USAGE_SW_READ_OFTEN));
1774        }
1775    }
1776
1777    int32_t prependSPSPPS = 0;
1778    if (encoder
1779            && msg->findInt32("prepend-sps-pps-to-idr-frames", &prependSPSPPS)
1780            && prependSPSPPS != 0) {
1781        OMX_INDEXTYPE index;
1782        err = mOMXNode->getExtensionIndex(
1783                "OMX.google.android.index.prependSPSPPSToIDRFrames", &index);
1784
1785        if (err == OK) {
1786            PrependSPSPPSToIDRFramesParams params;
1787            InitOMXParams(&params);
1788            params.bEnable = OMX_TRUE;
1789
1790            err = mOMXNode->setParameter(index, &params, sizeof(params));
1791        }
1792
1793        if (err != OK) {
1794            ALOGE("Encoder could not be configured to emit SPS/PPS before "
1795                  "IDR frames. (err %d)", err);
1796
1797            return err;
1798        }
1799    }
1800
1801    // Only enable metadata mode on encoder output if encoder can prepend
1802    // sps/pps to idr frames, since in metadata mode the bitstream is in an
1803    // opaque handle, to which we don't have access.
1804    if (encoder && mIsVideo) {
1805        OMX_BOOL enable = (OMX_BOOL) (prependSPSPPS
1806            && msg->findInt32("android._store-metadata-in-buffers-output", &storeMeta)
1807            && storeMeta != 0);
1808        if (mFlags & kFlagIsSecure) {
1809            enable = OMX_TRUE;
1810        }
1811
1812        err = setPortMode(kPortIndexOutput, enable ?
1813                IOMX::kPortModePresetSecureBuffer : IOMX::kPortModePresetByteBuffer);
1814        if (err != OK) {
1815            return err;
1816        }
1817
1818        if (!msg->findInt64(
1819                    "repeat-previous-frame-after",
1820                    &mRepeatFrameDelayUs)) {
1821            mRepeatFrameDelayUs = -1ll;
1822        }
1823
1824        // only allow 32-bit value, since we pass it as U32 to OMX.
1825        if (!msg->findInt64("max-pts-gap-to-encoder", &mMaxPtsGapUs)) {
1826            mMaxPtsGapUs = 0ll;
1827        } else if (mMaxPtsGapUs > INT32_MAX || mMaxPtsGapUs < INT32_MIN) {
1828            ALOGW("Unsupported value for max pts gap %lld", (long long) mMaxPtsGapUs);
1829            mMaxPtsGapUs = 0ll;
1830        }
1831
1832        if (!msg->findFloat("max-fps-to-encoder", &mMaxFps)) {
1833            mMaxFps = -1;
1834        }
1835
1836        // notify GraphicBufferSource to allow backward frames
1837        if (mMaxPtsGapUs < 0ll) {
1838            mMaxFps = -1;
1839        }
1840
1841        if (!msg->findDouble("time-lapse-fps", &mCaptureFps)) {
1842            mCaptureFps = -1.0;
1843        }
1844
1845        if (!msg->findInt32(
1846                    "create-input-buffers-suspended",
1847                    (int32_t*)&mCreateInputBuffersSuspended)) {
1848            mCreateInputBuffersSuspended = false;
1849        }
1850    }
1851
1852    // NOTE: we only use native window for video decoders
1853    sp<RefBase> obj;
1854    bool haveNativeWindow = msg->findObject("native-window", &obj)
1855            && obj != NULL && mIsVideo && !encoder;
1856    mUsingNativeWindow = haveNativeWindow;
1857    if (mIsVideo && !encoder) {
1858        inputFormat->setInt32("adaptive-playback", false);
1859
1860        int32_t usageProtected;
1861        if (msg->findInt32("protected", &usageProtected) && usageProtected) {
1862            if (!haveNativeWindow) {
1863                ALOGE("protected output buffers must be sent to an ANativeWindow");
1864                return PERMISSION_DENIED;
1865            }
1866            mFlags |= kFlagIsGrallocUsageProtected;
1867            mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
1868        }
1869    }
1870    if (mFlags & kFlagIsSecure) {
1871        // use native_handles for secure input buffers
1872        err = setPortMode(kPortIndexInput, IOMX::kPortModePresetSecureBuffer);
1873
1874        if (err != OK) {
1875            ALOGI("falling back to non-native_handles");
1876            setPortMode(kPortIndexInput, IOMX::kPortModePresetByteBuffer);
1877            err = OK; // ignore error for now
1878        }
1879    }
1880    if (haveNativeWindow) {
1881        sp<ANativeWindow> nativeWindow =
1882            static_cast<ANativeWindow *>(static_cast<Surface *>(obj.get()));
1883
1884        // START of temporary support for automatic FRC - THIS WILL BE REMOVED
1885        int32_t autoFrc;
1886        if (msg->findInt32("auto-frc", &autoFrc)) {
1887            bool enabled = autoFrc;
1888            OMX_CONFIG_BOOLEANTYPE config;
1889            InitOMXParams(&config);
1890            config.bEnabled = (OMX_BOOL)enabled;
1891            status_t temp = mOMXNode->setConfig(
1892                    (OMX_INDEXTYPE)OMX_IndexConfigAutoFramerateConversion,
1893                    &config, sizeof(config));
1894            if (temp == OK) {
1895                outputFormat->setInt32("auto-frc", enabled);
1896            } else if (enabled) {
1897                ALOGI("codec does not support requested auto-frc (err %d)", temp);
1898            }
1899        }
1900        // END of temporary support for automatic FRC
1901
1902        int32_t tunneled;
1903        if (msg->findInt32("feature-tunneled-playback", &tunneled) &&
1904            tunneled != 0) {
1905            ALOGI("Configuring TUNNELED video playback.");
1906            mTunneled = true;
1907
1908            int32_t audioHwSync = 0;
1909            if (!msg->findInt32("audio-hw-sync", &audioHwSync)) {
1910                ALOGW("No Audio HW Sync provided for video tunnel");
1911            }
1912            err = configureTunneledVideoPlayback(audioHwSync, nativeWindow);
1913            if (err != OK) {
1914                ALOGE("configureTunneledVideoPlayback(%d,%p) failed!",
1915                        audioHwSync, nativeWindow.get());
1916                return err;
1917            }
1918
1919            int32_t maxWidth = 0, maxHeight = 0;
1920            if (msg->findInt32("max-width", &maxWidth) &&
1921                    msg->findInt32("max-height", &maxHeight)) {
1922
1923                err = mOMXNode->prepareForAdaptivePlayback(
1924                        kPortIndexOutput, OMX_TRUE, maxWidth, maxHeight);
1925                if (err != OK) {
1926                    ALOGW("[%s] prepareForAdaptivePlayback failed w/ err %d",
1927                            mComponentName.c_str(), err);
1928                    // allow failure
1929                    err = OK;
1930                } else {
1931                    inputFormat->setInt32("max-width", maxWidth);
1932                    inputFormat->setInt32("max-height", maxHeight);
1933                    inputFormat->setInt32("adaptive-playback", true);
1934                }
1935            }
1936        } else {
1937            ALOGV("Configuring CPU controlled video playback.");
1938            mTunneled = false;
1939
1940            // Explicity reset the sideband handle of the window for
1941            // non-tunneled video in case the window was previously used
1942            // for a tunneled video playback.
1943            err = native_window_set_sideband_stream(nativeWindow.get(), NULL);
1944            if (err != OK) {
1945                ALOGE("set_sideband_stream(NULL) failed! (err %d).", err);
1946                return err;
1947            }
1948
1949            err = setPortMode(kPortIndexOutput, IOMX::kPortModeDynamicANWBuffer);
1950            if (err != OK) {
1951                // if adaptive playback has been requested, try JB fallback
1952                // NOTE: THIS FALLBACK MECHANISM WILL BE REMOVED DUE TO ITS
1953                // LARGE MEMORY REQUIREMENT
1954
1955                // we will not do adaptive playback on software accessed
1956                // surfaces as they never had to respond to changes in the
1957                // crop window, and we don't trust that they will be able to.
1958                int usageBits = 0;
1959                bool canDoAdaptivePlayback;
1960
1961                if (nativeWindow->query(
1962                        nativeWindow.get(),
1963                        NATIVE_WINDOW_CONSUMER_USAGE_BITS,
1964                        &usageBits) != OK) {
1965                    canDoAdaptivePlayback = false;
1966                } else {
1967                    canDoAdaptivePlayback =
1968                        (usageBits &
1969                                (GRALLOC_USAGE_SW_READ_MASK |
1970                                 GRALLOC_USAGE_SW_WRITE_MASK)) == 0;
1971                }
1972
1973                int32_t maxWidth = 0, maxHeight = 0;
1974                if (canDoAdaptivePlayback &&
1975                        msg->findInt32("max-width", &maxWidth) &&
1976                        msg->findInt32("max-height", &maxHeight)) {
1977                    ALOGV("[%s] prepareForAdaptivePlayback(%dx%d)",
1978                            mComponentName.c_str(), maxWidth, maxHeight);
1979
1980                    err = mOMXNode->prepareForAdaptivePlayback(
1981                            kPortIndexOutput, OMX_TRUE, maxWidth, maxHeight);
1982                    ALOGW_IF(err != OK,
1983                            "[%s] prepareForAdaptivePlayback failed w/ err %d",
1984                            mComponentName.c_str(), err);
1985
1986                    if (err == OK) {
1987                        inputFormat->setInt32("max-width", maxWidth);
1988                        inputFormat->setInt32("max-height", maxHeight);
1989                        inputFormat->setInt32("adaptive-playback", true);
1990                    }
1991                }
1992                // allow failure
1993                err = OK;
1994            } else {
1995                ALOGV("[%s] setPortMode on output to %s succeeded",
1996                        mComponentName.c_str(), asString(IOMX::kPortModeDynamicANWBuffer));
1997                CHECK(storingMetadataInDecodedBuffers());
1998                inputFormat->setInt32("adaptive-playback", true);
1999            }
2000
2001            int32_t push;
2002            if (msg->findInt32("push-blank-buffers-on-shutdown", &push)
2003                    && push != 0) {
2004                mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
2005            }
2006        }
2007
2008        int32_t rotationDegrees;
2009        if (msg->findInt32("rotation-degrees", &rotationDegrees)) {
2010            mRotationDegrees = rotationDegrees;
2011        } else {
2012            mRotationDegrees = 0;
2013        }
2014    }
2015
2016    AudioEncoding pcmEncoding = kAudioEncodingPcm16bit;
2017    (void)msg->findInt32("pcm-encoding", (int32_t*)&pcmEncoding);
2018    // invalid encodings will default to PCM-16bit in setupRawAudioFormat.
2019
2020    if (mIsVideo || mIsImage) {
2021        // determine need for software renderer
2022        bool usingSwRenderer = false;
2023        if (haveNativeWindow && mComponentName.startsWith("OMX.google.")) {
2024            usingSwRenderer = true;
2025            haveNativeWindow = false;
2026            (void)setPortMode(kPortIndexOutput, IOMX::kPortModePresetByteBuffer);
2027        } else if (haveNativeWindow && !storingMetadataInDecodedBuffers()) {
2028            err = setPortMode(kPortIndexOutput, IOMX::kPortModePresetANWBuffer);
2029            if (err != OK) {
2030                return err;
2031            }
2032        }
2033
2034        if (encoder) {
2035            err = setupVideoEncoder(mime, msg, outputFormat, inputFormat);
2036        } else {
2037            err = setupVideoDecoder(mime, msg, haveNativeWindow, usingSwRenderer, outputFormat);
2038        }
2039
2040        if (err != OK) {
2041            return err;
2042        }
2043
2044        if (haveNativeWindow) {
2045            mNativeWindow = static_cast<Surface *>(obj.get());
2046
2047            // fallback for devices that do not handle flex-YUV for native buffers
2048            int32_t requestedColorFormat = OMX_COLOR_FormatUnused;
2049            if (msg->findInt32("color-format", &requestedColorFormat) &&
2050                    requestedColorFormat == OMX_COLOR_FormatYUV420Flexible) {
2051                status_t err = getPortFormat(kPortIndexOutput, outputFormat);
2052                if (err != OK) {
2053                    return err;
2054                }
2055                int32_t colorFormat = OMX_COLOR_FormatUnused;
2056                OMX_U32 flexibleEquivalent = OMX_COLOR_FormatUnused;
2057                if (!outputFormat->findInt32("color-format", &colorFormat)) {
2058                    ALOGE("ouptut port did not have a color format (wrong domain?)");
2059                    return BAD_VALUE;
2060                }
2061                ALOGD("[%s] Requested output format %#x and got %#x.",
2062                        mComponentName.c_str(), requestedColorFormat, colorFormat);
2063                if (!IsFlexibleColorFormat(
2064                        mOMXNode, colorFormat, haveNativeWindow, &flexibleEquivalent)
2065                        || flexibleEquivalent != (OMX_U32)requestedColorFormat) {
2066                    // device did not handle flex-YUV request for native window, fall back
2067                    // to SW renderer
2068                    ALOGI("[%s] Falling back to software renderer", mComponentName.c_str());
2069                    mNativeWindow.clear();
2070                    mNativeWindowUsageBits = 0;
2071                    haveNativeWindow = false;
2072                    usingSwRenderer = true;
2073                    // TODO: implement adaptive-playback support for bytebuffer mode.
2074                    // This is done by SW codecs, but most HW codecs don't support it.
2075                    err = setPortMode(kPortIndexOutput, IOMX::kPortModePresetByteBuffer);
2076                    inputFormat->setInt32("adaptive-playback", false);
2077                    if (mFlags & kFlagIsGrallocUsageProtected) {
2078                        // fallback is not supported for protected playback
2079                        err = PERMISSION_DENIED;
2080                    } else if (err == OK) {
2081                        err = setupVideoDecoder(
2082                                mime, msg, haveNativeWindow, usingSwRenderer, outputFormat);
2083                    }
2084                }
2085            }
2086        }
2087
2088        if (usingSwRenderer) {
2089            outputFormat->setInt32("using-sw-renderer", 1);
2090        }
2091    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
2092        int32_t numChannels, sampleRate;
2093        if (!msg->findInt32("channel-count", &numChannels)
2094                || !msg->findInt32("sample-rate", &sampleRate)) {
2095            // Since we did not always check for these, leave them optional
2096            // and have the decoder figure it all out.
2097            err = OK;
2098        } else {
2099            err = setupRawAudioFormat(
2100                    encoder ? kPortIndexInput : kPortIndexOutput,
2101                    sampleRate,
2102                    numChannels);
2103        }
2104    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
2105        int32_t numChannels, sampleRate;
2106        if (!msg->findInt32("channel-count", &numChannels)
2107                || !msg->findInt32("sample-rate", &sampleRate)) {
2108            err = INVALID_OPERATION;
2109        } else {
2110            int32_t isADTS, aacProfile;
2111            int32_t sbrMode;
2112            int32_t maxOutputChannelCount;
2113            int32_t pcmLimiterEnable;
2114            drcParams_t drc;
2115            if (!msg->findInt32("is-adts", &isADTS)) {
2116                isADTS = 0;
2117            }
2118            if (!msg->findInt32("aac-profile", &aacProfile)) {
2119                aacProfile = OMX_AUDIO_AACObjectNull;
2120            }
2121            if (!msg->findInt32("aac-sbr-mode", &sbrMode)) {
2122                sbrMode = -1;
2123            }
2124
2125            if (!msg->findInt32("aac-max-output-channel_count", &maxOutputChannelCount)) {
2126                maxOutputChannelCount = -1;
2127            }
2128            if (!msg->findInt32("aac-pcm-limiter-enable", &pcmLimiterEnable)) {
2129                // value is unknown
2130                pcmLimiterEnable = -1;
2131            }
2132            if (!msg->findInt32("aac-encoded-target-level", &drc.encodedTargetLevel)) {
2133                // value is unknown
2134                drc.encodedTargetLevel = -1;
2135            }
2136            if (!msg->findInt32("aac-drc-cut-level", &drc.drcCut)) {
2137                // value is unknown
2138                drc.drcCut = -1;
2139            }
2140            if (!msg->findInt32("aac-drc-boost-level", &drc.drcBoost)) {
2141                // value is unknown
2142                drc.drcBoost = -1;
2143            }
2144            if (!msg->findInt32("aac-drc-heavy-compression", &drc.heavyCompression)) {
2145                // value is unknown
2146                drc.heavyCompression = -1;
2147            }
2148            if (!msg->findInt32("aac-target-ref-level", &drc.targetRefLevel)) {
2149                // value is unknown
2150                drc.targetRefLevel = -1;
2151            }
2152            if (!msg->findInt32("aac-drc-effect-type", &drc.effectType)) {
2153                // value is unknown
2154                drc.effectType = -2; // valid values are -1 and over
2155            }
2156
2157            err = setupAACCodec(
2158                    encoder, numChannels, sampleRate, bitrate, aacProfile,
2159                    isADTS != 0, sbrMode, maxOutputChannelCount, drc,
2160                    pcmLimiterEnable);
2161        }
2162    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) {
2163        err = setupAMRCodec(encoder, false /* isWAMR */, bitrate);
2164    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
2165        err = setupAMRCodec(encoder, true /* isWAMR */, bitrate);
2166    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW)
2167            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) {
2168        // These are PCM-like formats with a fixed sample rate but
2169        // a variable number of channels.
2170
2171        int32_t numChannels;
2172        if (!msg->findInt32("channel-count", &numChannels)) {
2173            err = INVALID_OPERATION;
2174        } else {
2175            int32_t sampleRate;
2176            if (!msg->findInt32("sample-rate", &sampleRate)) {
2177                sampleRate = 8000;
2178            }
2179            err = setupG711Codec(encoder, sampleRate, numChannels);
2180        }
2181    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)) {
2182        int32_t numChannels = 0, sampleRate = 0, compressionLevel = -1;
2183        if (encoder &&
2184                (!msg->findInt32("channel-count", &numChannels)
2185                        || !msg->findInt32("sample-rate", &sampleRate))) {
2186            ALOGE("missing channel count or sample rate for FLAC encoder");
2187            err = INVALID_OPERATION;
2188        } else {
2189            if (encoder) {
2190                if (!msg->findInt32(
2191                            "complexity", &compressionLevel) &&
2192                    !msg->findInt32(
2193                            "flac-compression-level", &compressionLevel)) {
2194                    compressionLevel = 5; // default FLAC compression level
2195                } else if (compressionLevel < 0) {
2196                    ALOGW("compression level %d outside [0..8] range, "
2197                          "using 0",
2198                          compressionLevel);
2199                    compressionLevel = 0;
2200                } else if (compressionLevel > 8) {
2201                    ALOGW("compression level %d outside [0..8] range, "
2202                          "using 8",
2203                          compressionLevel);
2204                    compressionLevel = 8;
2205                }
2206            }
2207            err = setupFlacCodec(
2208                    encoder, numChannels, sampleRate, compressionLevel);
2209        }
2210    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
2211        int32_t numChannels, sampleRate;
2212        if (encoder
2213                || !msg->findInt32("channel-count", &numChannels)
2214                || !msg->findInt32("sample-rate", &sampleRate)) {
2215            err = INVALID_OPERATION;
2216        } else {
2217            err = setupRawAudioFormat(kPortIndexInput, sampleRate, numChannels, pcmEncoding);
2218        }
2219    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AC3)) {
2220        int32_t numChannels;
2221        int32_t sampleRate;
2222        if (!msg->findInt32("channel-count", &numChannels)
2223                || !msg->findInt32("sample-rate", &sampleRate)) {
2224            err = INVALID_OPERATION;
2225        } else {
2226            err = setupAC3Codec(encoder, numChannels, sampleRate);
2227        }
2228    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_EAC3)) {
2229        int32_t numChannels;
2230        int32_t sampleRate;
2231        if (!msg->findInt32("channel-count", &numChannels)
2232                || !msg->findInt32("sample-rate", &sampleRate)) {
2233            err = INVALID_OPERATION;
2234        } else {
2235            err = setupEAC3Codec(encoder, numChannels, sampleRate);
2236        }
2237    }
2238
2239    if (err != OK) {
2240        return err;
2241    }
2242
2243    if (!msg->findInt32("encoder-delay", &mEncoderDelay)) {
2244        mEncoderDelay = 0;
2245    }
2246
2247    if (!msg->findInt32("encoder-padding", &mEncoderPadding)) {
2248        mEncoderPadding = 0;
2249    }
2250
2251    if (msg->findInt32("channel-mask", &mChannelMask)) {
2252        mChannelMaskPresent = true;
2253    } else {
2254        mChannelMaskPresent = false;
2255    }
2256
2257    int32_t maxInputSize;
2258    if (msg->findInt32("max-input-size", &maxInputSize)) {
2259        err = setMinBufferSize(kPortIndexInput, (size_t)maxInputSize);
2260        err = OK; // ignore error
2261    } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) {
2262        err = setMinBufferSize(kPortIndexInput, 8192);  // XXX
2263        err = OK; // ignore error
2264    }
2265
2266    int32_t priority;
2267    if (msg->findInt32("priority", &priority)) {
2268        err = setPriority(priority);
2269        err = OK; // ignore error
2270    }
2271
2272    int32_t rateInt = -1;
2273    float rateFloat = -1;
2274    if (!msg->findFloat("operating-rate", &rateFloat)) {
2275        msg->findInt32("operating-rate", &rateInt);
2276        rateFloat = (float)rateInt;  // 16MHz (FLINTMAX) is OK for upper bound.
2277    }
2278    if (rateFloat > 0) {
2279        err = setOperatingRate(rateFloat, mIsVideo);
2280        err = OK; // ignore errors
2281    }
2282
2283    if (err == OK) {
2284        err = setVendorParameters(msg);
2285        if (err != OK) {
2286            return err;
2287        }
2288    }
2289
2290    // NOTE: both mBaseOutputFormat and mOutputFormat are outputFormat to signal first frame.
2291    mBaseOutputFormat = outputFormat;
2292    mLastOutputFormat.clear();
2293
2294    err = getPortFormat(kPortIndexInput, inputFormat);
2295    if (err == OK) {
2296        err = getPortFormat(kPortIndexOutput, outputFormat);
2297        if (err == OK) {
2298            mInputFormat = inputFormat;
2299            mOutputFormat = outputFormat;
2300        }
2301    }
2302
2303    // create data converters if needed
2304    if (!mIsVideo && !mIsImage && err == OK) {
2305        AudioEncoding codecPcmEncoding = kAudioEncodingPcm16bit;
2306        if (encoder) {
2307            (void)mInputFormat->findInt32("pcm-encoding", (int32_t*)&codecPcmEncoding);
2308            mConverter[kPortIndexInput] = AudioConverter::Create(pcmEncoding, codecPcmEncoding);
2309            if (mConverter[kPortIndexInput] != NULL) {
2310                mInputFormat->setInt32("pcm-encoding", pcmEncoding);
2311            }
2312        } else {
2313            (void)mOutputFormat->findInt32("pcm-encoding", (int32_t*)&codecPcmEncoding);
2314            mConverter[kPortIndexOutput] = AudioConverter::Create(codecPcmEncoding, pcmEncoding);
2315            if (mConverter[kPortIndexOutput] != NULL) {
2316                mOutputFormat->setInt32("pcm-encoding", pcmEncoding);
2317            }
2318        }
2319    }
2320
2321    return err;
2322}
2323
2324status_t ACodec::setLatency(uint32_t latency) {
2325    OMX_PARAM_U32TYPE config;
2326    InitOMXParams(&config);
2327    config.nPortIndex = kPortIndexInput;
2328    config.nU32 = (OMX_U32)latency;
2329    status_t err = mOMXNode->setConfig(
2330            (OMX_INDEXTYPE)OMX_IndexConfigLatency,
2331            &config, sizeof(config));
2332    return err;
2333}
2334
2335status_t ACodec::getLatency(uint32_t *latency) {
2336    OMX_PARAM_U32TYPE config;
2337    InitOMXParams(&config);
2338    config.nPortIndex = kPortIndexInput;
2339    status_t err = mOMXNode->getConfig(
2340            (OMX_INDEXTYPE)OMX_IndexConfigLatency,
2341            &config, sizeof(config));
2342    if (err == OK) {
2343        *latency = config.nU32;
2344    }
2345    return err;
2346}
2347
2348status_t ACodec::setPriority(int32_t priority) {
2349    if (priority < 0) {
2350        return BAD_VALUE;
2351    }
2352    OMX_PARAM_U32TYPE config;
2353    InitOMXParams(&config);
2354    config.nU32 = (OMX_U32)priority;
2355    status_t temp = mOMXNode->setConfig(
2356            (OMX_INDEXTYPE)OMX_IndexConfigPriority,
2357            &config, sizeof(config));
2358    if (temp != OK) {
2359        ALOGI("codec does not support config priority (err %d)", temp);
2360    }
2361    return OK;
2362}
2363
2364status_t ACodec::setOperatingRate(float rateFloat, bool isVideo) {
2365    if (rateFloat < 0) {
2366        return BAD_VALUE;
2367    }
2368    OMX_U32 rate;
2369    if (isVideo) {
2370        if (rateFloat > 65535) {
2371            return BAD_VALUE;
2372        }
2373        rate = (OMX_U32)(rateFloat * 65536.0f + 0.5f);
2374    } else {
2375        if (rateFloat > UINT_MAX) {
2376            return BAD_VALUE;
2377        }
2378        rate = (OMX_U32)(rateFloat);
2379    }
2380    OMX_PARAM_U32TYPE config;
2381    InitOMXParams(&config);
2382    config.nU32 = rate;
2383    status_t err = mOMXNode->setConfig(
2384            (OMX_INDEXTYPE)OMX_IndexConfigOperatingRate,
2385            &config, sizeof(config));
2386    if (err != OK) {
2387        ALOGI("codec does not support config operating rate (err %d)", err);
2388    }
2389    return OK;
2390}
2391
2392status_t ACodec::getIntraRefreshPeriod(uint32_t *intraRefreshPeriod) {
2393    OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE params;
2394    InitOMXParams(&params);
2395    params.nPortIndex = kPortIndexOutput;
2396    status_t err = mOMXNode->getConfig(
2397            (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh, &params, sizeof(params));
2398    if (err == OK) {
2399        *intraRefreshPeriod = params.nRefreshPeriod;
2400        return OK;
2401    }
2402
2403    // Fallback to query through standard OMX index.
2404    OMX_VIDEO_PARAM_INTRAREFRESHTYPE refreshParams;
2405    InitOMXParams(&refreshParams);
2406    refreshParams.nPortIndex = kPortIndexOutput;
2407    refreshParams.eRefreshMode = OMX_VIDEO_IntraRefreshCyclic;
2408    err = mOMXNode->getParameter(
2409            OMX_IndexParamVideoIntraRefresh, &refreshParams, sizeof(refreshParams));
2410    if (err != OK || refreshParams.nCirMBs == 0) {
2411        *intraRefreshPeriod = 0;
2412        return OK;
2413    }
2414
2415    // Calculate period based on width and height
2416    uint32_t width, height;
2417    OMX_PARAM_PORTDEFINITIONTYPE def;
2418    InitOMXParams(&def);
2419    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
2420    def.nPortIndex = kPortIndexOutput;
2421    err = mOMXNode->getParameter(
2422            OMX_IndexParamPortDefinition, &def, sizeof(def));
2423    if (err != OK) {
2424        *intraRefreshPeriod = 0;
2425        return err;
2426    }
2427    width = video_def->nFrameWidth;
2428    height = video_def->nFrameHeight;
2429    // Use H.264/AVC MacroBlock size 16x16
2430    *intraRefreshPeriod = divUp((divUp(width, 16u) * divUp(height, 16u)), refreshParams.nCirMBs);
2431
2432    return OK;
2433}
2434
2435status_t ACodec::setIntraRefreshPeriod(uint32_t intraRefreshPeriod, bool inConfigure) {
2436    OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE params;
2437    InitOMXParams(&params);
2438    params.nPortIndex = kPortIndexOutput;
2439    params.nRefreshPeriod = intraRefreshPeriod;
2440    status_t err = mOMXNode->setConfig(
2441            (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh, &params, sizeof(params));
2442    if (err == OK) {
2443        return OK;
2444    }
2445
2446    // Only in configure state, a component could invoke setParameter.
2447    if (!inConfigure) {
2448        return INVALID_OPERATION;
2449    } else {
2450        ALOGI("[%s] try falling back to Cyclic", mComponentName.c_str());
2451    }
2452
2453    OMX_VIDEO_PARAM_INTRAREFRESHTYPE refreshParams;
2454    InitOMXParams(&refreshParams);
2455    refreshParams.nPortIndex = kPortIndexOutput;
2456    refreshParams.eRefreshMode = OMX_VIDEO_IntraRefreshCyclic;
2457
2458    if (intraRefreshPeriod == 0) {
2459        // 0 means disable intra refresh.
2460        refreshParams.nCirMBs = 0;
2461    } else {
2462        // Calculate macroblocks that need to be intra coded base on width and height
2463        uint32_t width, height;
2464        OMX_PARAM_PORTDEFINITIONTYPE def;
2465        InitOMXParams(&def);
2466        OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
2467        def.nPortIndex = kPortIndexOutput;
2468        err = mOMXNode->getParameter(
2469                OMX_IndexParamPortDefinition, &def, sizeof(def));
2470        if (err != OK) {
2471            return err;
2472        }
2473        width = video_def->nFrameWidth;
2474        height = video_def->nFrameHeight;
2475        // Use H.264/AVC MacroBlock size 16x16
2476        refreshParams.nCirMBs = divUp((divUp(width, 16u) * divUp(height, 16u)), intraRefreshPeriod);
2477    }
2478
2479    err = mOMXNode->setParameter(
2480            OMX_IndexParamVideoIntraRefresh,
2481            &refreshParams, sizeof(refreshParams));
2482    if (err != OK) {
2483        return err;
2484    }
2485
2486    return OK;
2487}
2488
2489status_t ACodec::configureTemporalLayers(
2490        const sp<AMessage> &msg, bool inConfigure, sp<AMessage> &outputFormat) {
2491    if (!mIsVideo || !mIsEncoder) {
2492        return INVALID_OPERATION;
2493    }
2494
2495    AString tsSchema;
2496    if (!msg->findString("ts-schema", &tsSchema)) {
2497        return OK;
2498    }
2499
2500    unsigned int numLayers = 0;
2501    unsigned int numBLayers = 0;
2502    int tags;
2503    char dummy;
2504    OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE pattern =
2505        OMX_VIDEO_AndroidTemporalLayeringPatternNone;
2506    if (sscanf(tsSchema.c_str(), "webrtc.vp8.%u-layer%c", &numLayers, &dummy) == 1
2507            && numLayers > 0) {
2508        pattern = OMX_VIDEO_AndroidTemporalLayeringPatternWebRTC;
2509    } else if ((tags = sscanf(tsSchema.c_str(), "android.generic.%u%c%u%c",
2510                    &numLayers, &dummy, &numBLayers, &dummy))
2511            && (tags == 1 || (tags == 3 && dummy == '+'))
2512            && numLayers > 0 && numLayers < UINT32_MAX - numBLayers) {
2513        numLayers += numBLayers;
2514        pattern = OMX_VIDEO_AndroidTemporalLayeringPatternAndroid;
2515    } else {
2516        ALOGI("Ignoring unsupported ts-schema [%s]", tsSchema.c_str());
2517        return BAD_VALUE;
2518    }
2519
2520    OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE layerParams;
2521    InitOMXParams(&layerParams);
2522    layerParams.nPortIndex = kPortIndexOutput;
2523
2524    status_t err = mOMXNode->getParameter(
2525            (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering,
2526            &layerParams, sizeof(layerParams));
2527
2528    if (err != OK) {
2529        return err;
2530    } else if (!(layerParams.eSupportedPatterns & pattern)) {
2531        return BAD_VALUE;
2532    }
2533
2534    numLayers = min(numLayers, layerParams.nLayerCountMax);
2535    numBLayers = min(numBLayers, layerParams.nBLayerCountMax);
2536
2537    if (!inConfigure) {
2538        OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE layerConfig;
2539        InitOMXParams(&layerConfig);
2540        layerConfig.nPortIndex = kPortIndexOutput;
2541        layerConfig.ePattern = pattern;
2542        layerConfig.nPLayerCountActual = numLayers - numBLayers;
2543        layerConfig.nBLayerCountActual = numBLayers;
2544        layerConfig.bBitrateRatiosSpecified = OMX_FALSE;
2545
2546        err = mOMXNode->setConfig(
2547                (OMX_INDEXTYPE)OMX_IndexConfigAndroidVideoTemporalLayering,
2548                &layerConfig, sizeof(layerConfig));
2549    } else {
2550        layerParams.ePattern = pattern;
2551        layerParams.nPLayerCountActual = numLayers - numBLayers;
2552        layerParams.nBLayerCountActual = numBLayers;
2553        layerParams.bBitrateRatiosSpecified = OMX_FALSE;
2554
2555        err = mOMXNode->setParameter(
2556                (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering,
2557                &layerParams, sizeof(layerParams));
2558    }
2559
2560    AString configSchema;
2561    if (pattern == OMX_VIDEO_AndroidTemporalLayeringPatternAndroid) {
2562        configSchema = AStringPrintf("android.generic.%u+%u", numLayers - numBLayers, numBLayers);
2563    } else if (pattern == OMX_VIDEO_AndroidTemporalLayeringPatternWebRTC) {
2564        configSchema = AStringPrintf("webrtc.vp8.%u", numLayers);
2565    }
2566
2567    if (err != OK) {
2568        ALOGW("Failed to set temporal layers to %s (requested %s)",
2569                configSchema.c_str(), tsSchema.c_str());
2570        return err;
2571    }
2572
2573    err = mOMXNode->getParameter(
2574            (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering,
2575            &layerParams, sizeof(layerParams));
2576
2577    if (err == OK) {
2578        ALOGD("Temporal layers requested:%s configured:%s got:%s(%u: P=%u, B=%u)",
2579                tsSchema.c_str(), configSchema.c_str(),
2580                asString(layerParams.ePattern), layerParams.ePattern,
2581                layerParams.nPLayerCountActual, layerParams.nBLayerCountActual);
2582
2583        if (outputFormat.get() == mOutputFormat.get()) {
2584            mOutputFormat = mOutputFormat->dup(); // trigger an output format change event
2585        }
2586        // assume we got what we configured
2587        outputFormat->setString("ts-schema", configSchema);
2588    }
2589    return err;
2590}
2591
2592status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) {
2593    OMX_PARAM_PORTDEFINITIONTYPE def;
2594    InitOMXParams(&def);
2595    def.nPortIndex = portIndex;
2596
2597    status_t err = mOMXNode->getParameter(
2598            OMX_IndexParamPortDefinition, &def, sizeof(def));
2599
2600    if (err != OK) {
2601        return err;
2602    }
2603
2604    if (def.nBufferSize >= size) {
2605        return OK;
2606    }
2607
2608    def.nBufferSize = size;
2609
2610    err = mOMXNode->setParameter(
2611            OMX_IndexParamPortDefinition, &def, sizeof(def));
2612
2613    if (err != OK) {
2614        return err;
2615    }
2616
2617    err = mOMXNode->getParameter(
2618            OMX_IndexParamPortDefinition, &def, sizeof(def));
2619
2620    if (err != OK) {
2621        return err;
2622    }
2623
2624    if (def.nBufferSize < size) {
2625        ALOGE("failed to set min buffer size to %zu (is still %u)", size, def.nBufferSize);
2626        return FAILED_TRANSACTION;
2627    }
2628
2629    return OK;
2630}
2631
2632status_t ACodec::selectAudioPortFormat(
2633        OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat) {
2634    OMX_AUDIO_PARAM_PORTFORMATTYPE format;
2635    InitOMXParams(&format);
2636
2637    format.nPortIndex = portIndex;
2638    for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
2639        format.nIndex = index;
2640        status_t err = mOMXNode->getParameter(
2641                OMX_IndexParamAudioPortFormat, &format, sizeof(format));
2642
2643        if (err != OK) {
2644            return err;
2645        }
2646
2647        if (format.eEncoding == desiredFormat) {
2648            break;
2649        }
2650
2651        if (index == kMaxIndicesToCheck) {
2652            ALOGW("[%s] stopping checking formats after %u: %s(%x)",
2653                    mComponentName.c_str(), index,
2654                    asString(format.eEncoding), format.eEncoding);
2655            return ERROR_UNSUPPORTED;
2656        }
2657    }
2658
2659    return mOMXNode->setParameter(
2660            OMX_IndexParamAudioPortFormat, &format, sizeof(format));
2661}
2662
2663status_t ACodec::setupAACCodec(
2664        bool encoder, int32_t numChannels, int32_t sampleRate,
2665        int32_t bitRate, int32_t aacProfile, bool isADTS, int32_t sbrMode,
2666        int32_t maxOutputChannelCount, const drcParams_t& drc,
2667        int32_t pcmLimiterEnable) {
2668    if (encoder && isADTS) {
2669        return -EINVAL;
2670    }
2671
2672    status_t err = setupRawAudioFormat(
2673            encoder ? kPortIndexInput : kPortIndexOutput,
2674            sampleRate,
2675            numChannels);
2676
2677    if (err != OK) {
2678        return err;
2679    }
2680
2681    if (encoder) {
2682        err = selectAudioPortFormat(kPortIndexOutput, OMX_AUDIO_CodingAAC);
2683
2684        if (err != OK) {
2685            return err;
2686        }
2687
2688        OMX_PARAM_PORTDEFINITIONTYPE def;
2689        InitOMXParams(&def);
2690        def.nPortIndex = kPortIndexOutput;
2691
2692        err = mOMXNode->getParameter(
2693                OMX_IndexParamPortDefinition, &def, sizeof(def));
2694
2695        if (err != OK) {
2696            return err;
2697        }
2698
2699        def.format.audio.bFlagErrorConcealment = OMX_TRUE;
2700        def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
2701
2702        err = mOMXNode->setParameter(
2703                OMX_IndexParamPortDefinition, &def, sizeof(def));
2704
2705        if (err != OK) {
2706            return err;
2707        }
2708
2709        OMX_AUDIO_PARAM_AACPROFILETYPE profile;
2710        InitOMXParams(&profile);
2711        profile.nPortIndex = kPortIndexOutput;
2712
2713        err = mOMXNode->getParameter(
2714                OMX_IndexParamAudioAac, &profile, sizeof(profile));
2715
2716        if (err != OK) {
2717            return err;
2718        }
2719
2720        profile.nChannels = numChannels;
2721
2722        profile.eChannelMode =
2723            (numChannels == 1)
2724                ? OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo;
2725
2726        profile.nSampleRate = sampleRate;
2727        profile.nBitRate = bitRate;
2728        profile.nAudioBandWidth = 0;
2729        profile.nFrameLength = 0;
2730        profile.nAACtools = OMX_AUDIO_AACToolAll;
2731        profile.nAACERtools = OMX_AUDIO_AACERNone;
2732        profile.eAACProfile = (OMX_AUDIO_AACPROFILETYPE) aacProfile;
2733        profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
2734        switch (sbrMode) {
2735        case 0:
2736            // disable sbr
2737            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR;
2738            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR;
2739            break;
2740        case 1:
2741            // enable single-rate sbr
2742            profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR;
2743            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR;
2744            break;
2745        case 2:
2746            // enable dual-rate sbr
2747            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR;
2748            profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR;
2749            break;
2750        case -1:
2751            // enable both modes -> the codec will decide which mode should be used
2752            profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR;
2753            profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR;
2754            break;
2755        default:
2756            // unsupported sbr mode
2757            return BAD_VALUE;
2758        }
2759
2760
2761        err = mOMXNode->setParameter(
2762                OMX_IndexParamAudioAac, &profile, sizeof(profile));
2763
2764        if (err != OK) {
2765            return err;
2766        }
2767
2768        return err;
2769    }
2770
2771    OMX_AUDIO_PARAM_AACPROFILETYPE profile;
2772    InitOMXParams(&profile);
2773    profile.nPortIndex = kPortIndexInput;
2774
2775    err = mOMXNode->getParameter(
2776            OMX_IndexParamAudioAac, &profile, sizeof(profile));
2777
2778    if (err != OK) {
2779        return err;
2780    }
2781
2782    profile.nChannels = numChannels;
2783    profile.nSampleRate = sampleRate;
2784
2785    profile.eAACStreamFormat =
2786        isADTS
2787            ? OMX_AUDIO_AACStreamFormatMP4ADTS
2788            : OMX_AUDIO_AACStreamFormatMP4FF;
2789
2790    OMX_AUDIO_PARAM_ANDROID_AACDRCPRESENTATIONTYPE presentation;
2791    InitOMXParams(&presentation);
2792    presentation.nMaxOutputChannels = maxOutputChannelCount;
2793    presentation.nDrcCut = drc.drcCut;
2794    presentation.nDrcBoost = drc.drcBoost;
2795    presentation.nHeavyCompression = drc.heavyCompression;
2796    presentation.nTargetReferenceLevel = drc.targetRefLevel;
2797    presentation.nEncodedTargetLevel = drc.encodedTargetLevel;
2798    presentation.nPCMLimiterEnable = pcmLimiterEnable;
2799    presentation.nDrcEffectType = drc.effectType;
2800
2801    status_t res = mOMXNode->setParameter(
2802            OMX_IndexParamAudioAac, &profile, sizeof(profile));
2803    if (res == OK) {
2804        // optional parameters, will not cause configuration failure
2805        if (mOMXNode->setParameter(
2806                (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAacDrcPresentation,
2807                &presentation, sizeof(presentation)) == ERROR_UNSUPPORTED) {
2808            // prior to 9.0 we used a different config structure and index
2809            OMX_AUDIO_PARAM_ANDROID_AACPRESENTATIONTYPE presentation8;
2810            InitOMXParams(&presentation8);
2811            presentation8.nMaxOutputChannels = presentation.nMaxOutputChannels;
2812            presentation8.nDrcCut = presentation.nDrcCut;
2813            presentation8.nDrcBoost = presentation.nDrcBoost;
2814            presentation8.nHeavyCompression = presentation.nHeavyCompression;
2815            presentation8.nTargetReferenceLevel = presentation.nTargetReferenceLevel;
2816            presentation8.nEncodedTargetLevel = presentation.nEncodedTargetLevel;
2817            presentation8.nPCMLimiterEnable = presentation.nPCMLimiterEnable;
2818            (void)mOMXNode->setParameter(
2819                (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAacPresentation,
2820                &presentation8, sizeof(presentation8));
2821        }
2822    } else {
2823        ALOGW("did not set AudioAndroidAacPresentation due to error %d when setting AudioAac", res);
2824    }
2825    mSampleRate = sampleRate;
2826    return res;
2827}
2828
2829status_t ACodec::setupAC3Codec(
2830        bool encoder, int32_t numChannels, int32_t sampleRate) {
2831    status_t err = setupRawAudioFormat(
2832            encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels);
2833
2834    if (err != OK) {
2835        return err;
2836    }
2837
2838    if (encoder) {
2839        ALOGW("AC3 encoding is not supported.");
2840        return INVALID_OPERATION;
2841    }
2842
2843    OMX_AUDIO_PARAM_ANDROID_AC3TYPE def;
2844    InitOMXParams(&def);
2845    def.nPortIndex = kPortIndexInput;
2846
2847    err = mOMXNode->getParameter(
2848            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, &def, sizeof(def));
2849
2850    if (err != OK) {
2851        return err;
2852    }
2853
2854    def.nChannels = numChannels;
2855    def.nSampleRate = sampleRate;
2856
2857    return mOMXNode->setParameter(
2858            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, &def, sizeof(def));
2859}
2860
2861status_t ACodec::setupEAC3Codec(
2862        bool encoder, int32_t numChannels, int32_t sampleRate) {
2863    status_t err = setupRawAudioFormat(
2864            encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels);
2865
2866    if (err != OK) {
2867        return err;
2868    }
2869
2870    if (encoder) {
2871        ALOGW("EAC3 encoding is not supported.");
2872        return INVALID_OPERATION;
2873    }
2874
2875    OMX_AUDIO_PARAM_ANDROID_EAC3TYPE def;
2876    InitOMXParams(&def);
2877    def.nPortIndex = kPortIndexInput;
2878
2879    err = mOMXNode->getParameter(
2880            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3, &def, sizeof(def));
2881
2882    if (err != OK) {
2883        return err;
2884    }
2885
2886    def.nChannels = numChannels;
2887    def.nSampleRate = sampleRate;
2888
2889    return mOMXNode->setParameter(
2890            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3, &def, sizeof(def));
2891}
2892
2893static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate(
2894        bool isAMRWB, int32_t bps) {
2895    if (isAMRWB) {
2896        if (bps <= 6600) {
2897            return OMX_AUDIO_AMRBandModeWB0;
2898        } else if (bps <= 8850) {
2899            return OMX_AUDIO_AMRBandModeWB1;
2900        } else if (bps <= 12650) {
2901            return OMX_AUDIO_AMRBandModeWB2;
2902        } else if (bps <= 14250) {
2903            return OMX_AUDIO_AMRBandModeWB3;
2904        } else if (bps <= 15850) {
2905            return OMX_AUDIO_AMRBandModeWB4;
2906        } else if (bps <= 18250) {
2907            return OMX_AUDIO_AMRBandModeWB5;
2908        } else if (bps <= 19850) {
2909            return OMX_AUDIO_AMRBandModeWB6;
2910        } else if (bps <= 23050) {
2911            return OMX_AUDIO_AMRBandModeWB7;
2912        }
2913
2914        // 23850 bps
2915        return OMX_AUDIO_AMRBandModeWB8;
2916    } else {  // AMRNB
2917        if (bps <= 4750) {
2918            return OMX_AUDIO_AMRBandModeNB0;
2919        } else if (bps <= 5150) {
2920            return OMX_AUDIO_AMRBandModeNB1;
2921        } else if (bps <= 5900) {
2922            return OMX_AUDIO_AMRBandModeNB2;
2923        } else if (bps <= 6700) {
2924            return OMX_AUDIO_AMRBandModeNB3;
2925        } else if (bps <= 7400) {
2926            return OMX_AUDIO_AMRBandModeNB4;
2927        } else if (bps <= 7950) {
2928            return OMX_AUDIO_AMRBandModeNB5;
2929        } else if (bps <= 10200) {
2930            return OMX_AUDIO_AMRBandModeNB6;
2931        }
2932
2933        // 12200 bps
2934        return OMX_AUDIO_AMRBandModeNB7;
2935    }
2936}
2937
2938status_t ACodec::setupAMRCodec(bool encoder, bool isWAMR, int32_t bitrate) {
2939    OMX_AUDIO_PARAM_AMRTYPE def;
2940    InitOMXParams(&def);
2941    def.nPortIndex = encoder ? kPortIndexOutput : kPortIndexInput;
2942
2943    status_t err = mOMXNode->getParameter(
2944            OMX_IndexParamAudioAmr, &def, sizeof(def));
2945
2946    if (err != OK) {
2947        return err;
2948    }
2949
2950    def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
2951    def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitrate);
2952
2953    err = mOMXNode->setParameter(
2954            OMX_IndexParamAudioAmr, &def, sizeof(def));
2955
2956    if (err != OK) {
2957        return err;
2958    }
2959
2960    return setupRawAudioFormat(
2961            encoder ? kPortIndexInput : kPortIndexOutput,
2962            isWAMR ? 16000 : 8000 /* sampleRate */,
2963            1 /* numChannels */);
2964}
2965
2966status_t ACodec::setupG711Codec(bool encoder, int32_t sampleRate, int32_t numChannels) {
2967    if (encoder) {
2968        return INVALID_OPERATION;
2969    }
2970
2971    return setupRawAudioFormat(
2972            kPortIndexInput, sampleRate, numChannels);
2973}
2974
2975status_t ACodec::setupFlacCodec(
2976        bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel) {
2977
2978    if (encoder) {
2979        OMX_AUDIO_PARAM_FLACTYPE def;
2980        InitOMXParams(&def);
2981        def.nPortIndex = kPortIndexOutput;
2982
2983        // configure compression level
2984        status_t err = mOMXNode->getParameter(OMX_IndexParamAudioFlac, &def, sizeof(def));
2985        if (err != OK) {
2986            ALOGE("setupFlacCodec(): Error %d getting OMX_IndexParamAudioFlac parameter", err);
2987            return err;
2988        }
2989        def.nCompressionLevel = compressionLevel;
2990        err = mOMXNode->setParameter(OMX_IndexParamAudioFlac, &def, sizeof(def));
2991        if (err != OK) {
2992            ALOGE("setupFlacCodec(): Error %d setting OMX_IndexParamAudioFlac parameter", err);
2993            return err;
2994        }
2995    }
2996
2997    return setupRawAudioFormat(
2998            encoder ? kPortIndexInput : kPortIndexOutput,
2999            sampleRate,
3000            numChannels);
3001}
3002
3003status_t ACodec::setupRawAudioFormat(
3004        OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels, AudioEncoding encoding) {
3005    OMX_PARAM_PORTDEFINITIONTYPE def;
3006    InitOMXParams(&def);
3007    def.nPortIndex = portIndex;
3008
3009    status_t err = mOMXNode->getParameter(
3010            OMX_IndexParamPortDefinition, &def, sizeof(def));
3011
3012    if (err != OK) {
3013        return err;
3014    }
3015
3016    def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
3017
3018    err = mOMXNode->setParameter(
3019            OMX_IndexParamPortDefinition, &def, sizeof(def));
3020
3021    if (err != OK) {
3022        return err;
3023    }
3024
3025    OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
3026    InitOMXParams(&pcmParams);
3027    pcmParams.nPortIndex = portIndex;
3028
3029    err = mOMXNode->getParameter(
3030            OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
3031
3032    if (err != OK) {
3033        return err;
3034    }
3035
3036    pcmParams.nChannels = numChannels;
3037    switch (encoding) {
3038        case kAudioEncodingPcm8bit:
3039            pcmParams.eNumData = OMX_NumericalDataUnsigned;
3040            pcmParams.nBitPerSample = 8;
3041            break;
3042        case kAudioEncodingPcmFloat:
3043            pcmParams.eNumData = OMX_NumericalDataFloat;
3044            pcmParams.nBitPerSample = 32;
3045            break;
3046        case kAudioEncodingPcm16bit:
3047            pcmParams.eNumData = OMX_NumericalDataSigned;
3048            pcmParams.nBitPerSample = 16;
3049            break;
3050        default:
3051            return BAD_VALUE;
3052    }
3053    pcmParams.bInterleaved = OMX_TRUE;
3054    pcmParams.nSamplingRate = sampleRate;
3055    pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
3056
3057    if (getOMXChannelMapping(numChannels, pcmParams.eChannelMapping) != OK) {
3058        return OMX_ErrorNone;
3059    }
3060
3061    err = mOMXNode->setParameter(
3062            OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
3063    // if we could not set up raw format to non-16-bit, try with 16-bit
3064    // NOTE: we will also verify this via readback, in case codec ignores these fields
3065    if (err != OK && encoding != kAudioEncodingPcm16bit) {
3066        pcmParams.eNumData = OMX_NumericalDataSigned;
3067        pcmParams.nBitPerSample = 16;
3068        err = mOMXNode->setParameter(
3069                OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
3070    }
3071    return err;
3072}
3073
3074status_t ACodec::configureTunneledVideoPlayback(
3075        int32_t audioHwSync, const sp<ANativeWindow> &nativeWindow) {
3076    native_handle_t* sidebandHandle;
3077
3078    status_t err = mOMXNode->configureVideoTunnelMode(
3079            kPortIndexOutput, OMX_TRUE, audioHwSync, &sidebandHandle);
3080    if (err != OK) {
3081        ALOGE("configureVideoTunnelMode failed! (err %d).", err);
3082        return err;
3083    }
3084
3085    err = native_window_set_sideband_stream(nativeWindow.get(), sidebandHandle);
3086    if (err != OK) {
3087        ALOGE("native_window_set_sideband_stream(%p) failed! (err %d).",
3088                sidebandHandle, err);
3089        return err;
3090    }
3091
3092    return OK;
3093}
3094
3095status_t ACodec::setVideoPortFormatType(
3096        OMX_U32 portIndex,
3097        OMX_VIDEO_CODINGTYPE compressionFormat,
3098        OMX_COLOR_FORMATTYPE colorFormat,
3099        bool usingNativeBuffers) {
3100    OMX_VIDEO_PARAM_PORTFORMATTYPE format;
3101    InitOMXParams(&format);
3102    format.nPortIndex = portIndex;
3103    format.nIndex = 0;
3104    bool found = false;
3105
3106    for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
3107        format.nIndex = index;
3108        status_t err = mOMXNode->getParameter(
3109                OMX_IndexParamVideoPortFormat,
3110                &format, sizeof(format));
3111
3112        if (err != OK) {
3113            return err;
3114        }
3115
3116        // substitute back flexible color format to codec supported format
3117        OMX_U32 flexibleEquivalent;
3118        if (compressionFormat == OMX_VIDEO_CodingUnused
3119                && IsFlexibleColorFormat(
3120                        mOMXNode, format.eColorFormat, usingNativeBuffers, &flexibleEquivalent)
3121                && colorFormat == flexibleEquivalent) {
3122            ALOGI("[%s] using color format %#x in place of %#x",
3123                    mComponentName.c_str(), format.eColorFormat, colorFormat);
3124            colorFormat = format.eColorFormat;
3125        }
3126
3127        // The following assertion is violated by TI's video decoder.
3128        // CHECK_EQ(format.nIndex, index);
3129
3130        if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) {
3131            if (portIndex == kPortIndexInput
3132                    && colorFormat == format.eColorFormat) {
3133                // eCompressionFormat does not seem right.
3134                found = true;
3135                break;
3136            }
3137            if (portIndex == kPortIndexOutput
3138                    && compressionFormat == format.eCompressionFormat) {
3139                // eColorFormat does not seem right.
3140                found = true;
3141                break;
3142            }
3143        }
3144
3145        if (format.eCompressionFormat == compressionFormat
3146            && format.eColorFormat == colorFormat) {
3147            found = true;
3148            break;
3149        }
3150
3151        if (index == kMaxIndicesToCheck) {
3152            ALOGW("[%s] stopping checking formats after %u: %s(%x)/%s(%x)",
3153                    mComponentName.c_str(), index,
3154                    asString(format.eCompressionFormat), format.eCompressionFormat,
3155                    asString(format.eColorFormat), format.eColorFormat);
3156        }
3157    }
3158
3159    if (!found) {
3160        return UNKNOWN_ERROR;
3161    }
3162
3163    status_t err = mOMXNode->setParameter(
3164            OMX_IndexParamVideoPortFormat, &format, sizeof(format));
3165
3166    return err;
3167}
3168
3169// Set optimal output format. OMX component lists output formats in the order
3170// of preference, but this got more complicated since the introduction of flexible
3171// YUV formats. We support a legacy behavior for applications that do not use
3172// surface output, do not specify an output format, but expect a "usable" standard
3173// OMX format. SW readable and standard formats must be flex-YUV.
3174//
3175// Suggested preference order:
3176// - optimal format for texture rendering (mediaplayer behavior)
3177// - optimal SW readable & texture renderable format (flex-YUV support)
3178// - optimal SW readable non-renderable format (flex-YUV bytebuffer support)
3179// - legacy "usable" standard formats
3180//
3181// For legacy support, we prefer a standard format, but will settle for a SW readable
3182// flex-YUV format.
3183status_t ACodec::setSupportedOutputFormat(bool getLegacyFlexibleFormat) {
3184    OMX_VIDEO_PARAM_PORTFORMATTYPE format, legacyFormat;
3185    InitOMXParams(&format);
3186    format.nPortIndex = kPortIndexOutput;
3187
3188    InitOMXParams(&legacyFormat);
3189    // this field will change when we find a suitable legacy format
3190    legacyFormat.eColorFormat = OMX_COLOR_FormatUnused;
3191
3192    for (OMX_U32 index = 0; ; ++index) {
3193        format.nIndex = index;
3194        status_t err = mOMXNode->getParameter(
3195                OMX_IndexParamVideoPortFormat, &format, sizeof(format));
3196        if (err != OK) {
3197            // no more formats, pick legacy format if found
3198            if (legacyFormat.eColorFormat != OMX_COLOR_FormatUnused) {
3199                 memcpy(&format, &legacyFormat, sizeof(format));
3200                 break;
3201            }
3202            return err;
3203        }
3204        if (format.eCompressionFormat != OMX_VIDEO_CodingUnused) {
3205            return OMX_ErrorBadParameter;
3206        }
3207        if (!getLegacyFlexibleFormat) {
3208            break;
3209        }
3210        // standard formats that were exposed to users before
3211        if (format.eColorFormat == OMX_COLOR_FormatYUV420Planar
3212                || format.eColorFormat == OMX_COLOR_FormatYUV420PackedPlanar
3213                || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
3214                || format.eColorFormat == OMX_COLOR_FormatYUV420PackedSemiPlanar
3215                || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar) {
3216            break;
3217        }
3218        // find best legacy non-standard format
3219        OMX_U32 flexibleEquivalent;
3220        if (legacyFormat.eColorFormat == OMX_COLOR_FormatUnused
3221                && IsFlexibleColorFormat(
3222                        mOMXNode, format.eColorFormat, false /* usingNativeBuffers */,
3223                        &flexibleEquivalent)
3224                && flexibleEquivalent == OMX_COLOR_FormatYUV420Flexible) {
3225            memcpy(&legacyFormat, &format, sizeof(format));
3226        }
3227    }
3228    return mOMXNode->setParameter(
3229            OMX_IndexParamVideoPortFormat, &format, sizeof(format));
3230}
3231
3232static const struct VideoCodingMapEntry {
3233    const char *mMime;
3234    OMX_VIDEO_CODINGTYPE mVideoCodingType;
3235} kVideoCodingMapEntry[] = {
3236    { MEDIA_MIMETYPE_VIDEO_AVC, OMX_VIDEO_CodingAVC },
3237    { MEDIA_MIMETYPE_VIDEO_HEVC, OMX_VIDEO_CodingHEVC },
3238    { MEDIA_MIMETYPE_VIDEO_MPEG4, OMX_VIDEO_CodingMPEG4 },
3239    { MEDIA_MIMETYPE_VIDEO_H263, OMX_VIDEO_CodingH263 },
3240    { MEDIA_MIMETYPE_VIDEO_MPEG2, OMX_VIDEO_CodingMPEG2 },
3241    { MEDIA_MIMETYPE_VIDEO_VP8, OMX_VIDEO_CodingVP8 },
3242    { MEDIA_MIMETYPE_VIDEO_VP9, OMX_VIDEO_CodingVP9 },
3243    { MEDIA_MIMETYPE_VIDEO_DOLBY_VISION, OMX_VIDEO_CodingDolbyVision },
3244    { MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC, OMX_VIDEO_CodingImageHEIC },
3245};
3246
3247static status_t GetVideoCodingTypeFromMime(
3248        const char *mime, OMX_VIDEO_CODINGTYPE *codingType) {
3249    for (size_t i = 0;
3250         i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]);
3251         ++i) {
3252        if (!strcasecmp(mime, kVideoCodingMapEntry[i].mMime)) {
3253            *codingType = kVideoCodingMapEntry[i].mVideoCodingType;
3254            return OK;
3255        }
3256    }
3257
3258    *codingType = OMX_VIDEO_CodingUnused;
3259
3260    return ERROR_UNSUPPORTED;
3261}
3262
3263static status_t GetMimeTypeForVideoCoding(
3264        OMX_VIDEO_CODINGTYPE codingType, AString *mime) {
3265    for (size_t i = 0;
3266         i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]);
3267         ++i) {
3268        if (codingType == kVideoCodingMapEntry[i].mVideoCodingType) {
3269            *mime = kVideoCodingMapEntry[i].mMime;
3270            return OK;
3271        }
3272    }
3273
3274    mime->clear();
3275
3276    return ERROR_UNSUPPORTED;
3277}
3278
3279status_t ACodec::setPortBufferNum(OMX_U32 portIndex, int bufferNum) {
3280    OMX_PARAM_PORTDEFINITIONTYPE def;
3281    InitOMXParams(&def);
3282    def.nPortIndex = portIndex;
3283    status_t err;
3284    ALOGD("Setting [%s] %s port buffer number: %d", mComponentName.c_str(),
3285            portIndex == kPortIndexInput ? "input" : "output", bufferNum);
3286    err = mOMXNode->getParameter(
3287        OMX_IndexParamPortDefinition, &def, sizeof(def));
3288    if (err != OK) {
3289        return err;
3290    }
3291    def.nBufferCountActual = bufferNum;
3292    err = mOMXNode->setParameter(
3293        OMX_IndexParamPortDefinition, &def, sizeof(def));
3294    if (err != OK) {
3295        // Component could reject this request.
3296        ALOGW("Fail to set [%s] %s port buffer number: %d", mComponentName.c_str(),
3297            portIndex == kPortIndexInput ? "input" : "output", bufferNum);
3298    }
3299    return OK;
3300}
3301
3302status_t ACodec::setupVideoDecoder(
3303        const char *mime, const sp<AMessage> &msg, bool haveNativeWindow,
3304        bool usingSwRenderer, sp<AMessage> &outputFormat) {
3305    int32_t width, height;
3306    if (!msg->findInt32("width", &width)
3307            || !msg->findInt32("height", &height)) {
3308        return INVALID_OPERATION;
3309    }
3310
3311    OMX_VIDEO_CODINGTYPE compressionFormat;
3312    status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
3313
3314    if (err != OK) {
3315        return err;
3316    }
3317
3318    if (compressionFormat == OMX_VIDEO_CodingHEVC) {
3319        int32_t profile;
3320        if (msg->findInt32("profile", &profile)) {
3321            // verify if Main10 profile is supported at all, and fail
3322            // immediately if it's not supported.
3323            if (profile == OMX_VIDEO_HEVCProfileMain10 ||
3324                profile == OMX_VIDEO_HEVCProfileMain10HDR10) {
3325                err = verifySupportForProfileAndLevel(
3326                        kPortIndexInput, profile, 0);
3327                if (err != OK) {
3328                    return err;
3329                }
3330            }
3331        }
3332    }
3333
3334    if (compressionFormat == OMX_VIDEO_CodingVP9) {
3335        OMX_VIDEO_PARAM_PROFILELEVELTYPE params;
3336        InitOMXParams(&params);
3337        params.nPortIndex = kPortIndexInput;
3338        // Check if VP9 decoder advertises supported profiles.
3339        params.nProfileIndex = 0;
3340        status_t err = mOMXNode->getParameter(
3341                OMX_IndexParamVideoProfileLevelQuerySupported,
3342                &params, sizeof(params));
3343        mIsLegacyVP9Decoder = err != OK;
3344    }
3345
3346    err = setVideoPortFormatType(
3347            kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
3348
3349    if (err != OK) {
3350        return err;
3351    }
3352
3353    int32_t tmp;
3354    if (msg->findInt32("color-format", &tmp)) {
3355        OMX_COLOR_FORMATTYPE colorFormat =
3356            static_cast<OMX_COLOR_FORMATTYPE>(tmp);
3357        err = setVideoPortFormatType(
3358                kPortIndexOutput, OMX_VIDEO_CodingUnused, colorFormat, haveNativeWindow);
3359        if (err != OK) {
3360            ALOGW("[%s] does not support color format %d",
3361                  mComponentName.c_str(), colorFormat);
3362            err = setSupportedOutputFormat(!haveNativeWindow /* getLegacyFlexibleFormat */);
3363        }
3364    } else {
3365        err = setSupportedOutputFormat(!haveNativeWindow /* getLegacyFlexibleFormat */);
3366    }
3367
3368    if (err != OK) {
3369        return err;
3370    }
3371
3372    // Set the component input buffer number to be |tmp|. If succeed,
3373    // component will set input port buffer number to be |tmp|. If fail,
3374    // component will keep the same buffer number as before.
3375    if (msg->findInt32("android._num-input-buffers", &tmp)) {
3376        err = setPortBufferNum(kPortIndexInput, tmp);
3377        if (err != OK)
3378            return err;
3379    }
3380
3381    // Set the component output buffer number to be |tmp|. If succeed,
3382    // component will set output port buffer number to be |tmp|. If fail,
3383    // component will keep the same buffer number as before.
3384    if (msg->findInt32("android._num-output-buffers", &tmp)) {
3385        err = setPortBufferNum(kPortIndexOutput, tmp);
3386        if (err != OK)
3387            return err;
3388    }
3389
3390    int32_t frameRateInt;
3391    float frameRateFloat;
3392    if (!msg->findFloat("frame-rate", &frameRateFloat)) {
3393        if (!msg->findInt32("frame-rate", &frameRateInt)) {
3394            frameRateInt = -1;
3395        }
3396        frameRateFloat = (float)frameRateInt;
3397    }
3398
3399    err = setVideoFormatOnPort(
3400            kPortIndexInput, width, height, compressionFormat, frameRateFloat);
3401
3402    if (err != OK) {
3403        return err;
3404    }
3405
3406    err = setVideoFormatOnPort(
3407            kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused);
3408
3409    if (err != OK) {
3410        return err;
3411    }
3412
3413    err = setColorAspectsForVideoDecoder(
3414            width, height, haveNativeWindow | usingSwRenderer, msg, outputFormat);
3415    if (err == ERROR_UNSUPPORTED) { // support is optional
3416        err = OK;
3417    }
3418
3419    if (err != OK) {
3420        return err;
3421    }
3422
3423    err = setHDRStaticInfoForVideoCodec(kPortIndexOutput, msg, outputFormat);
3424    if (err == ERROR_UNSUPPORTED) { // support is optional
3425        err = OK;
3426    }
3427    return err;
3428}
3429
3430status_t ACodec::initDescribeColorAspectsIndex() {
3431    status_t err = mOMXNode->getExtensionIndex(
3432            "OMX.google.android.index.describeColorAspects", &mDescribeColorAspectsIndex);
3433    if (err != OK) {
3434        mDescribeColorAspectsIndex = (OMX_INDEXTYPE)0;
3435    }
3436    return err;
3437}
3438
3439status_t ACodec::setCodecColorAspects(DescribeColorAspectsParams &params, bool verify) {
3440    status_t err = ERROR_UNSUPPORTED;
3441    if (mDescribeColorAspectsIndex) {
3442        err = mOMXNode->setConfig(mDescribeColorAspectsIndex, &params, sizeof(params));
3443    }
3444    ALOGV("[%s] setting color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) err=%d(%s)",
3445            mComponentName.c_str(),
3446            params.sAspects.mRange, asString(params.sAspects.mRange),
3447            params.sAspects.mPrimaries, asString(params.sAspects.mPrimaries),
3448            params.sAspects.mMatrixCoeffs, asString(params.sAspects.mMatrixCoeffs),
3449            params.sAspects.mTransfer, asString(params.sAspects.mTransfer),
3450            err, asString(err));
3451
3452    if (verify && err == OK) {
3453        err = getCodecColorAspects(params);
3454    }
3455
3456    ALOGW_IF(err == ERROR_UNSUPPORTED && mDescribeColorAspectsIndex,
3457            "[%s] setting color aspects failed even though codec advertises support",
3458            mComponentName.c_str());
3459    return err;
3460}
3461
3462status_t ACodec::setColorAspectsForVideoDecoder(
3463        int32_t width, int32_t height, bool usingNativeWindow,
3464        const sp<AMessage> &configFormat, sp<AMessage> &outputFormat) {
3465    DescribeColorAspectsParams params;
3466    InitOMXParams(&params);
3467    params.nPortIndex = kPortIndexOutput;
3468
3469    getColorAspectsFromFormat(configFormat, params.sAspects);
3470    if (usingNativeWindow) {
3471        setDefaultCodecColorAspectsIfNeeded(params.sAspects, width, height);
3472        // The default aspects will be set back to the output format during the
3473        // getFormat phase of configure(). Set non-Unspecified values back into the
3474        // format, in case component does not support this enumeration.
3475        setColorAspectsIntoFormat(params.sAspects, outputFormat);
3476    }
3477
3478    (void)initDescribeColorAspectsIndex();
3479
3480    // communicate color aspects to codec
3481    return setCodecColorAspects(params);
3482}
3483
3484status_t ACodec::getCodecColorAspects(DescribeColorAspectsParams &params) {
3485    status_t err = ERROR_UNSUPPORTED;
3486    if (mDescribeColorAspectsIndex) {
3487        err = mOMXNode->getConfig(mDescribeColorAspectsIndex, &params, sizeof(params));
3488    }
3489    ALOGV("[%s] got color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) err=%d(%s)",
3490            mComponentName.c_str(),
3491            params.sAspects.mRange, asString(params.sAspects.mRange),
3492            params.sAspects.mPrimaries, asString(params.sAspects.mPrimaries),
3493            params.sAspects.mMatrixCoeffs, asString(params.sAspects.mMatrixCoeffs),
3494            params.sAspects.mTransfer, asString(params.sAspects.mTransfer),
3495            err, asString(err));
3496    if (params.bRequestingDataSpace) {
3497        ALOGV("for dataspace %#x", params.nDataSpace);
3498    }
3499    if (err == ERROR_UNSUPPORTED && mDescribeColorAspectsIndex
3500            && !params.bRequestingDataSpace && !params.bDataSpaceChanged) {
3501        ALOGW("[%s] getting color aspects failed even though codec advertises support",
3502                mComponentName.c_str());
3503    }
3504    return err;
3505}
3506
3507status_t ACodec::getInputColorAspectsForVideoEncoder(sp<AMessage> &format) {
3508    DescribeColorAspectsParams params;
3509    InitOMXParams(&params);
3510    params.nPortIndex = kPortIndexInput;
3511    status_t err = getCodecColorAspects(params);
3512    if (err == OK) {
3513        // we only set encoder input aspects if codec supports them
3514        setColorAspectsIntoFormat(params.sAspects, format, true /* force */);
3515    }
3516    return err;
3517}
3518
3519status_t ACodec::getDataSpace(
3520        DescribeColorAspectsParams &params, android_dataspace *dataSpace /* nonnull */,
3521        bool tryCodec) {
3522    status_t err = OK;
3523    if (tryCodec) {
3524        // request dataspace guidance from codec.
3525        params.bRequestingDataSpace = OMX_TRUE;
3526        err = getCodecColorAspects(params);
3527        params.bRequestingDataSpace = OMX_FALSE;
3528        if (err == OK && params.nDataSpace != HAL_DATASPACE_UNKNOWN) {
3529            *dataSpace = (android_dataspace)params.nDataSpace;
3530            return err;
3531        } else if (err == ERROR_UNSUPPORTED) {
3532            // ignore not-implemented error for dataspace requests
3533            err = OK;
3534        }
3535    }
3536
3537    // this returns legacy versions if available
3538    *dataSpace = getDataSpaceForColorAspects(params.sAspects, true /* mayexpand */);
3539    ALOGV("[%s] using color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) "
3540          "and dataspace %#x",
3541            mComponentName.c_str(),
3542            params.sAspects.mRange, asString(params.sAspects.mRange),
3543            params.sAspects.mPrimaries, asString(params.sAspects.mPrimaries),
3544            params.sAspects.mMatrixCoeffs, asString(params.sAspects.mMatrixCoeffs),
3545            params.sAspects.mTransfer, asString(params.sAspects.mTransfer),
3546            *dataSpace);
3547    return err;
3548}
3549
3550
3551status_t ACodec::getColorAspectsAndDataSpaceForVideoDecoder(
3552        int32_t width, int32_t height, const sp<AMessage> &configFormat, sp<AMessage> &outputFormat,
3553        android_dataspace *dataSpace) {
3554    DescribeColorAspectsParams params;
3555    InitOMXParams(&params);
3556    params.nPortIndex = kPortIndexOutput;
3557
3558    // reset default format and get resulting format
3559    getColorAspectsFromFormat(configFormat, params.sAspects);
3560    if (dataSpace != NULL) {
3561        setDefaultCodecColorAspectsIfNeeded(params.sAspects, width, height);
3562    }
3563    status_t err = setCodecColorAspects(params, true /* readBack */);
3564
3565    // we always set specified aspects for decoders
3566    setColorAspectsIntoFormat(params.sAspects, outputFormat);
3567
3568    if (dataSpace != NULL) {
3569        status_t res = getDataSpace(params, dataSpace, err == OK /* tryCodec */);
3570        if (err == OK) {
3571            err = res;
3572        }
3573    }
3574
3575    return err;
3576}
3577
3578// initial video encoder setup for bytebuffer mode
3579status_t ACodec::setColorAspectsForVideoEncoder(
3580        const sp<AMessage> &configFormat, sp<AMessage> &outputFormat, sp<AMessage> &inputFormat) {
3581    // copy config to output format as this is not exposed via getFormat
3582    copyColorConfig(configFormat, outputFormat);
3583
3584    DescribeColorAspectsParams params;
3585    InitOMXParams(&params);
3586    params.nPortIndex = kPortIndexInput;
3587    getColorAspectsFromFormat(configFormat, params.sAspects);
3588
3589    (void)initDescribeColorAspectsIndex();
3590
3591    int32_t usingRecorder;
3592    if (configFormat->findInt32("android._using-recorder", &usingRecorder) && usingRecorder) {
3593        android_dataspace dataSpace = HAL_DATASPACE_BT709;
3594        int32_t width, height;
3595        if (configFormat->findInt32("width", &width)
3596                && configFormat->findInt32("height", &height)) {
3597            setDefaultCodecColorAspectsIfNeeded(params.sAspects, width, height);
3598            status_t err = getDataSpace(
3599                    params, &dataSpace, mDescribeColorAspectsIndex /* tryCodec */);
3600            if (err != OK) {
3601                return err;
3602            }
3603            setColorAspectsIntoFormat(params.sAspects, outputFormat);
3604        }
3605        inputFormat->setInt32("android._dataspace", (int32_t)dataSpace);
3606    }
3607
3608    // communicate color aspects to codec, but do not allow change of the platform aspects
3609    ColorAspects origAspects = params.sAspects;
3610    for (int triesLeft = 2; --triesLeft >= 0; ) {
3611        status_t err = setCodecColorAspects(params, true /* readBack */);
3612        if (err != OK
3613                || !ColorUtils::checkIfAspectsChangedAndUnspecifyThem(
3614                        params.sAspects, origAspects, true /* usePlatformAspects */)) {
3615            return err;
3616        }
3617        ALOGW_IF(triesLeft == 0, "[%s] Codec repeatedly changed requested ColorAspects.",
3618                mComponentName.c_str());
3619    }
3620    return OK;
3621}
3622
3623status_t ACodec::setHDRStaticInfoForVideoCodec(
3624        OMX_U32 portIndex, const sp<AMessage> &configFormat, sp<AMessage> &outputFormat) {
3625    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
3626
3627    DescribeHDRStaticInfoParams params;
3628    InitOMXParams(&params);
3629    params.nPortIndex = portIndex;
3630
3631    HDRStaticInfo *info = &params.sInfo;
3632    if (getHDRStaticInfoFromFormat(configFormat, info)) {
3633        setHDRStaticInfoIntoFormat(params.sInfo, outputFormat);
3634    }
3635
3636    (void)initDescribeHDRStaticInfoIndex();
3637
3638    // communicate HDR static Info to codec
3639    return setHDRStaticInfo(params);
3640}
3641
3642// subsequent initial video encoder setup for surface mode
3643status_t ACodec::setInitialColorAspectsForVideoEncoderSurfaceAndGetDataSpace(
3644        android_dataspace *dataSpace /* nonnull */) {
3645    DescribeColorAspectsParams params;
3646    InitOMXParams(&params);
3647    params.nPortIndex = kPortIndexInput;
3648    ColorAspects &aspects = params.sAspects;
3649
3650    // reset default format and store resulting format into both input and output formats
3651    getColorAspectsFromFormat(mConfigFormat, aspects);
3652    int32_t width, height;
3653    if (mInputFormat->findInt32("width", &width) && mInputFormat->findInt32("height", &height)) {
3654        setDefaultCodecColorAspectsIfNeeded(aspects, width, height);
3655    }
3656    setColorAspectsIntoFormat(aspects, mInputFormat);
3657    setColorAspectsIntoFormat(aspects, mOutputFormat);
3658
3659    // communicate color aspects to codec, but do not allow any change
3660    ColorAspects origAspects = aspects;
3661    status_t err = OK;
3662    for (int triesLeft = 2; mDescribeColorAspectsIndex && --triesLeft >= 0; ) {
3663        status_t err = setCodecColorAspects(params, true /* readBack */);
3664        if (err != OK || !ColorUtils::checkIfAspectsChangedAndUnspecifyThem(aspects, origAspects)) {
3665            break;
3666        }
3667        ALOGW_IF(triesLeft == 0, "[%s] Codec repeatedly changed requested ColorAspects.",
3668                mComponentName.c_str());
3669    }
3670
3671    *dataSpace = HAL_DATASPACE_BT709;
3672    aspects = origAspects; // restore desired color aspects
3673    status_t res = getDataSpace(
3674            params, dataSpace, err == OK && mDescribeColorAspectsIndex /* tryCodec */);
3675    if (err == OK) {
3676        err = res;
3677    }
3678    mInputFormat->setInt32("android._dataspace", (int32_t)*dataSpace);
3679    mInputFormat->setBuffer(
3680            "android._color-aspects", ABuffer::CreateAsCopy(&aspects, sizeof(aspects)));
3681
3682    // update input format with codec supported color aspects (basically set unsupported
3683    // aspects to Unspecified)
3684    if (err == OK) {
3685        (void)getInputColorAspectsForVideoEncoder(mInputFormat);
3686    }
3687
3688    ALOGV("set default color aspects, updated input format to %s, output format to %s",
3689            mInputFormat->debugString(4).c_str(), mOutputFormat->debugString(4).c_str());
3690
3691    return err;
3692}
3693
3694status_t ACodec::getHDRStaticInfoForVideoCodec(OMX_U32 portIndex, sp<AMessage> &format) {
3695    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
3696    DescribeHDRStaticInfoParams params;
3697    InitOMXParams(&params);
3698    params.nPortIndex = portIndex;
3699
3700    status_t err = getHDRStaticInfo(params);
3701    if (err == OK) {
3702        // we only set decodec output HDRStaticInfo if codec supports them
3703        setHDRStaticInfoIntoFormat(params.sInfo, format);
3704    }
3705    return err;
3706}
3707
3708status_t ACodec::initDescribeHDRStaticInfoIndex() {
3709    status_t err = mOMXNode->getExtensionIndex(
3710            "OMX.google.android.index.describeHDRStaticInfo", &mDescribeHDRStaticInfoIndex);
3711    if (err != OK) {
3712        mDescribeHDRStaticInfoIndex = (OMX_INDEXTYPE)0;
3713    }
3714    return err;
3715}
3716
3717status_t ACodec::setHDRStaticInfo(const DescribeHDRStaticInfoParams &params) {
3718    status_t err = ERROR_UNSUPPORTED;
3719    if (mDescribeHDRStaticInfoIndex) {
3720        err = mOMXNode->setConfig(mDescribeHDRStaticInfoIndex, &params, sizeof(params));
3721    }
3722
3723    const HDRStaticInfo *info = &params.sInfo;
3724    ALOGV("[%s] setting  HDRStaticInfo (R: %u %u, G: %u %u, B: %u, %u, W: %u, %u, "
3725            "MaxDispL: %u, MinDispL: %u, MaxContentL: %u, MaxFrameAvgL: %u)",
3726            mComponentName.c_str(),
3727            info->sType1.mR.x, info->sType1.mR.y, info->sType1.mG.x, info->sType1.mG.y,
3728            info->sType1.mB.x, info->sType1.mB.y, info->sType1.mW.x, info->sType1.mW.y,
3729            info->sType1.mMaxDisplayLuminance, info->sType1.mMinDisplayLuminance,
3730            info->sType1.mMaxContentLightLevel, info->sType1.mMaxFrameAverageLightLevel);
3731
3732    ALOGW_IF(err == ERROR_UNSUPPORTED && mDescribeHDRStaticInfoIndex,
3733            "[%s] setting HDRStaticInfo failed even though codec advertises support",
3734            mComponentName.c_str());
3735    return err;
3736}
3737
3738status_t ACodec::getHDRStaticInfo(DescribeHDRStaticInfoParams &params) {
3739    status_t err = ERROR_UNSUPPORTED;
3740    if (mDescribeHDRStaticInfoIndex) {
3741        err = mOMXNode->getConfig(mDescribeHDRStaticInfoIndex, &params, sizeof(params));
3742    }
3743
3744    ALOGW_IF(err == ERROR_UNSUPPORTED && mDescribeHDRStaticInfoIndex,
3745            "[%s] getting HDRStaticInfo failed even though codec advertises support",
3746            mComponentName.c_str());
3747    return err;
3748}
3749
3750status_t ACodec::setupVideoEncoder(
3751        const char *mime, const sp<AMessage> &msg,
3752        sp<AMessage> &outputFormat, sp<AMessage> &inputFormat) {
3753    int32_t tmp;
3754    if (!msg->findInt32("color-format", &tmp)) {
3755        return INVALID_OPERATION;
3756    }
3757
3758    OMX_COLOR_FORMATTYPE colorFormat =
3759        static_cast<OMX_COLOR_FORMATTYPE>(tmp);
3760
3761    status_t err = setVideoPortFormatType(
3762            kPortIndexInput, OMX_VIDEO_CodingUnused, colorFormat);
3763
3764    if (err != OK) {
3765        ALOGE("[%s] does not support color format %d",
3766              mComponentName.c_str(), colorFormat);
3767
3768        return err;
3769    }
3770
3771    /* Input port configuration */
3772
3773    OMX_PARAM_PORTDEFINITIONTYPE def;
3774    InitOMXParams(&def);
3775
3776    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
3777
3778    def.nPortIndex = kPortIndexInput;
3779
3780    err = mOMXNode->getParameter(
3781            OMX_IndexParamPortDefinition, &def, sizeof(def));
3782
3783    if (err != OK) {
3784        return err;
3785    }
3786
3787    OMX_VIDEO_CONTROLRATETYPE bitrateMode;
3788    int32_t width, height, bitrate = 0, quality;
3789    if (!msg->findInt32("width", &width)
3790            || !msg->findInt32("height", &height)
3791            || !findVideoBitrateControlInfo(
3792                    msg, &bitrateMode, &bitrate, &quality)) {
3793        return INVALID_OPERATION;
3794    }
3795
3796    video_def->nFrameWidth = width;
3797    video_def->nFrameHeight = height;
3798
3799    int32_t stride;
3800    if (!msg->findInt32("stride", &stride)) {
3801        stride = width;
3802    }
3803
3804    video_def->nStride = stride;
3805
3806    int32_t sliceHeight;
3807    if (!msg->findInt32("slice-height", &sliceHeight)) {
3808        sliceHeight = height;
3809    }
3810
3811    video_def->nSliceHeight = sliceHeight;
3812
3813    def.nBufferSize = (video_def->nStride * video_def->nSliceHeight * 3) / 2;
3814
3815    float framerate;
3816    if (!msg->findFloat("frame-rate", &framerate)) {
3817        int32_t tmp;
3818        if (!msg->findInt32("frame-rate", &tmp)) {
3819            return INVALID_OPERATION;
3820        }
3821        mFps = (double)tmp;
3822    } else {
3823        mFps = (double)framerate;
3824    }
3825    // propagate framerate to the output so that the muxer has it
3826    outputFormat->setInt32("frame-rate", (int32_t)mFps);
3827
3828    video_def->xFramerate = (OMX_U32)(mFps * 65536);
3829    video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
3830    // this is redundant as it was already set up in setVideoPortFormatType
3831    // FIXME for now skip this only for flexible YUV formats
3832    if (colorFormat != OMX_COLOR_FormatYUV420Flexible) {
3833        video_def->eColorFormat = colorFormat;
3834    }
3835
3836    err = mOMXNode->setParameter(
3837            OMX_IndexParamPortDefinition, &def, sizeof(def));
3838
3839    if (err != OK) {
3840        ALOGE("[%s] failed to set input port definition parameters.",
3841              mComponentName.c_str());
3842
3843        return err;
3844    }
3845
3846    /* Output port configuration */
3847
3848    OMX_VIDEO_CODINGTYPE compressionFormat;
3849    err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
3850
3851    if (err != OK) {
3852        return err;
3853    }
3854
3855    err = setVideoPortFormatType(
3856            kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused);
3857
3858    if (err != OK) {
3859        ALOGE("[%s] does not support compression format %d",
3860             mComponentName.c_str(), compressionFormat);
3861
3862        return err;
3863    }
3864
3865    def.nPortIndex = kPortIndexOutput;
3866
3867    err = mOMXNode->getParameter(
3868            OMX_IndexParamPortDefinition, &def, sizeof(def));
3869
3870    if (err != OK) {
3871        return err;
3872    }
3873
3874    video_def->nFrameWidth = width;
3875    video_def->nFrameHeight = height;
3876    video_def->xFramerate = 0;
3877    video_def->nBitrate = bitrate;
3878    video_def->eCompressionFormat = compressionFormat;
3879    video_def->eColorFormat = OMX_COLOR_FormatUnused;
3880
3881    err = mOMXNode->setParameter(
3882            OMX_IndexParamPortDefinition, &def, sizeof(def));
3883
3884    if (err != OK) {
3885        ALOGE("[%s] failed to set output port definition parameters.",
3886              mComponentName.c_str());
3887
3888        return err;
3889    }
3890
3891    int32_t intraRefreshPeriod = 0;
3892    if (msg->findInt32("intra-refresh-period", &intraRefreshPeriod)
3893            && intraRefreshPeriod >= 0) {
3894        err = setIntraRefreshPeriod((uint32_t)intraRefreshPeriod, true);
3895        if (err != OK) {
3896            ALOGI("[%s] failed setIntraRefreshPeriod. Failure is fine since this key is optional",
3897                    mComponentName.c_str());
3898            err = OK;
3899        }
3900    }
3901
3902    configureEncoderLatency(msg);
3903
3904    switch (compressionFormat) {
3905        case OMX_VIDEO_CodingMPEG4:
3906            err = setupMPEG4EncoderParameters(msg);
3907            break;
3908
3909        case OMX_VIDEO_CodingH263:
3910            err = setupH263EncoderParameters(msg);
3911            break;
3912
3913        case OMX_VIDEO_CodingAVC:
3914            err = setupAVCEncoderParameters(msg);
3915            break;
3916
3917        case OMX_VIDEO_CodingHEVC:
3918        case OMX_VIDEO_CodingImageHEIC:
3919            err = setupHEVCEncoderParameters(msg, outputFormat);
3920            break;
3921
3922        case OMX_VIDEO_CodingVP8:
3923        case OMX_VIDEO_CodingVP9:
3924            err = setupVPXEncoderParameters(msg, outputFormat);
3925            break;
3926
3927        default:
3928            break;
3929    }
3930
3931    if (err != OK) {
3932        return err;
3933    }
3934
3935    // Set up color aspects on input, but propagate them to the output format, as they will
3936    // not be read back from encoder.
3937    err = setColorAspectsForVideoEncoder(msg, outputFormat, inputFormat);
3938    if (err == ERROR_UNSUPPORTED) {
3939        ALOGI("[%s] cannot encode color aspects. Ignoring.", mComponentName.c_str());
3940        err = OK;
3941    }
3942
3943    if (err != OK) {
3944        return err;
3945    }
3946
3947    err = setHDRStaticInfoForVideoCodec(kPortIndexInput, msg, outputFormat);
3948    if (err == ERROR_UNSUPPORTED) { // support is optional
3949        ALOGI("[%s] cannot encode HDR static metadata. Ignoring.", mComponentName.c_str());
3950        err = OK;
3951    }
3952
3953    if (err != OK) {
3954        return err;
3955    }
3956
3957    switch (compressionFormat) {
3958        case OMX_VIDEO_CodingAVC:
3959        case OMX_VIDEO_CodingHEVC:
3960            err = configureTemporalLayers(msg, true /* inConfigure */, outputFormat);
3961            if (err != OK) {
3962                err = OK; // ignore failure
3963            }
3964            break;
3965
3966        case OMX_VIDEO_CodingVP8:
3967        case OMX_VIDEO_CodingVP9:
3968            // TODO: do we need to support android.generic layering? webrtc layering is
3969            // already set up in setupVPXEncoderParameters.
3970            break;
3971
3972        default:
3973            break;
3974    }
3975
3976    if (err == OK) {
3977        ALOGI("setupVideoEncoder succeeded");
3978    }
3979
3980    return err;
3981}
3982
3983status_t ACodec::setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode) {
3984    OMX_VIDEO_PARAM_INTRAREFRESHTYPE params;
3985    InitOMXParams(&params);
3986    params.nPortIndex = kPortIndexOutput;
3987
3988    params.eRefreshMode = static_cast<OMX_VIDEO_INTRAREFRESHTYPE>(mode);
3989
3990    if (params.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic ||
3991            params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) {
3992        int32_t mbs;
3993        if (!msg->findInt32("intra-refresh-CIR-mbs", &mbs)) {
3994            return INVALID_OPERATION;
3995        }
3996        params.nCirMBs = mbs;
3997    }
3998
3999    if (params.eRefreshMode == OMX_VIDEO_IntraRefreshAdaptive ||
4000            params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) {
4001        int32_t mbs;
4002        if (!msg->findInt32("intra-refresh-AIR-mbs", &mbs)) {
4003            return INVALID_OPERATION;
4004        }
4005        params.nAirMBs = mbs;
4006
4007        int32_t ref;
4008        if (!msg->findInt32("intra-refresh-AIR-ref", &ref)) {
4009            return INVALID_OPERATION;
4010        }
4011        params.nAirRef = ref;
4012    }
4013
4014    status_t err = mOMXNode->setParameter(
4015            OMX_IndexParamVideoIntraRefresh, &params, sizeof(params));
4016    return err;
4017}
4018
4019static OMX_U32 setPFramesSpacing(
4020        float iFramesInterval /* seconds */, int32_t frameRate, uint32_t BFramesSpacing = 0) {
4021    // BFramesSpacing is the number of B frames between I/P frames
4022    // PFramesSpacing (the value to be returned) is the number of P frames between I frames
4023    //
4024    // keyFrameInterval = ((PFramesSpacing + 1) * BFramesSpacing) + PFramesSpacing + 1
4025    //                                     ^^^                            ^^^        ^^^
4026    //                              number of B frames                number of P    I frame
4027    //
4028    //                  = (PFramesSpacing + 1) * (BFramesSpacing + 1)
4029    //
4030    // E.g.
4031    //      I   P   I  : I-interval: 8, nPFrames 1, nBFrames 3
4032    //       BBB BBB
4033
4034    if (iFramesInterval < 0) { // just 1 key frame
4035        return 0xFFFFFFFE; // don't use maxint as key-frame-interval calculation will add 1
4036    } else if (iFramesInterval == 0) { // just key frames
4037        return 0;
4038    }
4039
4040    // round down as key-frame-interval is an upper limit
4041    uint32_t keyFrameInterval = uint32_t(frameRate * iFramesInterval);
4042    OMX_U32 ret = keyFrameInterval / (BFramesSpacing + 1);
4043    return ret > 0 ? ret - 1 : 0;
4044}
4045
4046status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) {
4047    int32_t bitrate;
4048    float iFrameInterval;
4049    if (!msg->findInt32("bitrate", &bitrate)
4050            || !msg->findAsFloat("i-frame-interval", &iFrameInterval)) {
4051        return INVALID_OPERATION;
4052    }
4053
4054    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getVideoBitrateMode(msg);
4055
4056    float frameRate;
4057    if (!msg->findFloat("frame-rate", &frameRate)) {
4058        int32_t tmp;
4059        if (!msg->findInt32("frame-rate", &tmp)) {
4060            return INVALID_OPERATION;
4061        }
4062        frameRate = (float)tmp;
4063    }
4064
4065    OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type;
4066    InitOMXParams(&mpeg4type);
4067    mpeg4type.nPortIndex = kPortIndexOutput;
4068
4069    status_t err = mOMXNode->getParameter(
4070            OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
4071
4072    if (err != OK) {
4073        return err;
4074    }
4075
4076    mpeg4type.nSliceHeaderSpacing = 0;
4077    mpeg4type.bSVH = OMX_FALSE;
4078    mpeg4type.bGov = OMX_FALSE;
4079
4080    mpeg4type.nAllowedPictureTypes =
4081        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
4082
4083    mpeg4type.nBFrames = 0;
4084    mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, mpeg4type.nBFrames);
4085    if (mpeg4type.nPFrames == 0) {
4086        mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
4087    }
4088    mpeg4type.nIDCVLCThreshold = 0;
4089    mpeg4type.bACPred = OMX_TRUE;
4090    mpeg4type.nMaxPacketSize = 256;
4091    mpeg4type.nTimeIncRes = 1000;
4092    mpeg4type.nHeaderExtension = 0;
4093    mpeg4type.bReversibleVLC = OMX_FALSE;
4094
4095    int32_t profile;
4096    if (msg->findInt32("profile", &profile)) {
4097        int32_t level;
4098        if (!msg->findInt32("level", &level)) {
4099            return INVALID_OPERATION;
4100        }
4101
4102        err = verifySupportForProfileAndLevel(kPortIndexOutput, profile, level);
4103
4104        if (err != OK) {
4105            return err;
4106        }
4107
4108        mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile);
4109        mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level);
4110    }
4111
4112    err = mOMXNode->setParameter(
4113            OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
4114
4115    if (err != OK) {
4116        return err;
4117    }
4118
4119    err = configureBitrate(bitrateMode, bitrate);
4120
4121    if (err != OK) {
4122        return err;
4123    }
4124
4125    return setupErrorCorrectionParameters();
4126}
4127
4128status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) {
4129    int32_t bitrate;
4130    float iFrameInterval;
4131    if (!msg->findInt32("bitrate", &bitrate)
4132            || !msg->findAsFloat("i-frame-interval", &iFrameInterval)) {
4133        return INVALID_OPERATION;
4134    }
4135
4136    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getVideoBitrateMode(msg);
4137
4138    float frameRate;
4139    if (!msg->findFloat("frame-rate", &frameRate)) {
4140        int32_t tmp;
4141        if (!msg->findInt32("frame-rate", &tmp)) {
4142            return INVALID_OPERATION;
4143        }
4144        frameRate = (float)tmp;
4145    }
4146
4147    OMX_VIDEO_PARAM_H263TYPE h263type;
4148    InitOMXParams(&h263type);
4149    h263type.nPortIndex = kPortIndexOutput;
4150
4151    status_t err = mOMXNode->getParameter(
4152            OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
4153
4154    if (err != OK) {
4155        return err;
4156    }
4157
4158    h263type.nAllowedPictureTypes =
4159        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
4160
4161    h263type.nBFrames = 0;
4162    h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, h263type.nBFrames);
4163    if (h263type.nPFrames == 0) {
4164        h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
4165    }
4166
4167    int32_t profile;
4168    if (msg->findInt32("profile", &profile)) {
4169        int32_t level;
4170        if (!msg->findInt32("level", &level)) {
4171            return INVALID_OPERATION;
4172        }
4173
4174        err = verifySupportForProfileAndLevel(kPortIndexOutput, profile, level);
4175
4176        if (err != OK) {
4177            return err;
4178        }
4179
4180        h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile);
4181        h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level);
4182    }
4183
4184    h263type.bPLUSPTYPEAllowed = OMX_FALSE;
4185    h263type.bForceRoundingTypeToZero = OMX_FALSE;
4186    h263type.nPictureHeaderRepetition = 0;
4187    h263type.nGOBHeaderInterval = 0;
4188
4189    err = mOMXNode->setParameter(
4190            OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
4191
4192    if (err != OK) {
4193        return err;
4194    }
4195
4196    err = configureBitrate(bitrateMode, bitrate);
4197
4198    if (err != OK) {
4199        return err;
4200    }
4201
4202    return setupErrorCorrectionParameters();
4203}
4204
4205// static
4206int /* OMX_VIDEO_AVCLEVELTYPE */ ACodec::getAVCLevelFor(
4207        int width, int height, int rate, int bitrate,
4208        OMX_VIDEO_AVCPROFILEEXTTYPE profile) {
4209    // convert bitrate to main/baseline profile kbps equivalent
4210    switch ((uint32_t)profile) {
4211        case OMX_VIDEO_AVCProfileHigh10:
4212            bitrate = divUp(bitrate, 3000); break;
4213        case OMX_VIDEO_AVCProfileConstrainedHigh:
4214        case OMX_VIDEO_AVCProfileHigh:
4215            bitrate = divUp(bitrate, 1250); break;
4216        default:
4217            bitrate = divUp(bitrate, 1000); break;
4218    }
4219
4220    // convert size and rate to MBs
4221    width = divUp(width, 16);
4222    height = divUp(height, 16);
4223    int mbs = width * height;
4224    rate *= mbs;
4225    int maxDimension = max(width, height);
4226
4227    static const int limits[][5] = {
4228        /*   MBps     MB   dim  bitrate        level */
4229        {    1485,    99,  28,     64, OMX_VIDEO_AVCLevel1  },
4230        {    1485,    99,  28,    128, OMX_VIDEO_AVCLevel1b },
4231        {    3000,   396,  56,    192, OMX_VIDEO_AVCLevel11 },
4232        {    6000,   396,  56,    384, OMX_VIDEO_AVCLevel12 },
4233        {   11880,   396,  56,    768, OMX_VIDEO_AVCLevel13 },
4234        {   11880,   396,  56,   2000, OMX_VIDEO_AVCLevel2  },
4235        {   19800,   792,  79,   4000, OMX_VIDEO_AVCLevel21 },
4236        {   20250,  1620, 113,   4000, OMX_VIDEO_AVCLevel22 },
4237        {   40500,  1620, 113,  10000, OMX_VIDEO_AVCLevel3  },
4238        {  108000,  3600, 169,  14000, OMX_VIDEO_AVCLevel31 },
4239        {  216000,  5120, 202,  20000, OMX_VIDEO_AVCLevel32 },
4240        {  245760,  8192, 256,  20000, OMX_VIDEO_AVCLevel4  },
4241        {  245760,  8192, 256,  50000, OMX_VIDEO_AVCLevel41 },
4242        {  522240,  8704, 263,  50000, OMX_VIDEO_AVCLevel42 },
4243        {  589824, 22080, 420, 135000, OMX_VIDEO_AVCLevel5  },
4244        {  983040, 36864, 543, 240000, OMX_VIDEO_AVCLevel51 },
4245        { 2073600, 36864, 543, 240000, OMX_VIDEO_AVCLevel52 },
4246    };
4247
4248    for (size_t i = 0; i < ARRAY_SIZE(limits); i++) {
4249        const int (&limit)[5] = limits[i];
4250        if (rate <= limit[0] && mbs <= limit[1] && maxDimension <= limit[2]
4251                && bitrate <= limit[3]) {
4252            return limit[4];
4253        }
4254    }
4255    return 0;
4256}
4257
4258status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) {
4259    int32_t bitrate;
4260    float iFrameInterval;
4261    if (!msg->findInt32("bitrate", &bitrate)
4262            || !msg->findAsFloat("i-frame-interval", &iFrameInterval)) {
4263        return INVALID_OPERATION;
4264    }
4265
4266    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getVideoBitrateMode(msg);
4267
4268    float frameRate;
4269    if (!msg->findFloat("frame-rate", &frameRate)) {
4270        int32_t tmp;
4271        if (!msg->findInt32("frame-rate", &tmp)) {
4272            return INVALID_OPERATION;
4273        }
4274        frameRate = (float)tmp;
4275    }
4276
4277    status_t err = OK;
4278    int32_t intraRefreshMode = 0;
4279    if (msg->findInt32("intra-refresh-mode", &intraRefreshMode)) {
4280        err = setCyclicIntraMacroblockRefresh(msg, intraRefreshMode);
4281        if (err != OK) {
4282            ALOGE("Setting intra macroblock refresh mode (%d) failed: 0x%x",
4283                    err, intraRefreshMode);
4284            return err;
4285        }
4286    }
4287
4288    OMX_VIDEO_PARAM_AVCTYPE h264type;
4289    InitOMXParams(&h264type);
4290    h264type.nPortIndex = kPortIndexOutput;
4291
4292    err = mOMXNode->getParameter(
4293            OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
4294
4295    if (err != OK) {
4296        return err;
4297    }
4298
4299    h264type.nAllowedPictureTypes =
4300        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
4301
4302    int32_t profile;
4303    if (msg->findInt32("profile", &profile)) {
4304        int32_t level;
4305        if (!msg->findInt32("level", &level)) {
4306            return INVALID_OPERATION;
4307        }
4308
4309        err = verifySupportForProfileAndLevel(kPortIndexOutput, profile, level);
4310
4311        if (err != OK) {
4312            return err;
4313        }
4314
4315        h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile);
4316        h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level);
4317    } else {
4318        h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
4319#if 0   /* DON'T YET DEFAULT TO HIGHEST PROFILE */
4320        // Use largest supported profile for AVC recording if profile is not specified.
4321        for (OMX_VIDEO_AVCPROFILETYPE profile : {
4322                OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCProfileMain }) {
4323            if (verifySupportForProfileAndLevel(kPortIndexOutput, profile, 0) == OK) {
4324                h264type.eProfile = profile;
4325                break;
4326            }
4327        }
4328#endif
4329    }
4330
4331    ALOGI("setupAVCEncoderParameters with [profile: %s] [level: %s]",
4332            asString(h264type.eProfile), asString(h264type.eLevel));
4333
4334    if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
4335        h264type.nSliceHeaderSpacing = 0;
4336        h264type.bUseHadamard = OMX_TRUE;
4337        h264type.nRefFrames = 1;
4338        h264type.nBFrames = 0;
4339        h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, h264type.nBFrames);
4340        if (h264type.nPFrames == 0) {
4341            h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
4342        }
4343        h264type.nRefIdx10ActiveMinus1 = 0;
4344        h264type.nRefIdx11ActiveMinus1 = 0;
4345        h264type.bEntropyCodingCABAC = OMX_FALSE;
4346        h264type.bWeightedPPrediction = OMX_FALSE;
4347        h264type.bconstIpred = OMX_FALSE;
4348        h264type.bDirect8x8Inference = OMX_FALSE;
4349        h264type.bDirectSpatialTemporal = OMX_FALSE;
4350        h264type.nCabacInitIdc = 0;
4351    } else if (h264type.eProfile == OMX_VIDEO_AVCProfileMain ||
4352            h264type.eProfile == OMX_VIDEO_AVCProfileHigh) {
4353        h264type.nSliceHeaderSpacing = 0;
4354        h264type.bUseHadamard = OMX_TRUE;
4355        h264type.nRefFrames = 2;
4356        h264type.nBFrames = mLatency == 0 ? 1 : std::min(1U, mLatency - 1);
4357
4358        // disable B-frames until MPEG4Writer can guarantee finalizing files with B-frames
4359        h264type.nRefFrames = 1;
4360        h264type.nBFrames = 0;
4361
4362        h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, h264type.nBFrames);
4363        h264type.nAllowedPictureTypes =
4364            OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
4365        h264type.nRefIdx10ActiveMinus1 = 0;
4366        h264type.nRefIdx11ActiveMinus1 = 0;
4367        h264type.bEntropyCodingCABAC = OMX_TRUE;
4368        h264type.bWeightedPPrediction = OMX_TRUE;
4369        h264type.bconstIpred = OMX_TRUE;
4370        h264type.bDirect8x8Inference = OMX_TRUE;
4371        h264type.bDirectSpatialTemporal = OMX_TRUE;
4372        h264type.nCabacInitIdc = 1;
4373    }
4374
4375    if (h264type.nBFrames != 0) {
4376        h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
4377    }
4378
4379    h264type.bEnableUEP = OMX_FALSE;
4380    h264type.bEnableFMO = OMX_FALSE;
4381    h264type.bEnableASO = OMX_FALSE;
4382    h264type.bEnableRS = OMX_FALSE;
4383    h264type.bFrameMBsOnly = OMX_TRUE;
4384    h264type.bMBAFF = OMX_FALSE;
4385    h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
4386
4387    err = mOMXNode->setParameter(
4388            OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
4389
4390    if (err != OK) {
4391        return err;
4392    }
4393
4394    // TRICKY: if we are enabling temporal layering as well, some codecs may not support layering
4395    // when B-frames are enabled. Detect this now so we can disable B frames if temporal layering
4396    // is preferred.
4397    AString tsSchema;
4398    int32_t preferBFrames = (int32_t)false;
4399    if (msg->findString("ts-schema", &tsSchema)
4400            && (!msg->findInt32("android._prefer-b-frames", &preferBFrames) || !preferBFrames)) {
4401        OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE layering;
4402        InitOMXParams(&layering);
4403        layering.nPortIndex = kPortIndexOutput;
4404        if (mOMXNode->getParameter(
4405                        (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering,
4406                        &layering, sizeof(layering)) == OK
4407                && layering.eSupportedPatterns
4408                && layering.nBLayerCountMax == 0) {
4409            h264type.nBFrames = 0;
4410            h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, h264type.nBFrames);
4411            h264type.nAllowedPictureTypes &= ~OMX_VIDEO_PictureTypeB;
4412            ALOGI("disabling B-frames");
4413            err = mOMXNode->setParameter(
4414                    OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
4415
4416            if (err != OK) {
4417                return err;
4418            }
4419        }
4420    }
4421
4422    return configureBitrate(bitrateMode, bitrate);
4423}
4424
4425status_t ACodec::configureImageGrid(
4426        const sp<AMessage> &msg, sp<AMessage> &outputFormat) {
4427    int32_t tileWidth, tileHeight, gridRows, gridCols;
4428    if (!msg->findInt32("tile-width", &tileWidth) ||
4429        !msg->findInt32("tile-height", &tileHeight) ||
4430        !msg->findInt32("grid-rows", &gridRows) ||
4431        !msg->findInt32("grid-cols", &gridCols)) {
4432        return OK;
4433    }
4434
4435    OMX_VIDEO_PARAM_ANDROID_IMAGEGRIDTYPE gridType;
4436    InitOMXParams(&gridType);
4437    gridType.nPortIndex = kPortIndexOutput;
4438    gridType.bEnabled = OMX_TRUE;
4439    gridType.nTileWidth = tileWidth;
4440    gridType.nTileHeight = tileHeight;
4441    gridType.nGridRows = gridRows;
4442    gridType.nGridCols = gridCols;
4443
4444    status_t err = mOMXNode->setParameter(
4445            (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidImageGrid,
4446            &gridType, sizeof(gridType));
4447
4448    // for video encoders, grid config is only a hint.
4449    if (!mIsImage) {
4450        return OK;
4451    }
4452
4453    // image encoders must support grid config.
4454    if (err != OK) {
4455        return err;
4456    }
4457
4458    // query to get the image encoder's real grid config as it might be
4459    // different from the requested, and transfer that to the output.
4460    err = mOMXNode->getParameter(
4461            (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidImageGrid,
4462            &gridType, sizeof(gridType));
4463
4464    if (err == OK && gridType.bEnabled) {
4465        outputFormat->setInt32("tile-width", gridType.nTileWidth);
4466        outputFormat->setInt32("tile-height", gridType.nTileHeight);
4467        outputFormat->setInt32("grid-rows", gridType.nGridRows);
4468        outputFormat->setInt32("grid-cols", gridType.nGridCols);
4469    }
4470
4471    return err;
4472}
4473
4474status_t ACodec::setupHEVCEncoderParameters(
4475        const sp<AMessage> &msg, sp<AMessage> &outputFormat) {
4476    OMX_VIDEO_CONTROLRATETYPE bitrateMode;
4477    int32_t bitrate, quality;
4478    if (!findVideoBitrateControlInfo(msg, &bitrateMode, &bitrate, &quality)) {
4479        return INVALID_OPERATION;
4480    }
4481
4482    OMX_VIDEO_PARAM_HEVCTYPE hevcType;
4483    InitOMXParams(&hevcType);
4484    hevcType.nPortIndex = kPortIndexOutput;
4485
4486    status_t err = OK;
4487    err = mOMXNode->getParameter(
4488            (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
4489    if (err != OK) {
4490        return err;
4491    }
4492
4493    int32_t profile;
4494    if (msg->findInt32("profile", &profile)) {
4495        int32_t level;
4496        if (!msg->findInt32("level", &level)) {
4497            return INVALID_OPERATION;
4498        }
4499
4500        err = verifySupportForProfileAndLevel(kPortIndexOutput, profile, level);
4501        if (err != OK) {
4502            return err;
4503        }
4504
4505        hevcType.eProfile = static_cast<OMX_VIDEO_HEVCPROFILETYPE>(profile);
4506        hevcType.eLevel = static_cast<OMX_VIDEO_HEVCLEVELTYPE>(level);
4507    }
4508    // TODO: finer control?
4509    if (mIsImage) {
4510        hevcType.nKeyFrameInterval = 1;
4511    } else {
4512        float iFrameInterval;
4513        if (!msg->findAsFloat("i-frame-interval", &iFrameInterval)) {
4514            return INVALID_OPERATION;
4515        }
4516
4517        float frameRate;
4518        if (!msg->findFloat("frame-rate", &frameRate)) {
4519            int32_t tmp;
4520            if (!msg->findInt32("frame-rate", &tmp)) {
4521                return INVALID_OPERATION;
4522            }
4523            frameRate = (float)tmp;
4524        }
4525
4526        hevcType.nKeyFrameInterval =
4527                setPFramesSpacing(iFrameInterval, frameRate) + 1;
4528    }
4529
4530
4531    err = mOMXNode->setParameter(
4532            (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
4533    if (err != OK) {
4534        return err;
4535    }
4536
4537    err = configureImageGrid(msg, outputFormat);
4538
4539    if (err != OK) {
4540        return err;
4541    }
4542
4543    return configureBitrate(bitrateMode, bitrate, quality);
4544}
4545
4546status_t ACodec::setupVPXEncoderParameters(const sp<AMessage> &msg, sp<AMessage> &outputFormat) {
4547    int32_t bitrate;
4548    float iFrameInterval = 0;
4549    size_t tsLayers = 0;
4550    OMX_VIDEO_ANDROID_VPXTEMPORALLAYERPATTERNTYPE pattern =
4551        OMX_VIDEO_VPXTemporalLayerPatternNone;
4552    static const uint32_t kVp8LayerRateAlloction
4553        [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS]
4554        [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS] = {
4555        {100, 100, 100},  // 1 layer
4556        { 60, 100, 100},  // 2 layers {60%, 40%}
4557        { 40,  60, 100},  // 3 layers {40%, 20%, 40%}
4558    };
4559    if (!msg->findInt32("bitrate", &bitrate)) {
4560        return INVALID_OPERATION;
4561    }
4562    msg->findAsFloat("i-frame-interval", &iFrameInterval);
4563
4564    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getVideoBitrateMode(msg);
4565
4566    float frameRate;
4567    if (!msg->findFloat("frame-rate", &frameRate)) {
4568        int32_t tmp;
4569        if (!msg->findInt32("frame-rate", &tmp)) {
4570            return INVALID_OPERATION;
4571        }
4572        frameRate = (float)tmp;
4573    }
4574
4575    AString tsSchema;
4576    OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE tsType =
4577        OMX_VIDEO_AndroidTemporalLayeringPatternNone;
4578
4579    if (msg->findString("ts-schema", &tsSchema)) {
4580        unsigned int numLayers = 0;
4581        unsigned int numBLayers = 0;
4582        int tags;
4583        char dummy;
4584        if (sscanf(tsSchema.c_str(), "webrtc.vp8.%u-layer%c", &numLayers, &dummy) == 1
4585                && numLayers > 0) {
4586            pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
4587            tsType = OMX_VIDEO_AndroidTemporalLayeringPatternWebRTC;
4588            tsLayers = numLayers;
4589        } else if ((tags = sscanf(tsSchema.c_str(), "android.generic.%u%c%u%c",
4590                        &numLayers, &dummy, &numBLayers, &dummy))
4591                && (tags == 1 || (tags == 3 && dummy == '+'))
4592                && numLayers > 0 && numLayers < UINT32_MAX - numBLayers) {
4593            pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
4594            // VPX does not have a concept of B-frames, so just count all layers
4595            tsType = OMX_VIDEO_AndroidTemporalLayeringPatternAndroid;
4596            tsLayers = numLayers + numBLayers;
4597        } else {
4598            ALOGW("Ignoring unsupported ts-schema [%s]", tsSchema.c_str());
4599        }
4600        tsLayers = min(tsLayers, (size_t)OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS);
4601    }
4602
4603    OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type;
4604    InitOMXParams(&vp8type);
4605    vp8type.nPortIndex = kPortIndexOutput;
4606    status_t err = mOMXNode->getParameter(
4607            (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
4608            &vp8type, sizeof(vp8type));
4609
4610    if (err == OK) {
4611        if (iFrameInterval > 0) {
4612            vp8type.nKeyFrameInterval = setPFramesSpacing(iFrameInterval, frameRate) + 1;
4613        }
4614        vp8type.eTemporalPattern = pattern;
4615        vp8type.nTemporalLayerCount = tsLayers;
4616        if (tsLayers > 0) {
4617            for (size_t i = 0; i < OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS; i++) {
4618                vp8type.nTemporalLayerBitrateRatio[i] =
4619                    kVp8LayerRateAlloction[tsLayers - 1][i];
4620            }
4621        }
4622        if (bitrateMode == OMX_Video_ControlRateConstant) {
4623            vp8type.nMinQuantizer = 2;
4624            vp8type.nMaxQuantizer = 63;
4625        }
4626
4627        err = mOMXNode->setParameter(
4628                (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
4629                &vp8type, sizeof(vp8type));
4630        if (err != OK) {
4631            ALOGW("Extended VP8 parameters set failed: %d", err);
4632        } else if (tsType == OMX_VIDEO_AndroidTemporalLayeringPatternWebRTC) {
4633            // advertise even single layer WebRTC layering, as it is defined
4634            outputFormat->setString("ts-schema", AStringPrintf("webrtc.vp8.%u-layer", tsLayers));
4635        } else if (tsLayers > 0) {
4636            // tsType == OMX_VIDEO_AndroidTemporalLayeringPatternAndroid
4637            outputFormat->setString("ts-schema", AStringPrintf("android.generic.%u", tsLayers));
4638        }
4639    }
4640
4641    return configureBitrate(bitrateMode, bitrate);
4642}
4643
4644status_t ACodec::verifySupportForProfileAndLevel(
4645        OMX_U32 portIndex, int32_t profile, int32_t level) {
4646    OMX_VIDEO_PARAM_PROFILELEVELTYPE params;
4647    InitOMXParams(&params);
4648    params.nPortIndex = portIndex;
4649
4650    for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
4651        params.nProfileIndex = index;
4652        status_t err = mOMXNode->getParameter(
4653                OMX_IndexParamVideoProfileLevelQuerySupported,
4654                &params, sizeof(params));
4655
4656        if (err != OK) {
4657            return err;
4658        }
4659
4660        int32_t supportedProfile = static_cast<int32_t>(params.eProfile);
4661        int32_t supportedLevel = static_cast<int32_t>(params.eLevel);
4662
4663        if (profile == supportedProfile && level <= supportedLevel) {
4664            return OK;
4665        }
4666
4667        if (index == kMaxIndicesToCheck) {
4668            ALOGW("[%s] stopping checking profiles after %u: %x/%x",
4669                    mComponentName.c_str(), index,
4670                    params.eProfile, params.eLevel);
4671        }
4672    }
4673    return ERROR_UNSUPPORTED;
4674}
4675
4676status_t ACodec::configureBitrate(
4677        OMX_VIDEO_CONTROLRATETYPE bitrateMode, int32_t bitrate, int32_t quality) {
4678    OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
4679    InitOMXParams(&bitrateType);
4680    bitrateType.nPortIndex = kPortIndexOutput;
4681
4682    status_t err = mOMXNode->getParameter(
4683            OMX_IndexParamVideoBitrate, &bitrateType, sizeof(bitrateType));
4684
4685    if (err != OK) {
4686        return err;
4687    }
4688
4689    bitrateType.eControlRate = bitrateMode;
4690
4691    // write it out explicitly even if it's a union
4692    if (bitrateMode == OMX_Video_ControlRateConstantQuality) {
4693        bitrateType.nQualityFactor = quality;
4694    } else {
4695        bitrateType.nTargetBitrate = bitrate;
4696    }
4697
4698    return mOMXNode->setParameter(
4699            OMX_IndexParamVideoBitrate, &bitrateType, sizeof(bitrateType));
4700}
4701
4702void ACodec::configureEncoderLatency(const sp<AMessage> &msg) {
4703    if (!mIsEncoder || !mIsVideo) {
4704        return;
4705    }
4706
4707    int32_t latency = 0, bitrateMode;
4708    if (msg->findInt32("latency", &latency) && latency > 0) {
4709        status_t err = setLatency(latency);
4710        if (err != OK) {
4711            ALOGW("[%s] failed setLatency. Failure is fine since this key is optional",
4712                    mComponentName.c_str());
4713            err = OK;
4714        } else {
4715            mLatency = latency;
4716        }
4717    } else if ((!msg->findInt32("bitrate-mode", &bitrateMode) &&
4718            bitrateMode == OMX_Video_ControlRateConstant)) {
4719        // default the latency to be 1 if latency key is not specified or unsupported and bitrateMode
4720        // is CBR.
4721        mLatency = 1;
4722    }
4723}
4724
4725status_t ACodec::setupErrorCorrectionParameters() {
4726    OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
4727    InitOMXParams(&errorCorrectionType);
4728    errorCorrectionType.nPortIndex = kPortIndexOutput;
4729
4730    status_t err = mOMXNode->getParameter(
4731            OMX_IndexParamVideoErrorCorrection,
4732            &errorCorrectionType, sizeof(errorCorrectionType));
4733
4734    if (err != OK) {
4735        return OK;  // Optional feature. Ignore this failure
4736    }
4737
4738    errorCorrectionType.bEnableHEC = OMX_FALSE;
4739    errorCorrectionType.bEnableResync = OMX_TRUE;
4740    errorCorrectionType.nResynchMarkerSpacing = 256;
4741    errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
4742    errorCorrectionType.bEnableRVLC = OMX_FALSE;
4743
4744    return mOMXNode->setParameter(
4745            OMX_IndexParamVideoErrorCorrection,
4746            &errorCorrectionType, sizeof(errorCorrectionType));
4747}
4748
4749status_t ACodec::setVideoFormatOnPort(
4750        OMX_U32 portIndex,
4751        int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat,
4752        float frameRate) {
4753    OMX_PARAM_PORTDEFINITIONTYPE def;
4754    InitOMXParams(&def);
4755    def.nPortIndex = portIndex;
4756
4757    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
4758
4759    status_t err = mOMXNode->getParameter(
4760            OMX_IndexParamPortDefinition, &def, sizeof(def));
4761    if (err != OK) {
4762        return err;
4763    }
4764
4765    if (portIndex == kPortIndexInput) {
4766        // XXX Need a (much) better heuristic to compute input buffer sizes.
4767        const size_t X = 64 * 1024;
4768        if (def.nBufferSize < X) {
4769            def.nBufferSize = X;
4770        }
4771    }
4772
4773    if (def.eDomain != OMX_PortDomainVideo) {
4774        ALOGE("expected video port, got %s(%d)", asString(def.eDomain), def.eDomain);
4775        return FAILED_TRANSACTION;
4776    }
4777
4778    video_def->nFrameWidth = width;
4779    video_def->nFrameHeight = height;
4780
4781    if (portIndex == kPortIndexInput) {
4782        video_def->eCompressionFormat = compressionFormat;
4783        video_def->eColorFormat = OMX_COLOR_FormatUnused;
4784        if (frameRate >= 0) {
4785            video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f);
4786        }
4787    }
4788
4789    err = mOMXNode->setParameter(
4790            OMX_IndexParamPortDefinition, &def, sizeof(def));
4791
4792    return err;
4793}
4794
4795size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const {
4796    size_t n = 0;
4797
4798    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
4799        const BufferInfo &info = mBuffers[portIndex].itemAt(i);
4800
4801        if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) {
4802            ++n;
4803        }
4804    }
4805
4806    return n;
4807}
4808
4809size_t ACodec::countBuffersOwnedByNativeWindow() const {
4810    size_t n = 0;
4811
4812    for (size_t i = 0; i < mBuffers[kPortIndexOutput].size(); ++i) {
4813        const BufferInfo &info = mBuffers[kPortIndexOutput].itemAt(i);
4814
4815        if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
4816            ++n;
4817        }
4818    }
4819
4820    return n;
4821}
4822
4823void ACodec::waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs() {
4824    if (mNativeWindow == NULL) {
4825        return;
4826    }
4827
4828    while (countBuffersOwnedByNativeWindow() > mNumUndequeuedBuffers
4829            && dequeueBufferFromNativeWindow() != NULL) {
4830        // these buffers will be submitted as regular buffers; account for this
4831        if (storingMetadataInDecodedBuffers() && mMetadataBuffersToSubmit > 0) {
4832            --mMetadataBuffersToSubmit;
4833        }
4834    }
4835}
4836
4837bool ACodec::allYourBuffersAreBelongToUs(
4838        OMX_U32 portIndex) {
4839    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
4840        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
4841
4842        if (info->mStatus != BufferInfo::OWNED_BY_US
4843                && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
4844            ALOGV("[%s] Buffer %u on port %u still has status %d",
4845                    mComponentName.c_str(),
4846                    info->mBufferID, portIndex, info->mStatus);
4847            return false;
4848        }
4849    }
4850
4851    return true;
4852}
4853
4854bool ACodec::allYourBuffersAreBelongToUs() {
4855    return allYourBuffersAreBelongToUs(kPortIndexInput)
4856        && allYourBuffersAreBelongToUs(kPortIndexOutput);
4857}
4858
4859void ACodec::deferMessage(const sp<AMessage> &msg) {
4860    mDeferredQueue.push_back(msg);
4861}
4862
4863void ACodec::processDeferredMessages() {
4864    List<sp<AMessage> > queue = mDeferredQueue;
4865    mDeferredQueue.clear();
4866
4867    List<sp<AMessage> >::iterator it = queue.begin();
4868    while (it != queue.end()) {
4869        onMessageReceived(*it++);
4870    }
4871}
4872
4873status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> &notify) {
4874    const char *niceIndex = portIndex == kPortIndexInput ? "input" : "output";
4875    OMX_PARAM_PORTDEFINITIONTYPE def;
4876    InitOMXParams(&def);
4877    def.nPortIndex = portIndex;
4878
4879    status_t err = mOMXNode->getParameter(OMX_IndexParamPortDefinition, &def, sizeof(def));
4880    if (err != OK) {
4881        return err;
4882    }
4883
4884    if (def.eDir != (portIndex == kPortIndexOutput ? OMX_DirOutput : OMX_DirInput)) {
4885        ALOGE("unexpected dir: %s(%d) on %s port", asString(def.eDir), def.eDir, niceIndex);
4886        return BAD_VALUE;
4887    }
4888
4889    switch (def.eDomain) {
4890        case OMX_PortDomainVideo:
4891        {
4892            OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
4893            switch ((int)videoDef->eCompressionFormat) {
4894                case OMX_VIDEO_CodingUnused:
4895                {
4896                    CHECK(mIsEncoder ^ (portIndex == kPortIndexOutput));
4897                    notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW);
4898
4899                    notify->setInt32("stride", videoDef->nStride);
4900                    notify->setInt32("slice-height", videoDef->nSliceHeight);
4901                    notify->setInt32("color-format", videoDef->eColorFormat);
4902
4903                    if (mNativeWindow == NULL) {
4904                        DescribeColorFormat2Params describeParams;
4905                        InitOMXParams(&describeParams);
4906                        describeParams.eColorFormat = videoDef->eColorFormat;
4907                        describeParams.nFrameWidth = videoDef->nFrameWidth;
4908                        describeParams.nFrameHeight = videoDef->nFrameHeight;
4909                        describeParams.nStride = videoDef->nStride;
4910                        describeParams.nSliceHeight = videoDef->nSliceHeight;
4911                        describeParams.bUsingNativeBuffers = OMX_FALSE;
4912
4913                        if (DescribeColorFormat(mOMXNode, describeParams)) {
4914                            notify->setBuffer(
4915                                    "image-data",
4916                                    ABuffer::CreateAsCopy(
4917                                            &describeParams.sMediaImage,
4918                                            sizeof(describeParams.sMediaImage)));
4919
4920                            MediaImage2 &img = describeParams.sMediaImage;
4921                            MediaImage2::PlaneInfo *plane = img.mPlane;
4922                            ALOGV("[%s] MediaImage { F(%ux%u) @%u+%d+%d @%u+%d+%d @%u+%d+%d }",
4923                                    mComponentName.c_str(), img.mWidth, img.mHeight,
4924                                    plane[0].mOffset, plane[0].mColInc, plane[0].mRowInc,
4925                                    plane[1].mOffset, plane[1].mColInc, plane[1].mRowInc,
4926                                    plane[2].mOffset, plane[2].mColInc, plane[2].mRowInc);
4927                        }
4928                    }
4929
4930                    int32_t width = (int32_t)videoDef->nFrameWidth;
4931                    int32_t height = (int32_t)videoDef->nFrameHeight;
4932
4933                    if (portIndex == kPortIndexOutput) {
4934                        OMX_CONFIG_RECTTYPE rect;
4935                        InitOMXParams(&rect);
4936                        rect.nPortIndex = portIndex;
4937
4938                        if (mOMXNode->getConfig(
4939                                    (portIndex == kPortIndexOutput ?
4940                                            OMX_IndexConfigCommonOutputCrop :
4941                                            OMX_IndexConfigCommonInputCrop),
4942                                    &rect, sizeof(rect)) != OK) {
4943                            rect.nLeft = 0;
4944                            rect.nTop = 0;
4945                            rect.nWidth = videoDef->nFrameWidth;
4946                            rect.nHeight = videoDef->nFrameHeight;
4947                        }
4948
4949                        if (rect.nLeft < 0 || rect.nTop < 0 ||
4950                            rect.nWidth == 0 || rect.nHeight == 0 ||
4951                            rect.nLeft + rect.nWidth > videoDef->nFrameWidth ||
4952                            rect.nTop + rect.nHeight > videoDef->nFrameHeight) {
4953                            ALOGE("Wrong cropped rect (%d, %d, %u, %u) vs. frame (%u, %u)",
4954                                    rect.nLeft, rect.nTop,
4955                                    rect.nWidth, rect.nHeight,
4956                                    videoDef->nFrameWidth, videoDef->nFrameHeight);
4957                            return BAD_VALUE;
4958                        }
4959
4960                        notify->setRect(
4961                                "crop",
4962                                rect.nLeft,
4963                                rect.nTop,
4964                                rect.nLeft + rect.nWidth - 1,
4965                                rect.nTop + rect.nHeight - 1);
4966
4967                        width = rect.nWidth;
4968                        height = rect.nHeight;
4969
4970                        android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN;
4971                        (void)getColorAspectsAndDataSpaceForVideoDecoder(
4972                                width, height, mConfigFormat, notify,
4973                                mUsingNativeWindow ? &dataSpace : NULL);
4974                        if (mUsingNativeWindow) {
4975                            notify->setInt32("android._dataspace", dataSpace);
4976                        }
4977                        (void)getHDRStaticInfoForVideoCodec(kPortIndexOutput, notify);
4978                    } else {
4979                        (void)getInputColorAspectsForVideoEncoder(notify);
4980                        if (mConfigFormat->contains("hdr-static-info")) {
4981                            (void)getHDRStaticInfoForVideoCodec(kPortIndexInput, notify);
4982                        }
4983                        uint32_t latency = 0;
4984                        if (mIsEncoder && !mIsImage &&
4985                                getLatency(&latency) == OK && latency > 0) {
4986                            notify->setInt32("latency", latency);
4987                        }
4988                    }
4989
4990                    break;
4991                }
4992
4993                case OMX_VIDEO_CodingVP8:
4994                case OMX_VIDEO_CodingVP9:
4995                {
4996                    OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type;
4997                    InitOMXParams(&vp8type);
4998                    vp8type.nPortIndex = kPortIndexOutput;
4999                    status_t err = mOMXNode->getParameter(
5000                            (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
5001                            &vp8type,
5002                            sizeof(vp8type));
5003
5004                    if (err == OK) {
5005                        if (vp8type.eTemporalPattern == OMX_VIDEO_VPXTemporalLayerPatternWebRTC
5006                                && vp8type.nTemporalLayerCount > 0
5007                                && vp8type.nTemporalLayerCount
5008                                        <= OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS) {
5009                            // advertise as android.generic if we configured for android.generic
5010                            AString origSchema;
5011                            if (notify->findString("ts-schema", &origSchema)
5012                                    && origSchema.startsWith("android.generic")) {
5013                                notify->setString("ts-schema", AStringPrintf(
5014                                        "android.generic.%u", vp8type.nTemporalLayerCount));
5015                            } else {
5016                                notify->setString("ts-schema", AStringPrintf(
5017                                        "webrtc.vp8.%u-layer", vp8type.nTemporalLayerCount));
5018                            }
5019                        }
5020                    }
5021                    // Fall through to set up mime.
5022                }
5023
5024                default:
5025                {
5026                    if (mIsEncoder ^ (portIndex == kPortIndexOutput)) {
5027                        // should be CodingUnused
5028                        ALOGE("Raw port video compression format is %s(%d)",
5029                                asString(videoDef->eCompressionFormat),
5030                                videoDef->eCompressionFormat);
5031                        return BAD_VALUE;
5032                    }
5033                    AString mime;
5034                    if (GetMimeTypeForVideoCoding(
5035                        videoDef->eCompressionFormat, &mime) != OK) {
5036                        notify->setString("mime", "application/octet-stream");
5037                    } else {
5038                        notify->setString("mime", mime.c_str());
5039                    }
5040                    uint32_t intraRefreshPeriod = 0;
5041                    if (mIsEncoder && !mIsImage &&
5042                            getIntraRefreshPeriod(&intraRefreshPeriod) == OK
5043                            && intraRefreshPeriod > 0) {
5044                        notify->setInt32("intra-refresh-period", intraRefreshPeriod);
5045                    }
5046                    break;
5047                }
5048            }
5049            notify->setInt32("width", videoDef->nFrameWidth);
5050            notify->setInt32("height", videoDef->nFrameHeight);
5051            ALOGV("[%s] %s format is %s", mComponentName.c_str(),
5052                    portIndex == kPortIndexInput ? "input" : "output",
5053                    notify->debugString().c_str());
5054
5055            break;
5056        }
5057
5058        case OMX_PortDomainAudio:
5059        {
5060            OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
5061
5062            switch ((int)audioDef->eEncoding) {
5063                case OMX_AUDIO_CodingPCM:
5064                {
5065                    OMX_AUDIO_PARAM_PCMMODETYPE params;
5066                    InitOMXParams(&params);
5067                    params.nPortIndex = portIndex;
5068
5069                    err = mOMXNode->getParameter(
5070                            OMX_IndexParamAudioPcm, &params, sizeof(params));
5071                    if (err != OK) {
5072                        return err;
5073                    }
5074
5075                    if (params.nChannels <= 0
5076                            || (params.nChannels != 1 && !params.bInterleaved)
5077                            || params.ePCMMode != OMX_AUDIO_PCMModeLinear) {
5078                        ALOGE("unsupported PCM port: %u channels%s, %u-bit",
5079                                params.nChannels,
5080                                params.bInterleaved ? " interleaved" : "",
5081                                params.nBitPerSample);
5082                        return FAILED_TRANSACTION;
5083                    }
5084
5085                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
5086                    notify->setInt32("channel-count", params.nChannels);
5087                    notify->setInt32("sample-rate", params.nSamplingRate);
5088
5089                    AudioEncoding encoding = kAudioEncodingPcm16bit;
5090                    if (params.eNumData == OMX_NumericalDataUnsigned
5091                            && params.nBitPerSample == 8u) {
5092                        encoding = kAudioEncodingPcm8bit;
5093                    } else if (params.eNumData == OMX_NumericalDataFloat
5094                            && params.nBitPerSample == 32u) {
5095                        encoding = kAudioEncodingPcmFloat;
5096                    } else if (params.nBitPerSample != 16u
5097                            || params.eNumData != OMX_NumericalDataSigned) {
5098                        ALOGE("unsupported PCM port: %s(%d), %s(%d) mode ",
5099                                asString(params.eNumData), params.eNumData,
5100                                asString(params.ePCMMode), params.ePCMMode);
5101                        return FAILED_TRANSACTION;
5102                    }
5103                    notify->setInt32("pcm-encoding", encoding);
5104
5105                    if (mChannelMaskPresent) {
5106                        notify->setInt32("channel-mask", mChannelMask);
5107                    }
5108                    break;
5109                }
5110
5111                case OMX_AUDIO_CodingAAC:
5112                {
5113                    OMX_AUDIO_PARAM_AACPROFILETYPE params;
5114                    InitOMXParams(&params);
5115                    params.nPortIndex = portIndex;
5116
5117                    err = mOMXNode->getParameter(
5118                            OMX_IndexParamAudioAac, &params, sizeof(params));
5119                    if (err != OK) {
5120                        return err;
5121                    }
5122
5123                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
5124                    notify->setInt32("channel-count", params.nChannels);
5125                    notify->setInt32("sample-rate", params.nSampleRate);
5126                    break;
5127                }
5128
5129                case OMX_AUDIO_CodingAMR:
5130                {
5131                    OMX_AUDIO_PARAM_AMRTYPE params;
5132                    InitOMXParams(&params);
5133                    params.nPortIndex = portIndex;
5134
5135                    err = mOMXNode->getParameter(
5136                            OMX_IndexParamAudioAmr, &params, sizeof(params));
5137                    if (err != OK) {
5138                        return err;
5139                    }
5140
5141                    notify->setInt32("channel-count", 1);
5142                    if (params.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0) {
5143                        notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_WB);
5144                        notify->setInt32("sample-rate", 16000);
5145                    } else {
5146                        notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_NB);
5147                        notify->setInt32("sample-rate", 8000);
5148                    }
5149                    break;
5150                }
5151
5152                case OMX_AUDIO_CodingFLAC:
5153                {
5154                    OMX_AUDIO_PARAM_FLACTYPE params;
5155                    InitOMXParams(&params);
5156                    params.nPortIndex = portIndex;
5157
5158                    err = mOMXNode->getParameter(
5159                            OMX_IndexParamAudioFlac, &params, sizeof(params));
5160                    if (err != OK) {
5161                        return err;
5162                    }
5163
5164                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_FLAC);
5165                    notify->setInt32("channel-count", params.nChannels);
5166                    notify->setInt32("sample-rate", params.nSampleRate);
5167                    break;
5168                }
5169
5170                case OMX_AUDIO_CodingMP3:
5171                {
5172                    OMX_AUDIO_PARAM_MP3TYPE params;
5173                    InitOMXParams(&params);
5174                    params.nPortIndex = portIndex;
5175
5176                    err = mOMXNode->getParameter(
5177                            OMX_IndexParamAudioMp3, &params, sizeof(params));
5178                    if (err != OK) {
5179                        return err;
5180                    }
5181
5182                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MPEG);
5183                    notify->setInt32("channel-count", params.nChannels);
5184                    notify->setInt32("sample-rate", params.nSampleRate);
5185                    break;
5186                }
5187
5188                case OMX_AUDIO_CodingVORBIS:
5189                {
5190                    OMX_AUDIO_PARAM_VORBISTYPE params;
5191                    InitOMXParams(&params);
5192                    params.nPortIndex = portIndex;
5193
5194                    err = mOMXNode->getParameter(
5195                            OMX_IndexParamAudioVorbis, &params, sizeof(params));
5196                    if (err != OK) {
5197                        return err;
5198                    }
5199
5200                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_VORBIS);
5201                    notify->setInt32("channel-count", params.nChannels);
5202                    notify->setInt32("sample-rate", params.nSampleRate);
5203                    break;
5204                }
5205
5206                case OMX_AUDIO_CodingAndroidAC3:
5207                {
5208                    OMX_AUDIO_PARAM_ANDROID_AC3TYPE params;
5209                    InitOMXParams(&params);
5210                    params.nPortIndex = portIndex;
5211
5212                    err = mOMXNode->getParameter(
5213                            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
5214                            &params, sizeof(params));
5215                    if (err != OK) {
5216                        return err;
5217                    }
5218
5219                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AC3);
5220                    notify->setInt32("channel-count", params.nChannels);
5221                    notify->setInt32("sample-rate", params.nSampleRate);
5222                    break;
5223                }
5224
5225                case OMX_AUDIO_CodingAndroidEAC3:
5226                {
5227                    OMX_AUDIO_PARAM_ANDROID_EAC3TYPE params;
5228                    InitOMXParams(&params);
5229                    params.nPortIndex = portIndex;
5230
5231                    err = mOMXNode->getParameter(
5232                            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
5233                            &params, sizeof(params));
5234                    if (err != OK) {
5235                        return err;
5236                    }
5237
5238                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_EAC3);
5239                    notify->setInt32("channel-count", params.nChannels);
5240                    notify->setInt32("sample-rate", params.nSampleRate);
5241                    break;
5242                }
5243
5244                case OMX_AUDIO_CodingAndroidOPUS:
5245                {
5246                    OMX_AUDIO_PARAM_ANDROID_OPUSTYPE params;
5247                    InitOMXParams(&params);
5248                    params.nPortIndex = portIndex;
5249
5250                    err = mOMXNode->getParameter(
5251                            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus,
5252                            &params, sizeof(params));
5253                    if (err != OK) {
5254                        return err;
5255                    }
5256
5257                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_OPUS);
5258                    notify->setInt32("channel-count", params.nChannels);
5259                    notify->setInt32("sample-rate", params.nSampleRate);
5260                    break;
5261                }
5262
5263                case OMX_AUDIO_CodingG711:
5264                {
5265                    OMX_AUDIO_PARAM_PCMMODETYPE params;
5266                    InitOMXParams(&params);
5267                    params.nPortIndex = portIndex;
5268
5269                    err = mOMXNode->getParameter(
5270                            (OMX_INDEXTYPE)OMX_IndexParamAudioPcm, &params, sizeof(params));
5271                    if (err != OK) {
5272                        return err;
5273                    }
5274
5275                    const char *mime = NULL;
5276                    if (params.ePCMMode == OMX_AUDIO_PCMModeMULaw) {
5277                        mime = MEDIA_MIMETYPE_AUDIO_G711_MLAW;
5278                    } else if (params.ePCMMode == OMX_AUDIO_PCMModeALaw) {
5279                        mime = MEDIA_MIMETYPE_AUDIO_G711_ALAW;
5280                    } else { // params.ePCMMode == OMX_AUDIO_PCMModeLinear
5281                        mime = MEDIA_MIMETYPE_AUDIO_RAW;
5282                    }
5283                    notify->setString("mime", mime);
5284                    notify->setInt32("channel-count", params.nChannels);
5285                    notify->setInt32("sample-rate", params.nSamplingRate);
5286                    notify->setInt32("pcm-encoding", kAudioEncodingPcm16bit);
5287                    break;
5288                }
5289
5290                case OMX_AUDIO_CodingGSMFR:
5291                {
5292                    OMX_AUDIO_PARAM_PCMMODETYPE params;
5293                    InitOMXParams(&params);
5294                    params.nPortIndex = portIndex;
5295
5296                    err = mOMXNode->getParameter(
5297                                OMX_IndexParamAudioPcm, &params, sizeof(params));
5298                    if (err != OK) {
5299                        return err;
5300                    }
5301
5302                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MSGSM);
5303                    notify->setInt32("channel-count", params.nChannels);
5304                    notify->setInt32("sample-rate", params.nSamplingRate);
5305                    break;
5306                }
5307
5308                default:
5309                    ALOGE("Unsupported audio coding: %s(%d)\n",
5310                            asString(audioDef->eEncoding), audioDef->eEncoding);
5311                    return BAD_TYPE;
5312            }
5313            break;
5314        }
5315
5316        default:
5317            ALOGE("Unsupported domain: %s(%d)", asString(def.eDomain), def.eDomain);
5318            return BAD_TYPE;
5319    }
5320
5321    return getVendorParameters(portIndex, notify);
5322}
5323
5324void ACodec::onDataSpaceChanged(android_dataspace dataSpace, const ColorAspects &aspects) {
5325    // aspects are normally communicated in ColorAspects
5326    int32_t range, standard, transfer;
5327    convertCodecColorAspectsToPlatformAspects(aspects, &range, &standard, &transfer);
5328
5329    // if some aspects are unspecified, use dataspace fields
5330    if (range == 0) {
5331        range = (dataSpace & HAL_DATASPACE_RANGE_MASK) >> HAL_DATASPACE_RANGE_SHIFT;
5332    }
5333    if (standard == 0) {
5334        standard = (dataSpace & HAL_DATASPACE_STANDARD_MASK) >> HAL_DATASPACE_STANDARD_SHIFT;
5335    }
5336    if (transfer == 0) {
5337        transfer = (dataSpace & HAL_DATASPACE_TRANSFER_MASK) >> HAL_DATASPACE_TRANSFER_SHIFT;
5338    }
5339
5340    mOutputFormat = mOutputFormat->dup(); // trigger an output format changed event
5341    if (range != 0) {
5342        mOutputFormat->setInt32("color-range", range);
5343    }
5344    if (standard != 0) {
5345        mOutputFormat->setInt32("color-standard", standard);
5346    }
5347    if (transfer != 0) {
5348        mOutputFormat->setInt32("color-transfer", transfer);
5349    }
5350
5351    ALOGD("dataspace changed to %#x (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) "
5352          "(R:%d(%s), S:%d(%s), T:%d(%s))",
5353            dataSpace,
5354            aspects.mRange, asString(aspects.mRange),
5355            aspects.mPrimaries, asString(aspects.mPrimaries),
5356            aspects.mMatrixCoeffs, asString(aspects.mMatrixCoeffs),
5357            aspects.mTransfer, asString(aspects.mTransfer),
5358            range, asString((ColorRange)range),
5359            standard, asString((ColorStandard)standard),
5360            transfer, asString((ColorTransfer)transfer));
5361}
5362
5363void ACodec::onOutputFormatChanged(sp<const AMessage> expectedFormat) {
5364    // store new output format, at the same time mark that this is no longer the first frame
5365    mOutputFormat = mBaseOutputFormat->dup();
5366
5367    if (getPortFormat(kPortIndexOutput, mOutputFormat) != OK) {
5368        ALOGE("[%s] Failed to get port format to send format change", mComponentName.c_str());
5369        return;
5370    }
5371
5372    if (expectedFormat != NULL) {
5373        sp<const AMessage> changes = expectedFormat->changesFrom(mOutputFormat);
5374        sp<const AMessage> to = mOutputFormat->changesFrom(expectedFormat);
5375        if (changes->countEntries() != 0 || to->countEntries() != 0) {
5376            ALOGW("[%s] BAD CODEC: Output format changed unexpectedly from (diff) %s to (diff) %s",
5377                    mComponentName.c_str(),
5378                    changes->debugString(4).c_str(), to->debugString(4).c_str());
5379        }
5380    }
5381
5382    if (!mIsVideo && !mIsEncoder) {
5383        AudioEncoding pcmEncoding = kAudioEncodingPcm16bit;
5384        (void)mConfigFormat->findInt32("pcm-encoding", (int32_t*)&pcmEncoding);
5385        AudioEncoding codecPcmEncoding = kAudioEncodingPcm16bit;
5386        (void)mOutputFormat->findInt32("pcm-encoding", (int32_t*)&pcmEncoding);
5387
5388        mConverter[kPortIndexOutput] = AudioConverter::Create(codecPcmEncoding, pcmEncoding);
5389        if (mConverter[kPortIndexOutput] != NULL) {
5390            mOutputFormat->setInt32("pcm-encoding", pcmEncoding);
5391        }
5392    }
5393
5394    if (mTunneled) {
5395        sendFormatChange();
5396    }
5397}
5398
5399void ACodec::sendFormatChange() {
5400    AString mime;
5401    CHECK(mOutputFormat->findString("mime", &mime));
5402
5403    if (mime == MEDIA_MIMETYPE_AUDIO_RAW && (mEncoderDelay || mEncoderPadding)) {
5404        int32_t channelCount, sampleRate;
5405        CHECK(mOutputFormat->findInt32("channel-count", &channelCount));
5406        CHECK(mOutputFormat->findInt32("sample-rate", &sampleRate));
5407        if (mSampleRate != 0 && sampleRate != 0) {
5408            // avoiding 32-bit overflows in intermediate values
5409            mEncoderDelay = (int32_t)((((int64_t)mEncoderDelay) * sampleRate) / mSampleRate);
5410            mEncoderPadding = (int32_t)((((int64_t)mEncoderPadding) * sampleRate) / mSampleRate);
5411            mSampleRate = sampleRate;
5412        }
5413        if (mSkipCutBuffer != NULL) {
5414            size_t prevbufsize = mSkipCutBuffer->size();
5415            if (prevbufsize != 0) {
5416                ALOGW("Replacing SkipCutBuffer holding %zu bytes", prevbufsize);
5417            }
5418        }
5419        mSkipCutBuffer = new SkipCutBuffer(mEncoderDelay, mEncoderPadding, channelCount);
5420    }
5421
5422    // mLastOutputFormat is not used when tunneled; doing this just to stay consistent
5423    mLastOutputFormat = mOutputFormat;
5424}
5425
5426void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) {
5427    ALOGE("signalError(omxError %#x, internalError %d)", error, internalError);
5428
5429    if (internalError == UNKNOWN_ERROR) { // find better error code
5430        const status_t omxStatus = statusFromOMXError(error);
5431        if (omxStatus != 0) {
5432            internalError = omxStatus;
5433        } else {
5434            ALOGW("Invalid OMX error %#x", error);
5435        }
5436    }
5437
5438    mFatalError = true;
5439    mCallback->onError(internalError, ACTION_CODE_FATAL);
5440}
5441
5442status_t ACodec::requestIDRFrame() {
5443    if (!mIsEncoder) {
5444        return ERROR_UNSUPPORTED;
5445    }
5446
5447    OMX_CONFIG_INTRAREFRESHVOPTYPE params;
5448    InitOMXParams(&params);
5449
5450    params.nPortIndex = kPortIndexOutput;
5451    params.IntraRefreshVOP = OMX_TRUE;
5452
5453    return mOMXNode->setConfig(
5454            OMX_IndexConfigVideoIntraVOPRefresh,
5455            &params,
5456            sizeof(params));
5457}
5458
5459////////////////////////////////////////////////////////////////////////////////
5460
5461ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
5462    : AState(parentState),
5463      mCodec(codec) {
5464}
5465
5466ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(
5467        OMX_U32 /* portIndex */) {
5468    return KEEP_BUFFERS;
5469}
5470
5471void ACodec::BaseState::stateExited() {
5472    ++mCodec->mStateGeneration;
5473}
5474
5475bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) {
5476    switch (msg->what()) {
5477        case kWhatInputBufferFilled:
5478        {
5479            onInputBufferFilled(msg);
5480            break;
5481        }
5482
5483        case kWhatOutputBufferDrained:
5484        {
5485            onOutputBufferDrained(msg);
5486            break;
5487        }
5488
5489        case ACodec::kWhatOMXMessageList:
5490        {
5491            return checkOMXMessage(msg) ? onOMXMessageList(msg) : true;
5492        }
5493
5494        case ACodec::kWhatOMXMessageItem:
5495        {
5496            // no need to check as we already did it for kWhatOMXMessageList
5497            return onOMXMessage(msg);
5498        }
5499
5500        case ACodec::kWhatOMXMessage:
5501        {
5502            return checkOMXMessage(msg) ? onOMXMessage(msg) : true;
5503        }
5504
5505        case ACodec::kWhatSetSurface:
5506        {
5507            sp<AReplyToken> replyID;
5508            CHECK(msg->senderAwaitsResponse(&replyID));
5509
5510            sp<RefBase> obj;
5511            CHECK(msg->findObject("surface", &obj));
5512
5513            status_t err = mCodec->handleSetSurface(static_cast<Surface *>(obj.get()));
5514
5515            sp<AMessage> response = new AMessage;
5516            response->setInt32("err", err);
5517            response->postReply(replyID);
5518            break;
5519        }
5520
5521        case ACodec::kWhatCreateInputSurface:
5522        case ACodec::kWhatSetInputSurface:
5523        case ACodec::kWhatSignalEndOfInputStream:
5524        {
5525            // This may result in an app illegal state exception.
5526            ALOGE("Message 0x%x was not handled", msg->what());
5527            mCodec->signalError(OMX_ErrorUndefined, INVALID_OPERATION);
5528            return true;
5529        }
5530
5531        case ACodec::kWhatOMXDied:
5532        {
5533            // This will result in kFlagSawMediaServerDie handling in MediaCodec.
5534            ALOGE("OMX/mediaserver died, signalling error!");
5535            mCodec->mGraphicBufferSource.clear();
5536            mCodec->signalError(OMX_ErrorResourcesLost, DEAD_OBJECT);
5537            break;
5538        }
5539
5540        case ACodec::kWhatReleaseCodecInstance:
5541        {
5542            ALOGI("[%s] forcing the release of codec",
5543                    mCodec->mComponentName.c_str());
5544            status_t err = mCodec->mOMXNode->freeNode();
5545            ALOGE_IF("[%s] failed to release codec instance: err=%d",
5546                       mCodec->mComponentName.c_str(), err);
5547            mCodec->mCallback->onReleaseCompleted();
5548
5549            mCodec->changeState(mCodec->mUninitializedState);
5550            break;
5551        }
5552
5553        case ACodec::kWhatForceStateTransition:
5554        {
5555            ALOGV("Already transitioned --- ignore");
5556            break;
5557        }
5558
5559        default:
5560            return false;
5561    }
5562
5563    return true;
5564}
5565
5566bool ACodec::BaseState::checkOMXMessage(const sp<AMessage> &msg) {
5567    // there is a possibility that this is an outstanding message for a
5568    // codec that we have already destroyed
5569    if (mCodec->mOMXNode == NULL) {
5570        ALOGI("ignoring message as already freed component: %s",
5571                msg->debugString().c_str());
5572        return false;
5573    }
5574
5575    int32_t generation;
5576    CHECK(msg->findInt32("generation", (int32_t*)&generation));
5577    if (generation != mCodec->mNodeGeneration) {
5578        ALOGW("Unexpected message for component: %s, gen %u, cur %u",
5579                msg->debugString().c_str(), generation, mCodec->mNodeGeneration);
5580        return false;
5581    }
5582    return true;
5583}
5584
5585bool ACodec::BaseState::onOMXMessageList(const sp<AMessage> &msg) {
5586    sp<RefBase> obj;
5587    CHECK(msg->findObject("messages", &obj));
5588    sp<MessageList> msgList = static_cast<MessageList *>(obj.get());
5589
5590    bool receivedRenderedEvents = false;
5591    for (std::list<sp<AMessage>>::const_iterator it = msgList->getList().cbegin();
5592          it != msgList->getList().cend(); ++it) {
5593        (*it)->setWhat(ACodec::kWhatOMXMessageItem);
5594        mCodec->handleMessage(*it);
5595        int32_t type;
5596        CHECK((*it)->findInt32("type", &type));
5597        if (type == omx_message::FRAME_RENDERED) {
5598            receivedRenderedEvents = true;
5599        }
5600    }
5601
5602    if (receivedRenderedEvents) {
5603        // NOTE: all buffers are rendered in this case
5604        mCodec->notifyOfRenderedFrames();
5605    }
5606    return true;
5607}
5608
5609bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) {
5610    int32_t type;
5611    CHECK(msg->findInt32("type", &type));
5612
5613    switch (type) {
5614        case omx_message::EVENT:
5615        {
5616            int32_t event, data1, data2;
5617            CHECK(msg->findInt32("event", &event));
5618            CHECK(msg->findInt32("data1", &data1));
5619            CHECK(msg->findInt32("data2", &data2));
5620
5621            if (event == OMX_EventCmdComplete
5622                    && data1 == OMX_CommandFlush
5623                    && data2 == (int32_t)OMX_ALL) {
5624                // Use of this notification is not consistent across
5625                // implementations. We'll drop this notification and rely
5626                // on flush-complete notifications on the individual port
5627                // indices instead.
5628
5629                return true;
5630            }
5631
5632            return onOMXEvent(
5633                    static_cast<OMX_EVENTTYPE>(event),
5634                    static_cast<OMX_U32>(data1),
5635                    static_cast<OMX_U32>(data2));
5636        }
5637
5638        case omx_message::EMPTY_BUFFER_DONE:
5639        {
5640            IOMX::buffer_id bufferID;
5641            int32_t fenceFd;
5642
5643            CHECK(msg->findInt32("buffer", (int32_t*)&bufferID));
5644            CHECK(msg->findInt32("fence_fd", &fenceFd));
5645
5646            return onOMXEmptyBufferDone(bufferID, fenceFd);
5647        }
5648
5649        case omx_message::FILL_BUFFER_DONE:
5650        {
5651            IOMX::buffer_id bufferID;
5652            CHECK(msg->findInt32("buffer", (int32_t*)&bufferID));
5653
5654            int32_t rangeOffset, rangeLength, flags, fenceFd;
5655            int64_t timeUs;
5656
5657            CHECK(msg->findInt32("range_offset", &rangeOffset));
5658            CHECK(msg->findInt32("range_length", &rangeLength));
5659            CHECK(msg->findInt32("flags", &flags));
5660            CHECK(msg->findInt64("timestamp", &timeUs));
5661            CHECK(msg->findInt32("fence_fd", &fenceFd));
5662
5663            return onOMXFillBufferDone(
5664                    bufferID,
5665                    (size_t)rangeOffset, (size_t)rangeLength,
5666                    (OMX_U32)flags,
5667                    timeUs,
5668                    fenceFd);
5669        }
5670
5671        case omx_message::FRAME_RENDERED:
5672        {
5673            int64_t mediaTimeUs, systemNano;
5674
5675            CHECK(msg->findInt64("media_time_us", &mediaTimeUs));
5676            CHECK(msg->findInt64("system_nano", &systemNano));
5677
5678            return onOMXFrameRendered(
5679                    mediaTimeUs, systemNano);
5680        }
5681
5682        default:
5683            ALOGE("Unexpected message type: %d", type);
5684            return false;
5685    }
5686}
5687
5688bool ACodec::BaseState::onOMXFrameRendered(
5689        int64_t mediaTimeUs __unused, nsecs_t systemNano __unused) {
5690    // ignore outside of Executing and PortSettingsChanged states
5691    return true;
5692}
5693
5694bool ACodec::BaseState::onOMXEvent(
5695        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5696    if (event == OMX_EventDataSpaceChanged) {
5697        ColorAspects aspects = ColorUtils::unpackToColorAspects(data2);
5698
5699        mCodec->onDataSpaceChanged((android_dataspace)data1, aspects);
5700        return true;
5701    }
5702
5703    if (event != OMX_EventError) {
5704        ALOGV("[%s] EVENT(%d, 0x%08x, 0x%08x)",
5705             mCodec->mComponentName.c_str(), event, data1, data2);
5706
5707        return false;
5708    }
5709
5710    ALOGE("[%s] ERROR(0x%08x)", mCodec->mComponentName.c_str(), data1);
5711
5712    // verify OMX component sends back an error we expect.
5713    OMX_ERRORTYPE omxError = (OMX_ERRORTYPE)data1;
5714    if (!isOMXError(omxError)) {
5715        ALOGW("Invalid OMX error %#x", omxError);
5716        omxError = OMX_ErrorUndefined;
5717    }
5718    mCodec->signalError(omxError);
5719
5720    return true;
5721}
5722
5723bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID, int fenceFd) {
5724    ALOGV("[%s] onOMXEmptyBufferDone %u",
5725         mCodec->mComponentName.c_str(), bufferID);
5726
5727    BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
5728    BufferInfo::Status status = BufferInfo::getSafeStatus(info);
5729    if (status != BufferInfo::OWNED_BY_COMPONENT) {
5730        ALOGE("Wrong ownership in EBD: %s(%d) buffer #%u", _asString(status), status, bufferID);
5731        mCodec->dumpBuffers(kPortIndexInput);
5732        if (fenceFd >= 0) {
5733            ::close(fenceFd);
5734        }
5735        return false;
5736    }
5737    info->mStatus = BufferInfo::OWNED_BY_US;
5738
5739    // input buffers cannot take fences, so wait for any fence now
5740    (void)mCodec->waitForFence(fenceFd, "onOMXEmptyBufferDone");
5741    fenceFd = -1;
5742
5743    // still save fence for completeness
5744    info->setWriteFence(fenceFd, "onOMXEmptyBufferDone");
5745
5746    // We're in "store-metadata-in-buffers" mode, the underlying
5747    // OMX component had access to data that's implicitly refcounted
5748    // by this "MediaBuffer" object. Now that the OMX component has
5749    // told us that it's done with the input buffer, we can decrement
5750    // the mediaBuffer's reference count.
5751    info->mData->meta()->setObject("mediaBufferHolder", sp<MediaBufferHolder>(nullptr));
5752
5753    PortMode mode = getPortMode(kPortIndexInput);
5754
5755    switch (mode) {
5756        case KEEP_BUFFERS:
5757            break;
5758
5759        case RESUBMIT_BUFFERS:
5760            postFillThisBuffer(info);
5761            break;
5762
5763        case FREE_BUFFERS:
5764        default:
5765            ALOGE("SHOULD NOT REACH HERE: cannot free empty output buffers");
5766            return false;
5767    }
5768
5769    return true;
5770}
5771
5772void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) {
5773    if (mCodec->mPortEOS[kPortIndexInput]) {
5774        return;
5775    }
5776
5777    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
5778
5779    info->mData->setFormat(mCodec->mInputFormat);
5780    mCodec->mBufferChannel->fillThisBuffer(info->mBufferID);
5781    info->mData.clear();
5782    info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
5783}
5784
5785void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
5786    IOMX::buffer_id bufferID;
5787    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
5788    sp<MediaCodecBuffer> buffer;
5789    int32_t err = OK;
5790    bool eos = false;
5791    PortMode mode = getPortMode(kPortIndexInput);
5792    int32_t discarded = 0;
5793    if (msg->findInt32("discarded", &discarded) && discarded) {
5794        // these are unfilled buffers returned by client
5795        // buffers are returned on MediaCodec.flush
5796        mode = KEEP_BUFFERS;
5797    }
5798    sp<RefBase> obj;
5799    CHECK(msg->findObject("buffer", &obj));
5800    buffer = static_cast<MediaCodecBuffer *>(obj.get());
5801
5802    int32_t tmp;
5803    if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) {
5804        eos = true;
5805        err = ERROR_END_OF_STREAM;
5806    }
5807
5808    BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
5809    BufferInfo::Status status = BufferInfo::getSafeStatus(info);
5810    if (status != BufferInfo::OWNED_BY_UPSTREAM) {
5811        ALOGE("Wrong ownership in IBF: %s(%d) buffer #%u", _asString(status), status, bufferID);
5812        mCodec->dumpBuffers(kPortIndexInput);
5813        mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
5814        return;
5815    }
5816
5817    info->mStatus = BufferInfo::OWNED_BY_US;
5818    info->mData = buffer;
5819
5820    switch (mode) {
5821        case KEEP_BUFFERS:
5822        {
5823            if (eos) {
5824                if (!mCodec->mPortEOS[kPortIndexInput]) {
5825                    mCodec->mPortEOS[kPortIndexInput] = true;
5826                    mCodec->mInputEOSResult = err;
5827                }
5828            }
5829            break;
5830        }
5831
5832        case RESUBMIT_BUFFERS:
5833        {
5834            if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) {
5835                // Do not send empty input buffer w/o EOS to the component.
5836                if (buffer->size() == 0 && !eos) {
5837                    postFillThisBuffer(info);
5838                    break;
5839                }
5840
5841                int64_t timeUs;
5842                CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
5843
5844                OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
5845
5846                int32_t isCSD = 0;
5847                if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) {
5848                    if (mCodec->mIsLegacyVP9Decoder) {
5849                        ALOGV("[%s] is legacy VP9 decoder. Ignore %u codec specific data",
5850                            mCodec->mComponentName.c_str(), bufferID);
5851                        postFillThisBuffer(info);
5852                        break;
5853                    }
5854                    flags |= OMX_BUFFERFLAG_CODECCONFIG;
5855                }
5856
5857                if (eos) {
5858                    flags |= OMX_BUFFERFLAG_EOS;
5859                }
5860
5861                size_t size = buffer->size();
5862                size_t offset = buffer->offset();
5863                if (buffer->base() != info->mCodecData->base()) {
5864                    ALOGV("[%s] Needs to copy input data for buffer %u. (%p != %p)",
5865                         mCodec->mComponentName.c_str(),
5866                         bufferID,
5867                         buffer->base(), info->mCodecData->base());
5868
5869                    sp<DataConverter> converter = mCodec->mConverter[kPortIndexInput];
5870                    if (converter == NULL || isCSD) {
5871                        converter = getCopyConverter();
5872                    }
5873                    status_t err = converter->convert(buffer, info->mCodecData);
5874                    if (err != OK) {
5875                        mCodec->signalError(OMX_ErrorUndefined, err);
5876                        return;
5877                    }
5878                    size = info->mCodecData->size();
5879                } else {
5880                    info->mCodecData->setRange(offset, size);
5881                }
5882
5883                if (flags & OMX_BUFFERFLAG_CODECCONFIG) {
5884                    ALOGV("[%s] calling emptyBuffer %u w/ codec specific data",
5885                         mCodec->mComponentName.c_str(), bufferID);
5886                } else if (flags & OMX_BUFFERFLAG_EOS) {
5887                    ALOGV("[%s] calling emptyBuffer %u w/ EOS",
5888                         mCodec->mComponentName.c_str(), bufferID);
5889                } else {
5890#if TRACK_BUFFER_TIMING
5891                    ALOGI("[%s] calling emptyBuffer %u w/ time %lld us",
5892                         mCodec->mComponentName.c_str(), bufferID, (long long)timeUs);
5893#else
5894                    ALOGV("[%s] calling emptyBuffer %u w/ time %lld us",
5895                         mCodec->mComponentName.c_str(), bufferID, (long long)timeUs);
5896#endif
5897                }
5898
5899#if TRACK_BUFFER_TIMING
5900                ACodec::BufferStats stats;
5901                stats.mEmptyBufferTimeUs = ALooper::GetNowUs();
5902                stats.mFillBufferDoneTimeUs = -1ll;
5903                mCodec->mBufferStats.add(timeUs, stats);
5904#endif
5905
5906                if (mCodec->storingMetadataInDecodedBuffers()) {
5907                    // try to submit an output buffer for each input buffer
5908                    PortMode outputMode = getPortMode(kPortIndexOutput);
5909
5910                    ALOGV("MetadataBuffersToSubmit=%u portMode=%s",
5911                            mCodec->mMetadataBuffersToSubmit,
5912                            (outputMode == FREE_BUFFERS ? "FREE" :
5913                             outputMode == KEEP_BUFFERS ? "KEEP" : "RESUBMIT"));
5914                    if (outputMode == RESUBMIT_BUFFERS) {
5915                        mCodec->submitOutputMetadataBuffer();
5916                    }
5917                }
5918                info->checkReadFence("onInputBufferFilled");
5919
5920                status_t err2 = OK;
5921                switch (mCodec->mPortMode[kPortIndexInput]) {
5922                case IOMX::kPortModePresetByteBuffer:
5923                case IOMX::kPortModePresetANWBuffer:
5924                case IOMX::kPortModePresetSecureBuffer:
5925                    {
5926                        err2 = mCodec->mOMXNode->emptyBuffer(
5927                            bufferID, info->mCodecData, flags, timeUs, info->mFenceFd);
5928                    }
5929                    break;
5930#ifndef OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
5931                case IOMX::kPortModeDynamicNativeHandle:
5932                    if (info->mCodecData->size() >= sizeof(VideoNativeHandleMetadata)) {
5933                        VideoNativeHandleMetadata *vnhmd =
5934                            (VideoNativeHandleMetadata*)info->mCodecData->base();
5935                        sp<NativeHandle> handle = NativeHandle::create(
5936                                vnhmd->pHandle, false /* ownsHandle */);
5937                        err2 = mCodec->mOMXNode->emptyBuffer(
5938                            bufferID, handle, flags, timeUs, info->mFenceFd);
5939                    }
5940                    break;
5941                case IOMX::kPortModeDynamicANWBuffer:
5942                    if (info->mCodecData->size() >= sizeof(VideoNativeMetadata)) {
5943                        VideoNativeMetadata *vnmd = (VideoNativeMetadata*)info->mCodecData->base();
5944                        sp<GraphicBuffer> graphicBuffer = GraphicBuffer::from(vnmd->pBuffer);
5945                        err2 = mCodec->mOMXNode->emptyBuffer(
5946                            bufferID, graphicBuffer, flags, timeUs, info->mFenceFd);
5947                    }
5948                    break;
5949#endif
5950                default:
5951                    ALOGW("Can't marshall %s data in %zu sized buffers in %zu-bit mode",
5952                            asString(mCodec->mPortMode[kPortIndexInput]),
5953                            info->mCodecData->size(),
5954                            sizeof(buffer_handle_t) * 8);
5955                    err2 = ERROR_UNSUPPORTED;
5956                    break;
5957                }
5958
5959                info->mFenceFd = -1;
5960                if (err2 != OK) {
5961                    mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err2));
5962                    return;
5963                }
5964                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
5965                // Hold the reference while component is using the buffer.
5966                info->mData = buffer;
5967
5968                if (!eos && err == OK) {
5969                    getMoreInputDataIfPossible();
5970                } else {
5971                    ALOGV("[%s] Signalled EOS (%d) on the input port",
5972                         mCodec->mComponentName.c_str(), err);
5973
5974                    mCodec->mPortEOS[kPortIndexInput] = true;
5975                    mCodec->mInputEOSResult = err;
5976                }
5977            } else if (!mCodec->mPortEOS[kPortIndexInput]) {
5978                if (err != OK && err != ERROR_END_OF_STREAM) {
5979                    ALOGV("[%s] Signalling EOS on the input port due to error %d",
5980                         mCodec->mComponentName.c_str(), err);
5981                } else {
5982                    ALOGV("[%s] Signalling EOS on the input port",
5983                         mCodec->mComponentName.c_str());
5984                }
5985
5986                ALOGV("[%s] calling emptyBuffer %u signalling EOS",
5987                     mCodec->mComponentName.c_str(), bufferID);
5988
5989                info->checkReadFence("onInputBufferFilled");
5990                status_t err2 = mCodec->mOMXNode->emptyBuffer(
5991                        bufferID, OMXBuffer::sPreset, OMX_BUFFERFLAG_EOS, 0, info->mFenceFd);
5992                info->mFenceFd = -1;
5993                if (err2 != OK) {
5994                    mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err2));
5995                    return;
5996                }
5997                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
5998
5999                mCodec->mPortEOS[kPortIndexInput] = true;
6000                mCodec->mInputEOSResult = err;
6001            }
6002            break;
6003        }
6004
6005        case FREE_BUFFERS:
6006            break;
6007
6008        default:
6009            ALOGE("invalid port mode: %d", mode);
6010            break;
6011    }
6012}
6013
6014void ACodec::BaseState::getMoreInputDataIfPossible() {
6015    if (mCodec->mPortEOS[kPortIndexInput]) {
6016        return;
6017    }
6018
6019    BufferInfo *eligible = NULL;
6020
6021    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
6022        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
6023
6024#if 0
6025        if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) {
6026            // There's already a "read" pending.
6027            return;
6028        }
6029#endif
6030
6031        if (info->mStatus == BufferInfo::OWNED_BY_US) {
6032            eligible = info;
6033        }
6034    }
6035
6036    if (eligible == NULL) {
6037        return;
6038    }
6039
6040    postFillThisBuffer(eligible);
6041}
6042
6043bool ACodec::BaseState::onOMXFillBufferDone(
6044        IOMX::buffer_id bufferID,
6045        size_t rangeOffset, size_t rangeLength,
6046        OMX_U32 flags,
6047        int64_t timeUs,
6048        int fenceFd) {
6049    ALOGV("[%s] onOMXFillBufferDone %u time %" PRId64 " us, flags = 0x%08x",
6050         mCodec->mComponentName.c_str(), bufferID, timeUs, flags);
6051
6052    ssize_t index;
6053    status_t err= OK;
6054
6055#if TRACK_BUFFER_TIMING
6056    index = mCodec->mBufferStats.indexOfKey(timeUs);
6057    if (index >= 0) {
6058        ACodec::BufferStats *stats = &mCodec->mBufferStats.editValueAt(index);
6059        stats->mFillBufferDoneTimeUs = ALooper::GetNowUs();
6060
6061        ALOGI("frame PTS %lld: %lld",
6062                timeUs,
6063                stats->mFillBufferDoneTimeUs - stats->mEmptyBufferTimeUs);
6064
6065        mCodec->mBufferStats.removeItemsAt(index);
6066        stats = NULL;
6067    }
6068#endif
6069
6070    BufferInfo *info =
6071        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
6072    BufferInfo::Status status = BufferInfo::getSafeStatus(info);
6073    if (status != BufferInfo::OWNED_BY_COMPONENT) {
6074        ALOGE("Wrong ownership in FBD: %s(%d) buffer #%u", _asString(status), status, bufferID);
6075        mCodec->dumpBuffers(kPortIndexOutput);
6076        mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
6077        if (fenceFd >= 0) {
6078            ::close(fenceFd);
6079        }
6080        return true;
6081    }
6082
6083    info->mDequeuedAt = ++mCodec->mDequeueCounter;
6084    info->mStatus = BufferInfo::OWNED_BY_US;
6085
6086    if (info->mRenderInfo != NULL) {
6087        // The fence for an emptied buffer must have signaled, but there still could be queued
6088        // or out-of-order dequeued buffers in the render queue prior to this buffer. Drop these,
6089        // as we will soon requeue this buffer to the surface. While in theory we could still keep
6090        // track of buffers that are requeued to the surface, it is better to add support to the
6091        // buffer-queue to notify us of released buffers and their fences (in the future).
6092        mCodec->notifyOfRenderedFrames(true /* dropIncomplete */);
6093    }
6094
6095    // byte buffers cannot take fences, so wait for any fence now
6096    if (mCodec->mNativeWindow == NULL) {
6097        (void)mCodec->waitForFence(fenceFd, "onOMXFillBufferDone");
6098        fenceFd = -1;
6099    }
6100    info->setReadFence(fenceFd, "onOMXFillBufferDone");
6101
6102    PortMode mode = getPortMode(kPortIndexOutput);
6103
6104    switch (mode) {
6105        case KEEP_BUFFERS:
6106            break;
6107
6108        case RESUBMIT_BUFFERS:
6109        {
6110            if (rangeLength == 0 && (!(flags & OMX_BUFFERFLAG_EOS)
6111                    || mCodec->mPortEOS[kPortIndexOutput])) {
6112                ALOGV("[%s] calling fillBuffer %u",
6113                     mCodec->mComponentName.c_str(), info->mBufferID);
6114
6115                err = mCodec->fillBuffer(info);
6116                if (err != OK) {
6117                    mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6118                    return true;
6119                }
6120                break;
6121            }
6122
6123            sp<MediaCodecBuffer> buffer = info->mData;
6124
6125            if (mCodec->mOutputFormat != mCodec->mLastOutputFormat && rangeLength > 0) {
6126                // pretend that output format has changed on the first frame (we used to do this)
6127                if (mCodec->mBaseOutputFormat == mCodec->mOutputFormat) {
6128                    mCodec->onOutputFormatChanged(mCodec->mOutputFormat);
6129                }
6130                mCodec->sendFormatChange();
6131            }
6132            buffer->setFormat(mCodec->mOutputFormat);
6133
6134            if (mCodec->usingSecureBufferOnEncoderOutput()) {
6135                native_handle_t *handle = NULL;
6136                sp<SecureBuffer> secureBuffer = static_cast<SecureBuffer *>(buffer.get());
6137                if (secureBuffer != NULL) {
6138#ifdef OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
6139                    // handle is only valid on 32-bit/mediaserver process
6140                    handle = NULL;
6141#else
6142                    handle = (native_handle_t *)secureBuffer->getDestinationPointer();
6143#endif
6144                }
6145                buffer->meta()->setPointer("handle", handle);
6146                buffer->meta()->setInt32("rangeOffset", rangeOffset);
6147                buffer->meta()->setInt32("rangeLength", rangeLength);
6148            } else if (buffer->base() == info->mCodecData->base()) {
6149                buffer->setRange(rangeOffset, rangeLength);
6150            } else {
6151                info->mCodecData->setRange(rangeOffset, rangeLength);
6152                // in this case we know that mConverter is not null
6153                status_t err = mCodec->mConverter[kPortIndexOutput]->convert(
6154                        info->mCodecData, buffer);
6155                if (err != OK) {
6156                    mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6157                    return true;
6158                }
6159            }
6160#if 0
6161            if (mCodec->mNativeWindow == NULL) {
6162                if (IsIDR(info->mData->data(), info->mData->size())) {
6163                    ALOGI("IDR frame");
6164                }
6165            }
6166#endif
6167
6168            if (mCodec->mSkipCutBuffer != NULL) {
6169                mCodec->mSkipCutBuffer->submit(buffer);
6170            }
6171            buffer->meta()->setInt64("timeUs", timeUs);
6172
6173            info->mData.clear();
6174
6175            mCodec->mBufferChannel->drainThisBuffer(info->mBufferID, flags);
6176
6177            info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;
6178
6179            if (flags & OMX_BUFFERFLAG_EOS) {
6180                ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str());
6181
6182                mCodec->mCallback->onEos(mCodec->mInputEOSResult);
6183                mCodec->mPortEOS[kPortIndexOutput] = true;
6184            }
6185            break;
6186        }
6187
6188        case FREE_BUFFERS:
6189            err = mCodec->freeBuffer(kPortIndexOutput, index);
6190            if (err != OK) {
6191                mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6192                return true;
6193            }
6194            break;
6195
6196        default:
6197            ALOGE("Invalid port mode: %d", mode);
6198            return false;
6199    }
6200
6201    return true;
6202}
6203
6204void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
6205    IOMX::buffer_id bufferID;
6206    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
6207    sp<RefBase> obj;
6208    CHECK(msg->findObject("buffer", &obj));
6209    sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
6210    int32_t discarded = 0;
6211    msg->findInt32("discarded", &discarded);
6212
6213    ssize_t index;
6214    BufferInfo *info = mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
6215    BufferInfo::Status status = BufferInfo::getSafeStatus(info);
6216    if (status != BufferInfo::OWNED_BY_DOWNSTREAM) {
6217        ALOGE("Wrong ownership in OBD: %s(%d) buffer #%u", _asString(status), status, bufferID);
6218        mCodec->dumpBuffers(kPortIndexOutput);
6219        mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
6220        return;
6221    }
6222    info->mData = buffer;
6223    int32_t render;
6224    if (mCodec->mNativeWindow != NULL
6225            && msg->findInt32("render", &render) && render != 0
6226            && !discarded && buffer->size() != 0) {
6227        ATRACE_NAME("render");
6228        // The client wants this buffer to be rendered.
6229
6230        android_native_rect_t crop;
6231        if (buffer->format()->findRect("crop", &crop.left, &crop.top, &crop.right, &crop.bottom)) {
6232            // NOTE: native window uses extended right-bottom coordinate
6233            ++crop.right;
6234            ++crop.bottom;
6235            if (memcmp(&crop, &mCodec->mLastNativeWindowCrop, sizeof(crop)) != 0) {
6236                mCodec->mLastNativeWindowCrop = crop;
6237                status_t err = native_window_set_crop(mCodec->mNativeWindow.get(), &crop);
6238                ALOGW_IF(err != NO_ERROR, "failed to set crop: %d", err);
6239            }
6240        }
6241
6242        int32_t dataSpace;
6243        if (buffer->format()->findInt32("android._dataspace", &dataSpace)
6244                && dataSpace != mCodec->mLastNativeWindowDataSpace) {
6245            status_t err = native_window_set_buffers_data_space(
6246                    mCodec->mNativeWindow.get(), (android_dataspace)dataSpace);
6247            mCodec->mLastNativeWindowDataSpace = dataSpace;
6248            ALOGW_IF(err != NO_ERROR, "failed to set dataspace: %d", err);
6249        }
6250        if (buffer->format()->contains("hdr-static-info")) {
6251            HDRStaticInfo info;
6252            if (ColorUtils::getHDRStaticInfoFromFormat(buffer->format(), &info)
6253                && memcmp(&mCodec->mLastHDRStaticInfo, &info, sizeof(info))) {
6254                setNativeWindowHdrMetadata(mCodec->mNativeWindow.get(), &info);
6255                mCodec->mLastHDRStaticInfo = info;
6256            }
6257        }
6258
6259        // save buffers sent to the surface so we can get render time when they return
6260        int64_t mediaTimeUs = -1;
6261        buffer->meta()->findInt64("timeUs", &mediaTimeUs);
6262        if (mediaTimeUs >= 0) {
6263            mCodec->mRenderTracker.onFrameQueued(
6264                    mediaTimeUs, info->mGraphicBuffer, new Fence(::dup(info->mFenceFd)));
6265        }
6266
6267        int64_t timestampNs = 0;
6268        if (!msg->findInt64("timestampNs", &timestampNs)) {
6269            // use media timestamp if client did not request a specific render timestamp
6270            if (buffer->meta()->findInt64("timeUs", &timestampNs)) {
6271                ALOGV("using buffer PTS of %lld", (long long)timestampNs);
6272                timestampNs *= 1000;
6273            }
6274        }
6275
6276        status_t err;
6277        err = native_window_set_buffers_timestamp(mCodec->mNativeWindow.get(), timestampNs);
6278        ALOGW_IF(err != NO_ERROR, "failed to set buffer timestamp: %d", err);
6279
6280        info->checkReadFence("onOutputBufferDrained before queueBuffer");
6281        err = mCodec->mNativeWindow->queueBuffer(
6282                    mCodec->mNativeWindow.get(), info->mGraphicBuffer.get(), info->mFenceFd);
6283        info->mFenceFd = -1;
6284        if (err == OK) {
6285            info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
6286        } else {
6287            ALOGE("queueBuffer failed in onOutputBufferDrained: %d", err);
6288            mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6289            info->mStatus = BufferInfo::OWNED_BY_US;
6290            // keeping read fence as write fence to avoid clobbering
6291            info->mIsReadFence = false;
6292        }
6293    } else {
6294        if (mCodec->mNativeWindow != NULL && (discarded || buffer->size() != 0)) {
6295            // move read fence into write fence to avoid clobbering
6296            info->mIsReadFence = false;
6297            ATRACE_NAME("frame-drop");
6298        }
6299        info->mStatus = BufferInfo::OWNED_BY_US;
6300    }
6301
6302    PortMode mode = getPortMode(kPortIndexOutput);
6303
6304    switch (mode) {
6305        case KEEP_BUFFERS:
6306        {
6307            // XXX fishy, revisit!!! What about the FREE_BUFFERS case below?
6308
6309            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
6310                // We cannot resubmit the buffer we just rendered, dequeue
6311                // the spare instead.
6312
6313                info = mCodec->dequeueBufferFromNativeWindow();
6314            }
6315            break;
6316        }
6317
6318        case RESUBMIT_BUFFERS:
6319        {
6320            if (!mCodec->mPortEOS[kPortIndexOutput]) {
6321                if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
6322                    // We cannot resubmit the buffer we just rendered, dequeue
6323                    // the spare instead.
6324
6325                    info = mCodec->dequeueBufferFromNativeWindow();
6326                }
6327
6328                if (info != NULL) {
6329                    ALOGV("[%s] calling fillBuffer %u",
6330                         mCodec->mComponentName.c_str(), info->mBufferID);
6331                    info->checkWriteFence("onOutputBufferDrained::RESUBMIT_BUFFERS");
6332                    status_t err = mCodec->fillBuffer(info);
6333                    if (err != OK) {
6334                        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6335                    }
6336                }
6337            }
6338            break;
6339        }
6340
6341        case FREE_BUFFERS:
6342        {
6343            status_t err = mCodec->freeBuffer(kPortIndexOutput, index);
6344            if (err != OK) {
6345                mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6346            }
6347            break;
6348        }
6349
6350        default:
6351            ALOGE("Invalid port mode: %d", mode);
6352            return;
6353    }
6354}
6355
6356////////////////////////////////////////////////////////////////////////////////
6357
6358ACodec::UninitializedState::UninitializedState(ACodec *codec)
6359    : BaseState(codec) {
6360}
6361
6362void ACodec::UninitializedState::stateEntered() {
6363    ALOGV("Now uninitialized");
6364
6365    if (mDeathNotifier != NULL) {
6366        if (mCodec->mOMXNode != NULL) {
6367            auto tOmxNode = mCodec->mOMXNode->getHalInterface();
6368            tOmxNode->unlinkToDeath(mDeathNotifier);
6369        }
6370        mDeathNotifier.clear();
6371    }
6372
6373    mCodec->mUsingNativeWindow = false;
6374    mCodec->mNativeWindow.clear();
6375    mCodec->mNativeWindowUsageBits = 0;
6376    mCodec->mOMX.clear();
6377    mCodec->mOMXNode.clear();
6378    mCodec->mFlags = 0;
6379    mCodec->mPortMode[kPortIndexInput] = IOMX::kPortModePresetByteBuffer;
6380    mCodec->mPortMode[kPortIndexOutput] = IOMX::kPortModePresetByteBuffer;
6381    mCodec->mConverter[0].clear();
6382    mCodec->mConverter[1].clear();
6383    mCodec->mComponentName.clear();
6384}
6385
6386bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
6387    bool handled = false;
6388
6389    switch (msg->what()) {
6390        case ACodec::kWhatSetup:
6391        {
6392            onSetup(msg);
6393
6394            handled = true;
6395            break;
6396        }
6397
6398        case ACodec::kWhatAllocateComponent:
6399        {
6400            onAllocateComponent(msg);
6401            handled = true;
6402            break;
6403        }
6404
6405        case ACodec::kWhatShutdown:
6406        {
6407            int32_t keepComponentAllocated;
6408            CHECK(msg->findInt32(
6409                        "keepComponentAllocated", &keepComponentAllocated));
6410            ALOGW_IF(keepComponentAllocated,
6411                     "cannot keep component allocated on shutdown in Uninitialized state");
6412            if (keepComponentAllocated) {
6413                mCodec->mCallback->onStopCompleted();
6414            } else {
6415                mCodec->mCallback->onReleaseCompleted();
6416            }
6417            handled = true;
6418            break;
6419        }
6420
6421        case ACodec::kWhatFlush:
6422        {
6423            mCodec->mCallback->onFlushCompleted();
6424            handled = true;
6425            break;
6426        }
6427
6428        case ACodec::kWhatReleaseCodecInstance:
6429        {
6430            // nothing to do, as we have already signaled shutdown
6431            handled = true;
6432            break;
6433        }
6434
6435        default:
6436            return BaseState::onMessageReceived(msg);
6437    }
6438
6439    return handled;
6440}
6441
6442void ACodec::UninitializedState::onSetup(
6443        const sp<AMessage> &msg) {
6444    if (onAllocateComponent(msg)
6445            && mCodec->mLoadedState->onConfigureComponent(msg)) {
6446        mCodec->mLoadedState->onStart();
6447    }
6448}
6449
6450bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
6451    ALOGV("onAllocateComponent");
6452
6453    CHECK(mCodec->mOMXNode == NULL);
6454
6455    sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec);
6456
6457    sp<RefBase> obj;
6458    CHECK(msg->findObject("codecInfo", &obj));
6459    sp<MediaCodecInfo> info = (MediaCodecInfo *)obj.get();
6460    if (info == nullptr) {
6461        ALOGE("Unexpected nullptr for codec information");
6462        mCodec->signalError(OMX_ErrorUndefined, UNKNOWN_ERROR);
6463        return false;
6464    }
6465    AString owner = (info->getOwnerName() == nullptr) ? "default" : info->getOwnerName();
6466
6467    AString componentName;
6468    CHECK(msg->findString("componentName", &componentName));
6469
6470    sp<CodecObserver> observer = new CodecObserver;
6471    sp<IOMX> omx;
6472    sp<IOMXNode> omxNode;
6473
6474    status_t err = NAME_NOT_FOUND;
6475    OMXClient client;
6476    if (client.connect(owner.c_str()) != OK) {
6477        mCodec->signalError(OMX_ErrorUndefined, NO_INIT);
6478        return false;
6479    }
6480    omx = client.interface();
6481
6482    pid_t tid = gettid();
6483    int prevPriority = androidGetThreadPriority(tid);
6484    androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
6485    err = omx->allocateNode(componentName.c_str(), observer, &omxNode);
6486    androidSetThreadPriority(tid, prevPriority);
6487
6488    if (err != OK) {
6489        ALOGE("Unable to instantiate codec '%s' with err %#x.", componentName.c_str(), err);
6490
6491        mCodec->signalError((OMX_ERRORTYPE)err, makeNoSideEffectStatus(err));
6492        return false;
6493    }
6494
6495    mDeathNotifier = new DeathNotifier(notify);
6496    auto tOmxNode = omxNode->getHalInterface();
6497    if (!tOmxNode->linkToDeath(mDeathNotifier, 0)) {
6498        mDeathNotifier.clear();
6499    }
6500
6501    notify = new AMessage(kWhatOMXMessageList, mCodec);
6502    notify->setInt32("generation", ++mCodec->mNodeGeneration);
6503    observer->setNotificationMessage(notify);
6504
6505    mCodec->mComponentName = componentName;
6506    mCodec->mRenderTracker.setComponentName(componentName);
6507    mCodec->mFlags = 0;
6508
6509    if (componentName.endsWith(".secure")) {
6510        mCodec->mFlags |= kFlagIsSecure;
6511        mCodec->mFlags |= kFlagIsGrallocUsageProtected;
6512        mCodec->mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
6513    }
6514
6515    mCodec->mOMX = omx;
6516    mCodec->mOMXNode = omxNode;
6517    mCodec->mCallback->onComponentAllocated(mCodec->mComponentName.c_str());
6518    mCodec->changeState(mCodec->mLoadedState);
6519
6520    return true;
6521}
6522
6523////////////////////////////////////////////////////////////////////////////////
6524
6525ACodec::LoadedState::LoadedState(ACodec *codec)
6526    : BaseState(codec) {
6527}
6528
6529void ACodec::LoadedState::stateEntered() {
6530    ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
6531
6532    mCodec->mPortEOS[kPortIndexInput] =
6533        mCodec->mPortEOS[kPortIndexOutput] = false;
6534
6535    mCodec->mInputEOSResult = OK;
6536
6537    mCodec->mDequeueCounter = 0;
6538    mCodec->mMetadataBuffersToSubmit = 0;
6539    mCodec->mRepeatFrameDelayUs = -1ll;
6540    mCodec->mInputFormat.clear();
6541    mCodec->mOutputFormat.clear();
6542    mCodec->mBaseOutputFormat.clear();
6543    mCodec->mGraphicBufferSource.clear();
6544
6545    if (mCodec->mShutdownInProgress) {
6546        bool keepComponentAllocated = mCodec->mKeepComponentAllocated;
6547
6548        mCodec->mShutdownInProgress = false;
6549        mCodec->mKeepComponentAllocated = false;
6550
6551        onShutdown(keepComponentAllocated);
6552    }
6553    mCodec->mExplicitShutdown = false;
6554
6555    mCodec->processDeferredMessages();
6556}
6557
6558void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) {
6559    if (!keepComponentAllocated) {
6560        (void)mCodec->mOMXNode->freeNode();
6561
6562        mCodec->changeState(mCodec->mUninitializedState);
6563    }
6564
6565    if (mCodec->mExplicitShutdown) {
6566        if (keepComponentAllocated) {
6567            mCodec->mCallback->onStopCompleted();
6568        } else {
6569            mCodec->mCallback->onReleaseCompleted();
6570        }
6571        mCodec->mExplicitShutdown = false;
6572    }
6573}
6574
6575bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) {
6576    bool handled = false;
6577
6578    switch (msg->what()) {
6579        case ACodec::kWhatConfigureComponent:
6580        {
6581            onConfigureComponent(msg);
6582            handled = true;
6583            break;
6584        }
6585
6586        case ACodec::kWhatCreateInputSurface:
6587        {
6588            onCreateInputSurface(msg);
6589            handled = true;
6590            break;
6591        }
6592
6593        case ACodec::kWhatSetInputSurface:
6594        {
6595            onSetInputSurface(msg);
6596            handled = true;
6597            break;
6598        }
6599
6600        case ACodec::kWhatStart:
6601        {
6602            onStart();
6603            handled = true;
6604            break;
6605        }
6606
6607        case ACodec::kWhatShutdown:
6608        {
6609            int32_t keepComponentAllocated;
6610            CHECK(msg->findInt32(
6611                        "keepComponentAllocated", &keepComponentAllocated));
6612
6613            mCodec->mExplicitShutdown = true;
6614            onShutdown(keepComponentAllocated);
6615
6616            handled = true;
6617            break;
6618        }
6619
6620        case ACodec::kWhatFlush:
6621        {
6622            mCodec->mCallback->onFlushCompleted();
6623            handled = true;
6624            break;
6625        }
6626
6627        default:
6628            return BaseState::onMessageReceived(msg);
6629    }
6630
6631    return handled;
6632}
6633
6634bool ACodec::LoadedState::onConfigureComponent(
6635        const sp<AMessage> &msg) {
6636    ALOGV("onConfigureComponent");
6637
6638    CHECK(mCodec->mOMXNode != NULL);
6639
6640    status_t err = OK;
6641    AString mime;
6642    if (!msg->findString("mime", &mime)) {
6643        err = BAD_VALUE;
6644    } else {
6645        err = mCodec->configureCodec(mime.c_str(), msg);
6646    }
6647    if (err != OK) {
6648        ALOGE("[%s] configureCodec returning error %d",
6649              mCodec->mComponentName.c_str(), err);
6650
6651        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6652        return false;
6653    }
6654
6655    mCodec->mCallback->onComponentConfigured(mCodec->mInputFormat, mCodec->mOutputFormat);
6656
6657    return true;
6658}
6659
6660status_t ACodec::LoadedState::setupInputSurface() {
6661    if (mCodec->mGraphicBufferSource == NULL) {
6662        return BAD_VALUE;
6663    }
6664
6665    android_dataspace dataSpace;
6666    status_t err =
6667        mCodec->setInitialColorAspectsForVideoEncoderSurfaceAndGetDataSpace(&dataSpace);
6668    if (err != OK) {
6669        ALOGE("Failed to get default data space");
6670        return err;
6671    }
6672
6673    err = statusFromBinderStatus(
6674            mCodec->mGraphicBufferSource->configure(mCodec->mOMXNode, dataSpace));
6675    if (err != OK) {
6676        ALOGE("[%s] Unable to configure for node (err %d)",
6677              mCodec->mComponentName.c_str(), err);
6678        return err;
6679    }
6680
6681    if (mCodec->mRepeatFrameDelayUs > 0ll) {
6682        err = statusFromBinderStatus(
6683                mCodec->mGraphicBufferSource->setRepeatPreviousFrameDelayUs(
6684                        mCodec->mRepeatFrameDelayUs));
6685
6686        if (err != OK) {
6687            ALOGE("[%s] Unable to configure option to repeat previous "
6688                  "frames (err %d)",
6689                  mCodec->mComponentName.c_str(), err);
6690            return err;
6691        }
6692    }
6693
6694    if (mCodec->mMaxPtsGapUs != 0ll) {
6695        OMX_PARAM_U32TYPE maxPtsGapParams;
6696        InitOMXParams(&maxPtsGapParams);
6697        maxPtsGapParams.nPortIndex = kPortIndexInput;
6698        maxPtsGapParams.nU32 = (uint32_t)mCodec->mMaxPtsGapUs;
6699
6700        err = mCodec->mOMXNode->setParameter(
6701                (OMX_INDEXTYPE)OMX_IndexParamMaxFrameDurationForBitrateControl,
6702                &maxPtsGapParams, sizeof(maxPtsGapParams));
6703
6704        if (err != OK) {
6705            ALOGE("[%s] Unable to configure max timestamp gap (err %d)",
6706                    mCodec->mComponentName.c_str(), err);
6707            return err;
6708        }
6709    }
6710
6711    if (mCodec->mMaxFps > 0 || mCodec->mMaxPtsGapUs < 0) {
6712        err = statusFromBinderStatus(
6713                mCodec->mGraphicBufferSource->setMaxFps(mCodec->mMaxFps));
6714
6715        if (err != OK) {
6716            ALOGE("[%s] Unable to configure max fps (err %d)",
6717                    mCodec->mComponentName.c_str(), err);
6718            return err;
6719        }
6720    }
6721
6722    if (mCodec->mCaptureFps > 0. && mCodec->mFps > 0.) {
6723        err = statusFromBinderStatus(
6724                mCodec->mGraphicBufferSource->setTimeLapseConfig(
6725                        mCodec->mFps, mCodec->mCaptureFps));
6726
6727        if (err != OK) {
6728            ALOGE("[%s] Unable to configure time lapse (err %d)",
6729                    mCodec->mComponentName.c_str(), err);
6730            return err;
6731        }
6732    }
6733
6734    if (mCodec->mCreateInputBuffersSuspended) {
6735        err = statusFromBinderStatus(
6736                mCodec->mGraphicBufferSource->setSuspend(true, -1));
6737
6738        if (err != OK) {
6739            ALOGE("[%s] Unable to configure option to suspend (err %d)",
6740                  mCodec->mComponentName.c_str(), err);
6741            return err;
6742        }
6743    }
6744
6745    uint32_t usageBits;
6746    if (mCodec->mOMXNode->getParameter(
6747            (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
6748            &usageBits, sizeof(usageBits)) == OK) {
6749        mCodec->mInputFormat->setInt32(
6750                "using-sw-read-often", !!(usageBits & GRALLOC_USAGE_SW_READ_OFTEN));
6751    }
6752
6753    sp<ABuffer> colorAspectsBuffer;
6754    if (mCodec->mInputFormat->findBuffer("android._color-aspects", &colorAspectsBuffer)) {
6755        if (colorAspectsBuffer->size() != sizeof(ColorAspects)) {
6756            return INVALID_OPERATION;
6757        }
6758
6759        err = statusFromBinderStatus(
6760                mCodec->mGraphicBufferSource->setColorAspects(ColorUtils::packToU32(
6761                        *(ColorAspects *)colorAspectsBuffer->base())));
6762
6763        if (err != OK) {
6764            ALOGE("[%s] Unable to configure color aspects (err %d)",
6765                  mCodec->mComponentName.c_str(), err);
6766            return err;
6767        }
6768    }
6769    return OK;
6770}
6771
6772void ACodec::LoadedState::onCreateInputSurface(
6773        const sp<AMessage> & /* msg */) {
6774    ALOGV("onCreateInputSurface");
6775
6776    sp<IGraphicBufferProducer> bufferProducer;
6777    status_t err = mCodec->mOMX->createInputSurface(
6778            &bufferProducer, &mCodec->mGraphicBufferSource);
6779
6780    if (err == OK) {
6781        err = setupInputSurface();
6782    }
6783
6784    if (err == OK) {
6785        mCodec->mCallback->onInputSurfaceCreated(
6786                mCodec->mInputFormat,
6787                mCodec->mOutputFormat,
6788                new BufferProducerWrapper(bufferProducer));
6789    } else {
6790        // Can't use mCodec->signalError() here -- MediaCodec won't forward
6791        // the error through because it's in the "configured" state.  We
6792        // send a kWhatInputSurfaceCreated with an error value instead.
6793        ALOGE("[%s] onCreateInputSurface returning error %d",
6794                mCodec->mComponentName.c_str(), err);
6795        mCodec->mCallback->onInputSurfaceCreationFailed(err);
6796    }
6797}
6798
6799void ACodec::LoadedState::onSetInputSurface(const sp<AMessage> &msg) {
6800    ALOGV("onSetInputSurface");
6801
6802    sp<RefBase> obj;
6803    CHECK(msg->findObject("input-surface", &obj));
6804    if (obj == NULL) {
6805        ALOGE("[%s] NULL input surface", mCodec->mComponentName.c_str());
6806        mCodec->mCallback->onInputSurfaceDeclined(BAD_VALUE);
6807        return;
6808    }
6809
6810    sp<PersistentSurface> surface = static_cast<PersistentSurface *>(obj.get());
6811    mCodec->mGraphicBufferSource = surface->getBufferSource();
6812    status_t err = setupInputSurface();
6813
6814    if (err == OK) {
6815        mCodec->mCallback->onInputSurfaceAccepted(
6816                mCodec->mInputFormat, mCodec->mOutputFormat);
6817    } else {
6818        // Can't use mCodec->signalError() here -- MediaCodec won't forward
6819        // the error through because it's in the "configured" state.  We
6820        // send a kWhatInputSurfaceAccepted with an error value instead.
6821        ALOGE("[%s] onSetInputSurface returning error %d",
6822                mCodec->mComponentName.c_str(), err);
6823        mCodec->mCallback->onInputSurfaceDeclined(err);
6824    }
6825}
6826
6827void ACodec::LoadedState::onStart() {
6828    ALOGV("onStart");
6829
6830    status_t err = mCodec->mOMXNode->sendCommand(OMX_CommandStateSet, OMX_StateIdle);
6831    if (err != OK) {
6832        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6833    } else {
6834        mCodec->changeState(mCodec->mLoadedToIdleState);
6835    }
6836}
6837
6838////////////////////////////////////////////////////////////////////////////////
6839
6840ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec)
6841    : BaseState(codec) {
6842}
6843
6844void ACodec::LoadedToIdleState::stateEntered() {
6845    ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
6846
6847    status_t err;
6848    if ((err = allocateBuffers()) != OK) {
6849        ALOGE("Failed to allocate buffers after transitioning to IDLE state "
6850             "(error 0x%08x)",
6851             err);
6852
6853        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6854
6855        mCodec->mOMXNode->sendCommand(
6856                OMX_CommandStateSet, OMX_StateLoaded);
6857        if (mCodec->allYourBuffersAreBelongToUs(kPortIndexInput)) {
6858            mCodec->freeBuffersOnPort(kPortIndexInput);
6859        }
6860        if (mCodec->allYourBuffersAreBelongToUs(kPortIndexOutput)) {
6861            mCodec->freeBuffersOnPort(kPortIndexOutput);
6862        }
6863
6864        mCodec->changeState(mCodec->mLoadedState);
6865    }
6866}
6867
6868status_t ACodec::LoadedToIdleState::allocateBuffers() {
6869    status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput);
6870    if (err != OK) {
6871        return err;
6872    }
6873
6874    err = mCodec->allocateBuffersOnPort(kPortIndexOutput);
6875    if (err != OK) {
6876        return err;
6877    }
6878
6879    mCodec->mCallback->onStartCompleted();
6880
6881    return OK;
6882}
6883
6884bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
6885    switch (msg->what()) {
6886        case kWhatSetParameters:
6887        case kWhatShutdown:
6888        {
6889            mCodec->deferMessage(msg);
6890            return true;
6891        }
6892
6893        case kWhatSignalEndOfInputStream:
6894        {
6895            mCodec->onSignalEndOfInputStream();
6896            return true;
6897        }
6898
6899        case kWhatResume:
6900        {
6901            // We'll be active soon enough.
6902            return true;
6903        }
6904
6905        case kWhatFlush:
6906        {
6907            // We haven't even started yet, so we're flushed alright...
6908            mCodec->mCallback->onFlushCompleted();
6909            return true;
6910        }
6911
6912        default:
6913            return BaseState::onMessageReceived(msg);
6914    }
6915}
6916
6917bool ACodec::LoadedToIdleState::onOMXEvent(
6918        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
6919    switch (event) {
6920        case OMX_EventCmdComplete:
6921        {
6922            status_t err = OK;
6923            if (data1 != (OMX_U32)OMX_CommandStateSet
6924                    || data2 != (OMX_U32)OMX_StateIdle) {
6925                ALOGE("Unexpected command completion in LoadedToIdleState: %s(%u) %s(%u)",
6926                        asString((OMX_COMMANDTYPE)data1), data1,
6927                        asString((OMX_STATETYPE)data2), data2);
6928                err = FAILED_TRANSACTION;
6929            }
6930
6931            if (err == OK) {
6932                err = mCodec->mOMXNode->sendCommand(
6933                    OMX_CommandStateSet, OMX_StateExecuting);
6934            }
6935
6936            if (err != OK) {
6937                mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6938            } else {
6939                mCodec->changeState(mCodec->mIdleToExecutingState);
6940            }
6941
6942            return true;
6943        }
6944
6945        default:
6946            return BaseState::onOMXEvent(event, data1, data2);
6947    }
6948}
6949
6950////////////////////////////////////////////////////////////////////////////////
6951
6952ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec)
6953    : BaseState(codec) {
6954}
6955
6956void ACodec::IdleToExecutingState::stateEntered() {
6957    ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
6958}
6959
6960bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
6961    switch (msg->what()) {
6962        case kWhatSetParameters:
6963        case kWhatShutdown:
6964        {
6965            mCodec->deferMessage(msg);
6966            return true;
6967        }
6968
6969        case kWhatResume:
6970        {
6971            // We'll be active soon enough.
6972            return true;
6973        }
6974
6975        case kWhatFlush:
6976        {
6977            // We haven't even started yet, so we're flushed alright...
6978            mCodec->mCallback->onFlushCompleted();
6979            return true;
6980        }
6981
6982        case kWhatSignalEndOfInputStream:
6983        {
6984            mCodec->onSignalEndOfInputStream();
6985            return true;
6986        }
6987
6988        default:
6989            return BaseState::onMessageReceived(msg);
6990    }
6991}
6992
6993bool ACodec::IdleToExecutingState::onOMXEvent(
6994        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
6995    switch (event) {
6996        case OMX_EventCmdComplete:
6997        {
6998            if (data1 != (OMX_U32)OMX_CommandStateSet
6999                    || data2 != (OMX_U32)OMX_StateExecuting) {
7000                ALOGE("Unexpected command completion in IdleToExecutingState: %s(%u) %s(%u)",
7001                        asString((OMX_COMMANDTYPE)data1), data1,
7002                        asString((OMX_STATETYPE)data2), data2);
7003                mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
7004                return true;
7005            }
7006
7007            mCodec->mExecutingState->resume();
7008            mCodec->changeState(mCodec->mExecutingState);
7009
7010            return true;
7011        }
7012
7013        default:
7014            return BaseState::onOMXEvent(event, data1, data2);
7015    }
7016}
7017
7018////////////////////////////////////////////////////////////////////////////////
7019
7020ACodec::ExecutingState::ExecutingState(ACodec *codec)
7021    : BaseState(codec),
7022      mActive(false) {
7023}
7024
7025ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode(
7026        OMX_U32 /* portIndex */) {
7027    return RESUBMIT_BUFFERS;
7028}
7029
7030void ACodec::ExecutingState::submitOutputMetaBuffers() {
7031    // submit as many buffers as there are input buffers with the codec
7032    // in case we are in port reconfiguring
7033    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
7034        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
7035
7036        if (info->mStatus == BufferInfo::OWNED_BY_COMPONENT) {
7037            if (mCodec->submitOutputMetadataBuffer() != OK)
7038                break;
7039        }
7040    }
7041
7042    // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
7043    mCodec->signalSubmitOutputMetadataBufferIfEOS_workaround();
7044}
7045
7046void ACodec::ExecutingState::submitRegularOutputBuffers() {
7047    bool failed = false;
7048    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
7049        BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
7050
7051        if (mCodec->mNativeWindow != NULL) {
7052            if (info->mStatus != BufferInfo::OWNED_BY_US
7053                    && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
7054                ALOGE("buffers should be owned by us or the surface");
7055                failed = true;
7056                break;
7057            }
7058
7059            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
7060                continue;
7061            }
7062        } else {
7063            if (info->mStatus != BufferInfo::OWNED_BY_US) {
7064                ALOGE("buffers should be owned by us");
7065                failed = true;
7066                break;
7067            }
7068        }
7069
7070        ALOGV("[%s] calling fillBuffer %u", mCodec->mComponentName.c_str(), info->mBufferID);
7071
7072        info->checkWriteFence("submitRegularOutputBuffers");
7073        status_t err = mCodec->fillBuffer(info);
7074        if (err != OK) {
7075            failed = true;
7076            break;
7077        }
7078    }
7079
7080    if (failed) {
7081        mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
7082    }
7083}
7084
7085void ACodec::ExecutingState::submitOutputBuffers() {
7086    submitRegularOutputBuffers();
7087    if (mCodec->storingMetadataInDecodedBuffers()) {
7088        submitOutputMetaBuffers();
7089    }
7090}
7091
7092void ACodec::ExecutingState::resume() {
7093    if (mActive) {
7094        ALOGV("[%s] We're already active, no need to resume.", mCodec->mComponentName.c_str());
7095        return;
7096    }
7097
7098    submitOutputBuffers();
7099
7100    // Post all available input buffers
7101    if (mCodec->mBuffers[kPortIndexInput].size() == 0u) {
7102        ALOGW("[%s] we don't have any input buffers to resume", mCodec->mComponentName.c_str());
7103    }
7104
7105    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); i++) {
7106        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
7107        if (info->mStatus == BufferInfo::OWNED_BY_US) {
7108            postFillThisBuffer(info);
7109        }
7110    }
7111
7112    mActive = true;
7113}
7114
7115void ACodec::ExecutingState::stateEntered() {
7116    ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
7117    mCodec->mRenderTracker.clear(systemTime(CLOCK_MONOTONIC));
7118    mCodec->processDeferredMessages();
7119}
7120
7121bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) {
7122    bool handled = false;
7123
7124    switch (msg->what()) {
7125        case kWhatShutdown:
7126        {
7127            int32_t keepComponentAllocated;
7128            CHECK(msg->findInt32(
7129                        "keepComponentAllocated", &keepComponentAllocated));
7130
7131            mCodec->mShutdownInProgress = true;
7132            mCodec->mExplicitShutdown = true;
7133            mCodec->mKeepComponentAllocated = keepComponentAllocated;
7134
7135            mActive = false;
7136
7137            status_t err = mCodec->mOMXNode->sendCommand(
7138                    OMX_CommandStateSet, OMX_StateIdle);
7139            if (err != OK) {
7140                if (keepComponentAllocated) {
7141                    mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
7142                }
7143                // TODO: do some recovery here.
7144            } else {
7145                mCodec->changeState(mCodec->mExecutingToIdleState);
7146            }
7147
7148            handled = true;
7149            break;
7150        }
7151
7152        case kWhatFlush:
7153        {
7154            ALOGV("[%s] ExecutingState flushing now "
7155                 "(codec owns %zu/%zu input, %zu/%zu output).",
7156                    mCodec->mComponentName.c_str(),
7157                    mCodec->countBuffersOwnedByComponent(kPortIndexInput),
7158                    mCodec->mBuffers[kPortIndexInput].size(),
7159                    mCodec->countBuffersOwnedByComponent(kPortIndexOutput),
7160                    mCodec->mBuffers[kPortIndexOutput].size());
7161
7162            mActive = false;
7163
7164            status_t err = mCodec->mOMXNode->sendCommand(OMX_CommandFlush, OMX_ALL);
7165            if (err != OK) {
7166                mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
7167            } else {
7168                mCodec->changeState(mCodec->mFlushingState);
7169            }
7170
7171            handled = true;
7172            break;
7173        }
7174
7175        case kWhatResume:
7176        {
7177            resume();
7178
7179            handled = true;
7180            break;
7181        }
7182
7183        case kWhatRequestIDRFrame:
7184        {
7185            status_t err = mCodec->requestIDRFrame();
7186            if (err != OK) {
7187                ALOGW("Requesting an IDR frame failed.");
7188            }
7189
7190            handled = true;
7191            break;
7192        }
7193
7194        case kWhatSetParameters:
7195        {
7196            sp<AMessage> params;
7197            CHECK(msg->findMessage("params", &params));
7198
7199            status_t err = mCodec->setParameters(params);
7200
7201            sp<AMessage> reply;
7202            if (msg->findMessage("reply", &reply)) {
7203                reply->setInt32("err", err);
7204                reply->post();
7205            }
7206
7207            handled = true;
7208            break;
7209        }
7210
7211        case ACodec::kWhatSignalEndOfInputStream:
7212        {
7213            mCodec->onSignalEndOfInputStream();
7214            handled = true;
7215            break;
7216        }
7217
7218        // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
7219        case kWhatSubmitOutputMetadataBufferIfEOS:
7220        {
7221            if (mCodec->mPortEOS[kPortIndexInput] &&
7222                    !mCodec->mPortEOS[kPortIndexOutput]) {
7223                status_t err = mCodec->submitOutputMetadataBuffer();
7224                if (err == OK) {
7225                    mCodec->signalSubmitOutputMetadataBufferIfEOS_workaround();
7226                }
7227            }
7228            return true;
7229        }
7230
7231        default:
7232            handled = BaseState::onMessageReceived(msg);
7233            break;
7234    }
7235
7236    return handled;
7237}
7238
7239status_t ACodec::setParameters(const sp<AMessage> &params) {
7240    int32_t videoBitrate;
7241    if (params->findInt32("video-bitrate", &videoBitrate)) {
7242        OMX_VIDEO_CONFIG_BITRATETYPE configParams;
7243        InitOMXParams(&configParams);
7244        configParams.nPortIndex = kPortIndexOutput;
7245        configParams.nEncodeBitrate = videoBitrate;
7246
7247        status_t err = mOMXNode->setConfig(
7248                OMX_IndexConfigVideoBitrate,
7249                &configParams,
7250                sizeof(configParams));
7251
7252        if (err != OK) {
7253            ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d",
7254                   videoBitrate, err);
7255
7256            return err;
7257        }
7258    }
7259
7260    int64_t timeOffsetUs;
7261    if (params->findInt64("time-offset-us", &timeOffsetUs)) {
7262        if (mGraphicBufferSource == NULL) {
7263            ALOGE("[%s] Invalid to set input buffer time offset without surface",
7264                    mComponentName.c_str());
7265            return INVALID_OPERATION;
7266        }
7267
7268        status_t err = statusFromBinderStatus(
7269                mGraphicBufferSource->setTimeOffsetUs(timeOffsetUs));
7270
7271        if (err != OK) {
7272            ALOGE("[%s] Unable to set input buffer time offset (err %d)",
7273                mComponentName.c_str(),
7274                err);
7275            return err;
7276        }
7277    }
7278
7279    int64_t skipFramesBeforeUs;
7280    if (params->findInt64("skip-frames-before", &skipFramesBeforeUs)) {
7281        if (mGraphicBufferSource == NULL) {
7282            ALOGE("[%s] Invalid to set start time without surface",
7283                    mComponentName.c_str());
7284            return INVALID_OPERATION;
7285        }
7286
7287        status_t err = statusFromBinderStatus(
7288                mGraphicBufferSource->setStartTimeUs(skipFramesBeforeUs));
7289
7290        if (err != OK) {
7291            ALOGE("Failed to set parameter 'skip-frames-before' (err %d)", err);
7292            return err;
7293        }
7294    }
7295
7296    int32_t dropInputFrames;
7297    if (params->findInt32("drop-input-frames", &dropInputFrames)) {
7298        if (mGraphicBufferSource == NULL) {
7299            ALOGE("[%s] Invalid to set suspend without surface",
7300                    mComponentName.c_str());
7301            return INVALID_OPERATION;
7302        }
7303
7304        int64_t suspendStartTimeUs = -1;
7305        (void) params->findInt64("drop-start-time-us", &suspendStartTimeUs);
7306        status_t err = statusFromBinderStatus(
7307                mGraphicBufferSource->setSuspend(dropInputFrames != 0, suspendStartTimeUs));
7308
7309        if (err != OK) {
7310            ALOGE("Failed to set parameter 'drop-input-frames' (err %d)", err);
7311            return err;
7312        }
7313    }
7314
7315    int64_t stopTimeUs;
7316    if (params->findInt64("stop-time-us", &stopTimeUs)) {
7317        if (mGraphicBufferSource == NULL) {
7318            ALOGE("[%s] Invalid to set stop time without surface",
7319                    mComponentName.c_str());
7320            return INVALID_OPERATION;
7321        }
7322        status_t err = statusFromBinderStatus(
7323                mGraphicBufferSource->setStopTimeUs(stopTimeUs));
7324
7325        if (err != OK) {
7326            ALOGE("Failed to set parameter 'stop-time-us' (err %d)", err);
7327            return err;
7328        }
7329
7330        int64_t stopTimeOffsetUs;
7331        err = statusFromBinderStatus(
7332                mGraphicBufferSource->getStopTimeOffsetUs(&stopTimeOffsetUs));
7333
7334        if (err != OK) {
7335            ALOGE("Failed to get stop time offset (err %d)", err);
7336            return err;
7337        }
7338        mInputFormat->setInt64("android._stop-time-offset-us", stopTimeOffsetUs);
7339    }
7340
7341    int32_t dummy;
7342    if (params->findInt32("request-sync", &dummy)) {
7343        status_t err = requestIDRFrame();
7344
7345        if (err != OK) {
7346            ALOGE("Requesting a sync frame failed w/ err %d", err);
7347            return err;
7348        }
7349    }
7350
7351    int32_t rateInt = -1;
7352    float rateFloat = -1;
7353    if (!params->findFloat("operating-rate", &rateFloat)) {
7354        params->findInt32("operating-rate", &rateInt);
7355        rateFloat = (float) rateInt; // 16MHz (FLINTMAX) is OK for upper bound.
7356    }
7357    if (rateFloat > 0) {
7358        status_t err = setOperatingRate(rateFloat, mIsVideo);
7359        if (err != OK) {
7360            ALOGI("Failed to set parameter 'operating-rate' (err %d)", err);
7361        }
7362    }
7363
7364    int32_t intraRefreshPeriod = 0;
7365    if (params->findInt32("intra-refresh-period", &intraRefreshPeriod)
7366            && intraRefreshPeriod > 0) {
7367        status_t err = setIntraRefreshPeriod(intraRefreshPeriod, false);
7368        if (err != OK) {
7369            ALOGI("[%s] failed setIntraRefreshPeriod. Failure is fine since this key is optional",
7370                    mComponentName.c_str());
7371            err = OK;
7372        }
7373    }
7374
7375    int32_t latency = 0;
7376    if (params->findInt32("latency", &latency) && latency > 0) {
7377        status_t err = setLatency(latency);
7378        if (err != OK) {
7379            ALOGI("[%s] failed setLatency. Failure is fine since this key is optional",
7380                    mComponentName.c_str());
7381            err = OK;
7382        }
7383    }
7384
7385    // Ignore errors as failure is expected for codecs that aren't video encoders.
7386    (void)configureTemporalLayers(params, false /* inConfigure */, mOutputFormat);
7387
7388    return setVendorParameters(params);
7389}
7390
7391// Removes trailing tags matching |tag| from |key| (e.g. a settings name). |minLength| specifies
7392// the minimum number of characters to keep in |key| (even if it has trailing tags).
7393// (Used to remove trailing 'value' tags in settings names, e.g. to normalize
7394// 'vendor.settingsX.value' to 'vendor.settingsX')
7395static void removeTrailingTags(char *key, size_t minLength, const char *tag) {
7396    size_t length = strlen(key);
7397    size_t tagLength = strlen(tag);
7398    while (length > minLength + tagLength
7399            && !strcmp(key + length - tagLength, tag)
7400            && key[length - tagLength - 1] == '.') {
7401        length -= tagLength + 1;
7402        key[length] = '\0';
7403    }
7404}
7405
7406/**
7407 * Struct encompassing a vendor extension config structure and a potential error status (in case
7408 * the structure is null). Used to iterate through vendor extensions.
7409 */
7410struct VendorExtension {
7411    OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *config;  // structure does not own config
7412    status_t status;
7413
7414    // create based on an error status
7415    VendorExtension(status_t s_ = NO_INIT) : config(nullptr), status(s_) { }
7416
7417    // create based on a successfully retrieved config structure
7418    VendorExtension(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *c_) : config(c_), status(OK) { }
7419};
7420
7421// class VendorExtensions;
7422/**
7423 * Forward iterator to enumerate vendor extensions supported by an OMX component.
7424 */
7425class VendorExtensionIterator {
7426//private:
7427    static constexpr size_t kLastIndex = ~(size_t)0; // last index marker
7428
7429    sp<IOMXNode> mNode;                   // component
7430    size_t mIndex;                        // current android extension index
7431    std::unique_ptr<uint8_t[]> mBacking;  // current extension's backing
7432    VendorExtension mCurrent;             // current extension
7433
7434    VendorExtensionIterator(const sp<IOMXNode> &node, size_t index)
7435        : mNode(node),
7436          mIndex(index) {
7437        mCurrent = retrieve();
7438    }
7439
7440    friend class VendorExtensions;
7441
7442public:
7443    // copy constructor
7444    VendorExtensionIterator(const VendorExtensionIterator &it)
7445        : VendorExtensionIterator(it.mNode, it.mIndex) { }
7446
7447    // retrieves the current extension pointed to by this iterator
7448    VendorExtension retrieve() {
7449        if (mIndex == kLastIndex) {
7450            return NO_INIT;
7451        }
7452
7453        // try with one param first, then retry if extension needs more than 1 param
7454        for (size_t paramSizeUsed = 1;; ) {
7455            if (paramSizeUsed > OMX_MAX_ANDROID_VENDOR_PARAMCOUNT) {
7456                return BAD_VALUE; // this prevents overflow in the following formula
7457            }
7458
7459            size_t size = sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE) +
7460                (paramSizeUsed - 1) * sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE::param);
7461            mBacking.reset(new uint8_t[size]);
7462            if (!mBacking) {
7463                return NO_MEMORY;
7464            }
7465
7466            OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *config =
7467                reinterpret_cast<OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *>(mBacking.get());
7468
7469            InitOMXParams(config);
7470            config->nSize = size;
7471            config->nIndex = mIndex;
7472            config->nParamSizeUsed = paramSizeUsed;
7473            status_t err = mNode->getConfig(
7474                    (OMX_INDEXTYPE)OMX_IndexConfigAndroidVendorExtension, config, size);
7475            if (err == OK && config->nParamCount > paramSizeUsed && paramSizeUsed == 1) {
7476                // reallocate if we need a bigger config
7477                paramSizeUsed = config->nParamCount;
7478                continue;
7479            } else if (err == NOT_ENOUGH_DATA
7480                   || (err != OK && mIndex == 0)) {
7481                // stop iterator on no-more signal, or if index is not at all supported
7482                mIndex = kLastIndex;
7483                return NO_INIT;
7484            } else if (err != OK) {
7485                return err;
7486            } else if (paramSizeUsed != config->nParamSizeUsed) {
7487                return BAD_VALUE; // component shall not modify size of nParam
7488            }
7489
7490            return config;
7491        }
7492    }
7493
7494    // returns extension pointed to by this iterator
7495    VendorExtension operator*() {
7496        return mCurrent;
7497    }
7498
7499    // prefix increment: move to next extension
7500    VendorExtensionIterator &operator++() { // prefix
7501        if (mIndex != kLastIndex) {
7502            ++mIndex;
7503            mCurrent = retrieve();
7504        }
7505        return *this;
7506    }
7507
7508    // iterator equality operators
7509    bool operator==(const VendorExtensionIterator &o) {
7510        return mNode == o.mNode && mIndex == o.mIndex;
7511    }
7512
7513    bool operator!=(const VendorExtensionIterator &o) {
7514        return !(*this == o);
7515    }
7516};
7517
7518/**
7519 * Iterable container for vendor extensions provided by a component
7520 */
7521class VendorExtensions {
7522//private:
7523    sp<IOMXNode> mNode;
7524
7525public:
7526    VendorExtensions(const sp<IOMXNode> &node)
7527        : mNode(node) {
7528    }
7529
7530    VendorExtensionIterator begin() {
7531        return VendorExtensionIterator(mNode, 0);
7532    }
7533
7534    VendorExtensionIterator end() {
7535        return VendorExtensionIterator(mNode, VendorExtensionIterator::kLastIndex);
7536    }
7537};
7538
7539status_t ACodec::setVendorParameters(const sp<AMessage> &params) {
7540    std::map<std::string, std::string> vendorKeys; // maps reduced name to actual name
7541    constexpr char prefix[] = "vendor.";
7542    constexpr size_t prefixLength = sizeof(prefix) - 1;
7543    // longest possible vendor param name
7544    char reducedKey[OMX_MAX_STRINGNAME_SIZE + OMX_MAX_STRINGVALUE_SIZE];
7545
7546    // identify all vendor keys to speed up search later and to detect vendor keys
7547    for (size_t i = params->countEntries(); i; --i) {
7548        AMessage::Type keyType;
7549        const char* key = params->getEntryNameAt(i - 1, &keyType);
7550        if (key != nullptr && !strncmp(key, prefix, prefixLength)
7551                // it is safe to limit format keys to the max vendor param size as we only
7552                // shorten parameter names by removing any trailing 'value' tags, and we
7553                // already remove the vendor prefix.
7554                && strlen(key + prefixLength) < sizeof(reducedKey)
7555                && (keyType == AMessage::kTypeInt32
7556                        || keyType == AMessage::kTypeInt64
7557                        || keyType == AMessage::kTypeString)) {
7558            strcpy(reducedKey, key + prefixLength);
7559            removeTrailingTags(reducedKey, 0, "value");
7560            auto existingKey = vendorKeys.find(reducedKey);
7561            if (existingKey != vendorKeys.end()) {
7562                ALOGW("[%s] vendor parameter '%s' aliases parameter '%s'",
7563                        mComponentName.c_str(), key, existingKey->second.c_str());
7564                // ignore for now
7565            }
7566            vendorKeys.emplace(reducedKey, key);
7567        }
7568    }
7569
7570    // don't bother component if we don't have vendor extensions as they may not have implemented
7571    // the android vendor extension support, which will lead to unnecessary OMX failure logs.
7572    if (vendorKeys.empty()) {
7573        return OK;
7574    }
7575
7576    char key[sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE::cName) +
7577            sizeof(OMX_CONFIG_ANDROID_VENDOR_PARAMTYPE::cKey)];
7578
7579    status_t finalError = OK;
7580
7581    // don't try again if component does not have vendor extensions
7582    if (mVendorExtensionsStatus == kExtensionsNone) {
7583        return OK;
7584    }
7585
7586    for (VendorExtension ext : VendorExtensions(mOMXNode)) {
7587        OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *config = ext.config;
7588        if (config == nullptr) {
7589            return ext.status;
7590        }
7591
7592        mVendorExtensionsStatus = kExtensionsExist;
7593
7594        config->cName[sizeof(config->cName) - 1] = '\0'; // null-terminate name
7595        strcpy(key, (const char *)config->cName);
7596        size_t nameLength = strlen(key);
7597        key[nameLength] = '.';
7598
7599        // don't set vendor extension if client has not provided any of its parameters
7600        // or if client simply unsets parameters that are already unset
7601        bool needToSet = false;
7602        for (size_t paramIndex = 0; paramIndex < config->nParamCount; ++paramIndex) {
7603            // null-terminate param key
7604            config->param[paramIndex].cKey[sizeof(config->param[0].cKey) - 1] = '\0';
7605            strcpy(key + nameLength + 1, (const char *)config->param[paramIndex].cKey);
7606            removeTrailingTags(key, nameLength, "value");
7607            auto existingKey = vendorKeys.find(key);
7608
7609            // don't touch (e.g. change) parameters that are not specified by client
7610            if (existingKey == vendorKeys.end()) {
7611                continue;
7612            }
7613
7614            bool wasSet = config->param[paramIndex].bSet;
7615            switch (config->param[paramIndex].eValueType) {
7616            case OMX_AndroidVendorValueInt32:
7617            {
7618                int32_t value;
7619                config->param[paramIndex].bSet =
7620                    (OMX_BOOL)params->findInt32(existingKey->second.c_str(), &value);
7621                if (config->param[paramIndex].bSet) {
7622                    config->param[paramIndex].nInt32 = value;
7623                }
7624                break;
7625            }
7626            case OMX_AndroidVendorValueInt64:
7627            {
7628                int64_t value;
7629                config->param[paramIndex].bSet =
7630                    (OMX_BOOL)params->findAsInt64(existingKey->second.c_str(), &value);
7631                if (config->param[paramIndex].bSet) {
7632                    config->param[paramIndex].nInt64 = value;
7633                }
7634                break;
7635            }
7636            case OMX_AndroidVendorValueString:
7637            {
7638                AString value;
7639                config->param[paramIndex].bSet =
7640                    (OMX_BOOL)params->findString(existingKey->second.c_str(), &value);
7641                if (config->param[paramIndex].bSet) {
7642                    size_t dstSize = sizeof(config->param[paramIndex].cString);
7643                    strncpy((char *)config->param[paramIndex].cString, value.c_str(), dstSize - 1);
7644                    // null terminate value
7645                    config->param[paramIndex].cString[dstSize - 1] = '\0';
7646                }
7647                break;
7648            }
7649            default:
7650                ALOGW("[%s] vendor parameter '%s' is not a supported value",
7651                        mComponentName.c_str(), key);
7652                continue;
7653            }
7654            if (config->param[paramIndex].bSet || wasSet) {
7655                needToSet = true;
7656            }
7657        }
7658
7659        if (needToSet) {
7660            status_t err = mOMXNode->setConfig(
7661                    (OMX_INDEXTYPE)OMX_IndexConfigAndroidVendorExtension,
7662                    config, config->nSize);
7663            if (err != OK) {
7664                key[nameLength] = '\0';
7665                ALOGW("[%s] failed to set vendor extension '%s'", mComponentName.c_str(), key);
7666                // try to set each extension, and return first failure
7667                if (finalError == OK) {
7668                    finalError = err;
7669                }
7670            }
7671        }
7672    }
7673
7674    if (mVendorExtensionsStatus == kExtensionsUnchecked) {
7675        mVendorExtensionsStatus = kExtensionsNone;
7676    }
7677
7678    return finalError;
7679}
7680
7681status_t ACodec::getVendorParameters(OMX_U32 portIndex, sp<AMessage> &format) {
7682    constexpr char prefix[] = "vendor.";
7683    constexpr size_t prefixLength = sizeof(prefix) - 1;
7684    char key[sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE::cName) +
7685            sizeof(OMX_CONFIG_ANDROID_VENDOR_PARAMTYPE::cKey) + prefixLength];
7686    strcpy(key, prefix);
7687
7688    // don't try again if component does not have vendor extensions
7689    if (mVendorExtensionsStatus == kExtensionsNone) {
7690        return OK;
7691    }
7692
7693    for (VendorExtension ext : VendorExtensions(mOMXNode)) {
7694        OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *config = ext.config;
7695        if (config == nullptr) {
7696            return ext.status;
7697        }
7698
7699        mVendorExtensionsStatus = kExtensionsExist;
7700
7701        if (config->eDir != (portIndex == kPortIndexInput ? OMX_DirInput : OMX_DirOutput)) {
7702            continue;
7703        }
7704
7705        config->cName[sizeof(config->cName) - 1] = '\0'; // null-terminate name
7706        strcpy(key + prefixLength, (const char *)config->cName);
7707        size_t nameLength = strlen(key);
7708        key[nameLength] = '.';
7709
7710        for (size_t paramIndex = 0; paramIndex < config->nParamCount; ++paramIndex) {
7711            // null-terminate param key
7712            config->param[paramIndex].cKey[sizeof(config->param[0].cKey) - 1] = '\0';
7713            strcpy(key + nameLength + 1, (const char *)config->param[paramIndex].cKey);
7714            removeTrailingTags(key, nameLength, "value");
7715            if (config->param[paramIndex].bSet) {
7716                switch (config->param[paramIndex].eValueType) {
7717                case OMX_AndroidVendorValueInt32:
7718                {
7719                    format->setInt32(key, config->param[paramIndex].nInt32);
7720                    break;
7721                }
7722                case OMX_AndroidVendorValueInt64:
7723                {
7724                    format->setInt64(key, config->param[paramIndex].nInt64);
7725                    break;
7726                }
7727                case OMX_AndroidVendorValueString:
7728                {
7729                    config->param[paramIndex].cString[OMX_MAX_STRINGVALUE_SIZE - 1] = '\0';
7730                    format->setString(key, (const char *)config->param[paramIndex].cString);
7731                    break;
7732                }
7733                default:
7734                    ALOGW("vendor parameter %s is not a supported value", key);
7735                    continue;
7736                }
7737            }
7738        }
7739    }
7740
7741    if (mVendorExtensionsStatus == kExtensionsUnchecked) {
7742        mVendorExtensionsStatus = kExtensionsNone;
7743    }
7744
7745    return OK;
7746}
7747
7748void ACodec::onSignalEndOfInputStream() {
7749    status_t err = INVALID_OPERATION;
7750    if (mGraphicBufferSource != NULL) {
7751        err = statusFromBinderStatus(mGraphicBufferSource->signalEndOfInputStream());
7752    }
7753    mCallback->onSignaledInputEOS(err);
7754}
7755
7756void ACodec::forceStateTransition(int generation) {
7757    if (generation != mStateGeneration) {
7758        ALOGV("Ignoring stale force state transition message: #%d (now #%d)",
7759                generation, mStateGeneration);
7760        return;
7761    }
7762    ALOGE("State machine stuck");
7763    // Error must have already been signalled to the client.
7764
7765    // Deferred messages will be handled at LoadedState at the end of the
7766    // transition.
7767    mShutdownInProgress = true;
7768    // No shutdown complete callback at the end of the transition.
7769    mExplicitShutdown = false;
7770    mKeepComponentAllocated = true;
7771
7772    status_t err = mOMXNode->sendCommand(OMX_CommandStateSet, OMX_StateIdle);
7773    if (err != OK) {
7774        // TODO: do some recovery here.
7775    } else {
7776        changeState(mExecutingToIdleState);
7777    }
7778}
7779
7780bool ACodec::ExecutingState::onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano) {
7781    mCodec->onFrameRendered(mediaTimeUs, systemNano);
7782    return true;
7783}
7784
7785bool ACodec::ExecutingState::onOMXEvent(
7786        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
7787    switch (event) {
7788        case OMX_EventPortSettingsChanged:
7789        {
7790            CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
7791
7792            mCodec->onOutputFormatChanged();
7793
7794            if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
7795                mCodec->mMetadataBuffersToSubmit = 0;
7796                CHECK_EQ(mCodec->mOMXNode->sendCommand(
7797                            OMX_CommandPortDisable, kPortIndexOutput),
7798                         (status_t)OK);
7799
7800                mCodec->freeOutputBuffersNotOwnedByComponent();
7801
7802                mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
7803            } else if (data2 != OMX_IndexConfigCommonOutputCrop
7804                    && data2 != OMX_IndexConfigAndroidIntraRefresh) {
7805                ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08x",
7806                     mCodec->mComponentName.c_str(), data2);
7807            }
7808
7809            return true;
7810        }
7811
7812        case OMX_EventBufferFlag:
7813        {
7814            return true;
7815        }
7816
7817        default:
7818            return BaseState::onOMXEvent(event, data1, data2);
7819    }
7820}
7821
7822////////////////////////////////////////////////////////////////////////////////
7823
7824ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState(
7825        ACodec *codec)
7826    : BaseState(codec) {
7827}
7828
7829ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode(
7830        OMX_U32 portIndex) {
7831    if (portIndex == kPortIndexOutput) {
7832        return FREE_BUFFERS;
7833    }
7834
7835    CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput);
7836
7837    return RESUBMIT_BUFFERS;
7838}
7839
7840bool ACodec::OutputPortSettingsChangedState::onMessageReceived(
7841        const sp<AMessage> &msg) {
7842    bool handled = false;
7843
7844    switch (msg->what()) {
7845        case kWhatFlush:
7846        case kWhatShutdown: {
7847            if (mCodec->mFatalError) {
7848                sp<AMessage> msg = new AMessage(ACodec::kWhatForceStateTransition, mCodec);
7849                msg->setInt32("generation", mCodec->mStateGeneration);
7850                msg->post(3000000);
7851            }
7852            // fall-through
7853        }
7854        case kWhatResume:
7855        case kWhatSetParameters:
7856        {
7857            if (msg->what() == kWhatResume) {
7858                ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
7859            }
7860
7861            mCodec->deferMessage(msg);
7862            handled = true;
7863            break;
7864        }
7865
7866        case kWhatForceStateTransition:
7867        {
7868            int32_t generation = 0;
7869            CHECK(msg->findInt32("generation", &generation));
7870            mCodec->forceStateTransition(generation);
7871
7872            handled = true;
7873            break;
7874        }
7875
7876        default:
7877            handled = BaseState::onMessageReceived(msg);
7878            break;
7879    }
7880
7881    return handled;
7882}
7883
7884void ACodec::OutputPortSettingsChangedState::stateEntered() {
7885    ALOGV("[%s] Now handling output port settings change",
7886         mCodec->mComponentName.c_str());
7887}
7888
7889bool ACodec::OutputPortSettingsChangedState::onOMXFrameRendered(
7890        int64_t mediaTimeUs, nsecs_t systemNano) {
7891    mCodec->onFrameRendered(mediaTimeUs, systemNano);
7892    return true;
7893}
7894
7895bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
7896        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
7897    switch (event) {
7898        case OMX_EventCmdComplete:
7899        {
7900            if (data1 == (OMX_U32)OMX_CommandPortDisable) {
7901                if (data2 != (OMX_U32)kPortIndexOutput) {
7902                    ALOGW("ignoring EventCmdComplete CommandPortDisable for port %u", data2);
7903                    return false;
7904                }
7905
7906                ALOGV("[%s] Output port now disabled.", mCodec->mComponentName.c_str());
7907
7908                status_t err = OK;
7909                if (!mCodec->mBuffers[kPortIndexOutput].isEmpty()) {
7910                    ALOGE("disabled port should be empty, but has %zu buffers",
7911                            mCodec->mBuffers[kPortIndexOutput].size());
7912                    err = FAILED_TRANSACTION;
7913                } else {
7914                    mCodec->mAllocator[kPortIndexOutput].clear();
7915                }
7916
7917                if (err == OK) {
7918                    err = mCodec->mOMXNode->sendCommand(
7919                            OMX_CommandPortEnable, kPortIndexOutput);
7920                }
7921
7922                if (err == OK) {
7923                    err = mCodec->allocateBuffersOnPort(kPortIndexOutput);
7924                    ALOGE_IF(err != OK, "Failed to allocate output port buffers after port "
7925                            "reconfiguration: (%d)", err);
7926                    mCodec->mCallback->onOutputBuffersChanged();
7927                }
7928
7929                if (err != OK) {
7930                    mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
7931                    ALOGE("Error occurred while disabling the output port");
7932                }
7933
7934                return true;
7935            } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
7936                if (data2 != (OMX_U32)kPortIndexOutput) {
7937                    ALOGW("ignoring EventCmdComplete OMX_CommandPortEnable for port %u", data2);
7938                    return false;
7939                }
7940
7941                ALOGV("[%s] Output port now reenabled.", mCodec->mComponentName.c_str());
7942
7943                if (mCodec->mExecutingState->active()) {
7944                    mCodec->mExecutingState->submitOutputBuffers();
7945                }
7946
7947                mCodec->changeState(mCodec->mExecutingState);
7948
7949                return true;
7950            }
7951
7952            return false;
7953        }
7954
7955        default:
7956            return BaseState::onOMXEvent(event, data1, data2);
7957    }
7958}
7959
7960////////////////////////////////////////////////////////////////////////////////
7961
7962ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec)
7963    : BaseState(codec),
7964      mComponentNowIdle(false) {
7965}
7966
7967bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) {
7968    bool handled = false;
7969
7970    switch (msg->what()) {
7971        case kWhatFlush:
7972        {
7973            // Don't send me a flush request if you previously wanted me
7974            // to shutdown.
7975            ALOGW("Ignoring flush request in ExecutingToIdleState");
7976            break;
7977        }
7978
7979        case kWhatShutdown:
7980        {
7981            mCodec->deferMessage(msg);
7982            handled = true;
7983            break;
7984        }
7985
7986        default:
7987            handled = BaseState::onMessageReceived(msg);
7988            break;
7989    }
7990
7991    return handled;
7992}
7993
7994void ACodec::ExecutingToIdleState::stateEntered() {
7995    ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
7996
7997    mComponentNowIdle = false;
7998    mCodec->mLastOutputFormat.clear();
7999}
8000
8001bool ACodec::ExecutingToIdleState::onOMXEvent(
8002        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
8003    switch (event) {
8004        case OMX_EventCmdComplete:
8005        {
8006            if (data1 != (OMX_U32)OMX_CommandStateSet
8007                    || data2 != (OMX_U32)OMX_StateIdle) {
8008                ALOGE("Unexpected command completion in ExecutingToIdleState: %s(%u) %s(%u)",
8009                        asString((OMX_COMMANDTYPE)data1), data1,
8010                        asString((OMX_STATETYPE)data2), data2);
8011                mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
8012                return true;
8013            }
8014
8015            mComponentNowIdle = true;
8016
8017            changeStateIfWeOwnAllBuffers();
8018
8019            return true;
8020        }
8021
8022        case OMX_EventPortSettingsChanged:
8023        case OMX_EventBufferFlag:
8024        {
8025            // We're shutting down and don't care about this anymore.
8026            return true;
8027        }
8028
8029        default:
8030            return BaseState::onOMXEvent(event, data1, data2);
8031    }
8032}
8033
8034void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
8035    if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) {
8036        status_t err = mCodec->mOMXNode->sendCommand(
8037                OMX_CommandStateSet, OMX_StateLoaded);
8038        if (err == OK) {
8039            err = mCodec->freeBuffersOnPort(kPortIndexInput);
8040            status_t err2 = mCodec->freeBuffersOnPort(kPortIndexOutput);
8041            if (err == OK) {
8042                err = err2;
8043            }
8044        }
8045
8046        if ((mCodec->mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown)
8047                && mCodec->mNativeWindow != NULL) {
8048            // We push enough 1x1 blank buffers to ensure that one of
8049            // them has made it to the display.  This allows the OMX
8050            // component teardown to zero out any protected buffers
8051            // without the risk of scanning out one of those buffers.
8052            pushBlankBuffersToNativeWindow(mCodec->mNativeWindow.get());
8053        }
8054
8055        if (err != OK) {
8056            mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
8057            return;
8058        }
8059
8060        mCodec->changeState(mCodec->mIdleToLoadedState);
8061    }
8062}
8063
8064void ACodec::ExecutingToIdleState::onInputBufferFilled(
8065        const sp<AMessage> &msg) {
8066    BaseState::onInputBufferFilled(msg);
8067
8068    changeStateIfWeOwnAllBuffers();
8069}
8070
8071void ACodec::ExecutingToIdleState::onOutputBufferDrained(
8072        const sp<AMessage> &msg) {
8073    BaseState::onOutputBufferDrained(msg);
8074
8075    changeStateIfWeOwnAllBuffers();
8076}
8077
8078////////////////////////////////////////////////////////////////////////////////
8079
8080ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec)
8081    : BaseState(codec) {
8082}
8083
8084bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) {
8085    bool handled = false;
8086
8087    switch (msg->what()) {
8088        case kWhatShutdown:
8089        {
8090            mCodec->deferMessage(msg);
8091            handled = true;
8092            break;
8093        }
8094
8095        case kWhatFlush:
8096        {
8097            // Don't send me a flush request if you previously wanted me
8098            // to shutdown.
8099            ALOGE("Got flush request in IdleToLoadedState");
8100            break;
8101        }
8102
8103        default:
8104            handled = BaseState::onMessageReceived(msg);
8105            break;
8106    }
8107
8108    return handled;
8109}
8110
8111void ACodec::IdleToLoadedState::stateEntered() {
8112    ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
8113}
8114
8115bool ACodec::IdleToLoadedState::onOMXEvent(
8116        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
8117    switch (event) {
8118        case OMX_EventCmdComplete:
8119        {
8120            if (data1 != (OMX_U32)OMX_CommandStateSet
8121                    || data2 != (OMX_U32)OMX_StateLoaded) {
8122                ALOGE("Unexpected command completion in IdleToLoadedState: %s(%u) %s(%u)",
8123                        asString((OMX_COMMANDTYPE)data1), data1,
8124                        asString((OMX_STATETYPE)data2), data2);
8125                mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
8126                return true;
8127            }
8128
8129            mCodec->changeState(mCodec->mLoadedState);
8130
8131            return true;
8132        }
8133
8134        default:
8135            return BaseState::onOMXEvent(event, data1, data2);
8136    }
8137}
8138
8139////////////////////////////////////////////////////////////////////////////////
8140
8141ACodec::FlushingState::FlushingState(ACodec *codec)
8142    : BaseState(codec) {
8143}
8144
8145void ACodec::FlushingState::stateEntered() {
8146    ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());
8147
8148    mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
8149}
8150
8151bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) {
8152    bool handled = false;
8153
8154    switch (msg->what()) {
8155        case kWhatShutdown:
8156        {
8157            mCodec->deferMessage(msg);
8158            if (mCodec->mFatalError) {
8159                sp<AMessage> msg = new AMessage(ACodec::kWhatForceStateTransition, mCodec);
8160                msg->setInt32("generation", mCodec->mStateGeneration);
8161                msg->post(3000000);
8162            }
8163            break;
8164        }
8165
8166        case kWhatFlush:
8167        {
8168            // We're already doing this right now.
8169            handled = true;
8170            break;
8171        }
8172
8173        case kWhatForceStateTransition:
8174        {
8175            int32_t generation = 0;
8176            CHECK(msg->findInt32("generation", &generation));
8177            mCodec->forceStateTransition(generation);
8178
8179            handled = true;
8180            break;
8181        }
8182
8183        default:
8184            handled = BaseState::onMessageReceived(msg);
8185            break;
8186    }
8187
8188    return handled;
8189}
8190
8191bool ACodec::FlushingState::onOMXEvent(
8192        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
8193    ALOGV("[%s] FlushingState onOMXEvent(%u,%d)",
8194            mCodec->mComponentName.c_str(), event, (OMX_S32)data1);
8195
8196    switch (event) {
8197        case OMX_EventCmdComplete:
8198        {
8199            if (data1 != (OMX_U32)OMX_CommandFlush) {
8200                ALOGE("unexpected EventCmdComplete %s(%d) data2:%d in FlushingState",
8201                        asString((OMX_COMMANDTYPE)data1), data1, data2);
8202                mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
8203                return true;
8204            }
8205
8206            if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
8207                if (mFlushComplete[data2]) {
8208                    ALOGW("Flush already completed for %s port",
8209                            data2 == kPortIndexInput ? "input" : "output");
8210                    return true;
8211                }
8212                mFlushComplete[data2] = true;
8213
8214                if (mFlushComplete[kPortIndexInput] && mFlushComplete[kPortIndexOutput]) {
8215                    changeStateIfWeOwnAllBuffers();
8216                }
8217            } else if (data2 == OMX_ALL) {
8218                if (!mFlushComplete[kPortIndexInput] || !mFlushComplete[kPortIndexOutput]) {
8219                    ALOGW("received flush complete event for OMX_ALL before ports have been"
8220                            "flushed (%d/%d)",
8221                            mFlushComplete[kPortIndexInput], mFlushComplete[kPortIndexOutput]);
8222                    return false;
8223                }
8224
8225                changeStateIfWeOwnAllBuffers();
8226            } else {
8227                ALOGW("data2 not OMX_ALL but %u in EventCmdComplete CommandFlush", data2);
8228            }
8229
8230            return true;
8231        }
8232
8233        case OMX_EventPortSettingsChanged:
8234        {
8235            sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec);
8236            msg->setInt32("type", omx_message::EVENT);
8237            msg->setInt32("generation", mCodec->mNodeGeneration);
8238            msg->setInt32("event", event);
8239            msg->setInt32("data1", data1);
8240            msg->setInt32("data2", data2);
8241
8242            ALOGV("[%s] Deferring OMX_EventPortSettingsChanged",
8243                 mCodec->mComponentName.c_str());
8244
8245            mCodec->deferMessage(msg);
8246
8247            return true;
8248        }
8249
8250        default:
8251            return BaseState::onOMXEvent(event, data1, data2);
8252    }
8253
8254    return true;
8255}
8256
8257void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) {
8258    BaseState::onOutputBufferDrained(msg);
8259
8260    changeStateIfWeOwnAllBuffers();
8261}
8262
8263void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) {
8264    BaseState::onInputBufferFilled(msg);
8265
8266    changeStateIfWeOwnAllBuffers();
8267}
8268
8269void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() {
8270    if (mFlushComplete[kPortIndexInput]
8271            && mFlushComplete[kPortIndexOutput]
8272            && mCodec->allYourBuffersAreBelongToUs()) {
8273        // We now own all buffers except possibly those still queued with
8274        // the native window for rendering. Let's get those back as well.
8275        mCodec->waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs();
8276
8277        mCodec->mRenderTracker.clear(systemTime(CLOCK_MONOTONIC));
8278
8279        mCodec->mCallback->onFlushCompleted();
8280
8281        mCodec->mPortEOS[kPortIndexInput] =
8282            mCodec->mPortEOS[kPortIndexOutput] = false;
8283
8284        mCodec->mInputEOSResult = OK;
8285
8286        if (mCodec->mSkipCutBuffer != NULL) {
8287            mCodec->mSkipCutBuffer->clear();
8288        }
8289
8290        mCodec->changeState(mCodec->mExecutingState);
8291    }
8292}
8293
8294status_t ACodec::queryCapabilities(
8295        const char* owner, const char* name, const char* mime, bool isEncoder,
8296        MediaCodecInfo::CapabilitiesWriter* caps) {
8297    const char *role = GetComponentRole(isEncoder, mime);
8298    if (role == NULL) {
8299        return BAD_VALUE;
8300    }
8301
8302    OMXClient client;
8303    status_t err = client.connect(owner);
8304    if (err != OK) {
8305        return err;
8306    }
8307
8308    sp<IOMX> omx = client.interface();
8309    sp<CodecObserver> observer = new CodecObserver;
8310    sp<IOMXNode> omxNode;
8311
8312    err = omx->allocateNode(name, observer, &omxNode);
8313    if (err != OK) {
8314        client.disconnect();
8315        return err;
8316    }
8317
8318    err = SetComponentRole(omxNode, role);
8319    if (err != OK) {
8320        omxNode->freeNode();
8321        client.disconnect();
8322        return err;
8323    }
8324
8325    bool isVideo = strncasecmp(mime, "video/", 6) == 0;
8326    bool isImage = strncasecmp(mime, "image/", 6) == 0;
8327
8328    if (isVideo || isImage) {
8329        OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
8330        InitOMXParams(&param);
8331        param.nPortIndex = isEncoder ? kPortIndexOutput : kPortIndexInput;
8332
8333        for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
8334            param.nProfileIndex = index;
8335            status_t err = omxNode->getParameter(
8336                    OMX_IndexParamVideoProfileLevelQuerySupported,
8337                    &param, sizeof(param));
8338            if (err != OK) {
8339                break;
8340            }
8341            caps->addProfileLevel(param.eProfile, param.eLevel);
8342
8343            // AVC components may not list the constrained profiles explicitly, but
8344            // decoders that support a profile also support its constrained version.
8345            // Encoders must explicitly support constrained profiles.
8346            if (!isEncoder && strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC) == 0) {
8347                if (param.eProfile == OMX_VIDEO_AVCProfileHigh) {
8348                    caps->addProfileLevel(OMX_VIDEO_AVCProfileConstrainedHigh, param.eLevel);
8349                } else if (param.eProfile == OMX_VIDEO_AVCProfileBaseline) {
8350                    caps->addProfileLevel(OMX_VIDEO_AVCProfileConstrainedBaseline, param.eLevel);
8351                }
8352            }
8353
8354            if (index == kMaxIndicesToCheck) {
8355                ALOGW("[%s] stopping checking profiles after %u: %x/%x",
8356                        name, index,
8357                        param.eProfile, param.eLevel);
8358            }
8359        }
8360
8361        // Color format query
8362        // return colors in the order reported by the OMX component
8363        // prefix "flexible" standard ones with the flexible equivalent
8364        OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat;
8365        InitOMXParams(&portFormat);
8366        portFormat.nPortIndex = isEncoder ? kPortIndexInput : kPortIndexOutput;
8367        for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
8368            portFormat.nIndex = index;
8369            status_t err = omxNode->getParameter(
8370                    OMX_IndexParamVideoPortFormat,
8371                    &portFormat, sizeof(portFormat));
8372            if (err != OK) {
8373                break;
8374            }
8375
8376            OMX_U32 flexibleEquivalent;
8377            if (IsFlexibleColorFormat(
8378                    omxNode, portFormat.eColorFormat, false /* usingNativeWindow */,
8379                    &flexibleEquivalent)) {
8380                caps->addColorFormat(flexibleEquivalent);
8381            }
8382            caps->addColorFormat(portFormat.eColorFormat);
8383
8384            if (index == kMaxIndicesToCheck) {
8385                ALOGW("[%s] stopping checking formats after %u: %s(%x)",
8386                        name, index,
8387                        asString(portFormat.eColorFormat), portFormat.eColorFormat);
8388            }
8389        }
8390    } else if (strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC) == 0) {
8391        // More audio codecs if they have profiles.
8392        OMX_AUDIO_PARAM_ANDROID_PROFILETYPE param;
8393        InitOMXParams(&param);
8394        param.nPortIndex = isEncoder ? kPortIndexOutput : kPortIndexInput;
8395        for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
8396            param.nProfileIndex = index;
8397            status_t err = omxNode->getParameter(
8398                    (OMX_INDEXTYPE)OMX_IndexParamAudioProfileQuerySupported,
8399                    &param, sizeof(param));
8400            if (err != OK) {
8401                break;
8402            }
8403            // For audio, level is ignored.
8404            caps->addProfileLevel(param.eProfile, 0 /* level */);
8405
8406            if (index == kMaxIndicesToCheck) {
8407                ALOGW("[%s] stopping checking profiles after %u: %x",
8408                        name, index,
8409                        param.eProfile);
8410            }
8411        }
8412
8413        // NOTE: Without Android extensions, OMX does not provide a way to query
8414        // AAC profile support
8415        if (param.nProfileIndex == 0) {
8416            ALOGW("component %s doesn't support profile query.", name);
8417        }
8418    }
8419
8420    if (isVideo && !isEncoder) {
8421        native_handle_t *sidebandHandle = NULL;
8422        if (omxNode->configureVideoTunnelMode(
8423                kPortIndexOutput, OMX_TRUE, 0, &sidebandHandle) == OK) {
8424            // tunneled playback includes adaptive playback
8425            caps->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback
8426                    | MediaCodecInfo::Capabilities::kFlagSupportsTunneledPlayback);
8427        } else if (omxNode->setPortMode(
8428                kPortIndexOutput, IOMX::kPortModeDynamicANWBuffer) == OK ||
8429                omxNode->prepareForAdaptivePlayback(
8430                kPortIndexOutput, OMX_TRUE,
8431                1280 /* width */, 720 /* height */) == OK) {
8432            caps->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback);
8433        }
8434    }
8435
8436    if (isVideo && isEncoder) {
8437        OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE params;
8438        InitOMXParams(&params);
8439        params.nPortIndex = kPortIndexOutput;
8440        // TODO: should we verify if fallback is supported?
8441        if (omxNode->getConfig(
8442                (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh,
8443                &params, sizeof(params)) == OK) {
8444            caps->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsIntraRefresh);
8445        }
8446    }
8447
8448    omxNode->freeNode();
8449    client.disconnect();
8450    return OK;
8451}
8452
8453// These are supposed be equivalent to the logic in
8454// "audio_channel_out_mask_from_count".
8455//static
8456status_t ACodec::getOMXChannelMapping(size_t numChannels, OMX_AUDIO_CHANNELTYPE map[]) {
8457    switch (numChannels) {
8458        case 1:
8459            map[0] = OMX_AUDIO_ChannelCF;
8460            break;
8461        case 2:
8462            map[0] = OMX_AUDIO_ChannelLF;
8463            map[1] = OMX_AUDIO_ChannelRF;
8464            break;
8465        case 3:
8466            map[0] = OMX_AUDIO_ChannelLF;
8467            map[1] = OMX_AUDIO_ChannelRF;
8468            map[2] = OMX_AUDIO_ChannelCF;
8469            break;
8470        case 4:
8471            map[0] = OMX_AUDIO_ChannelLF;
8472            map[1] = OMX_AUDIO_ChannelRF;
8473            map[2] = OMX_AUDIO_ChannelLR;
8474            map[3] = OMX_AUDIO_ChannelRR;
8475            break;
8476        case 5:
8477            map[0] = OMX_AUDIO_ChannelLF;
8478            map[1] = OMX_AUDIO_ChannelRF;
8479            map[2] = OMX_AUDIO_ChannelCF;
8480            map[3] = OMX_AUDIO_ChannelLR;
8481            map[4] = OMX_AUDIO_ChannelRR;
8482            break;
8483        case 6:
8484            map[0] = OMX_AUDIO_ChannelLF;
8485            map[1] = OMX_AUDIO_ChannelRF;
8486            map[2] = OMX_AUDIO_ChannelCF;
8487            map[3] = OMX_AUDIO_ChannelLFE;
8488            map[4] = OMX_AUDIO_ChannelLR;
8489            map[5] = OMX_AUDIO_ChannelRR;
8490            break;
8491        case 7:
8492            map[0] = OMX_AUDIO_ChannelLF;
8493            map[1] = OMX_AUDIO_ChannelRF;
8494            map[2] = OMX_AUDIO_ChannelCF;
8495            map[3] = OMX_AUDIO_ChannelLFE;
8496            map[4] = OMX_AUDIO_ChannelLR;
8497            map[5] = OMX_AUDIO_ChannelRR;
8498            map[6] = OMX_AUDIO_ChannelCS;
8499            break;
8500        case 8:
8501            map[0] = OMX_AUDIO_ChannelLF;
8502            map[1] = OMX_AUDIO_ChannelRF;
8503            map[2] = OMX_AUDIO_ChannelCF;
8504            map[3] = OMX_AUDIO_ChannelLFE;
8505            map[4] = OMX_AUDIO_ChannelLR;
8506            map[5] = OMX_AUDIO_ChannelRR;
8507            map[6] = OMX_AUDIO_ChannelLS;
8508            map[7] = OMX_AUDIO_ChannelRS;
8509            break;
8510        default:
8511            return -EINVAL;
8512    }
8513
8514    return OK;
8515}
8516
8517}  // namespace android
8518