ACodec.cpp revision deb14ec33bc481809b465959882736e2262b667a
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(-1ll),
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 = -1ll;
1827        } else if (mMaxPtsGapUs > INT32_MAX || mMaxPtsGapUs < 0) {
1828            ALOGW("Unsupported value for max pts gap %lld", (long long) mMaxPtsGapUs);
1829            mMaxPtsGapUs = -1ll;
1830        }
1831
1832        if (!msg->findFloat("max-fps-to-encoder", &mMaxFps)) {
1833            mMaxFps = -1;
1834        }
1835
1836        if (!msg->findDouble("time-lapse-fps", &mCaptureFps)) {
1837            mCaptureFps = -1.0;
1838        }
1839
1840        if (!msg->findInt32(
1841                    "create-input-buffers-suspended",
1842                    (int32_t*)&mCreateInputBuffersSuspended)) {
1843            mCreateInputBuffersSuspended = false;
1844        }
1845    }
1846
1847    // NOTE: we only use native window for video decoders
1848    sp<RefBase> obj;
1849    bool haveNativeWindow = msg->findObject("native-window", &obj)
1850            && obj != NULL && mIsVideo && !encoder;
1851    mUsingNativeWindow = haveNativeWindow;
1852    if (mIsVideo && !encoder) {
1853        inputFormat->setInt32("adaptive-playback", false);
1854
1855        int32_t usageProtected;
1856        if (msg->findInt32("protected", &usageProtected) && usageProtected) {
1857            if (!haveNativeWindow) {
1858                ALOGE("protected output buffers must be sent to an ANativeWindow");
1859                return PERMISSION_DENIED;
1860            }
1861            mFlags |= kFlagIsGrallocUsageProtected;
1862            mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
1863        }
1864    }
1865    if (mFlags & kFlagIsSecure) {
1866        // use native_handles for secure input buffers
1867        err = setPortMode(kPortIndexInput, IOMX::kPortModePresetSecureBuffer);
1868
1869        if (err != OK) {
1870            ALOGI("falling back to non-native_handles");
1871            setPortMode(kPortIndexInput, IOMX::kPortModePresetByteBuffer);
1872            err = OK; // ignore error for now
1873        }
1874    }
1875    if (haveNativeWindow) {
1876        sp<ANativeWindow> nativeWindow =
1877            static_cast<ANativeWindow *>(static_cast<Surface *>(obj.get()));
1878
1879        // START of temporary support for automatic FRC - THIS WILL BE REMOVED
1880        int32_t autoFrc;
1881        if (msg->findInt32("auto-frc", &autoFrc)) {
1882            bool enabled = autoFrc;
1883            OMX_CONFIG_BOOLEANTYPE config;
1884            InitOMXParams(&config);
1885            config.bEnabled = (OMX_BOOL)enabled;
1886            status_t temp = mOMXNode->setConfig(
1887                    (OMX_INDEXTYPE)OMX_IndexConfigAutoFramerateConversion,
1888                    &config, sizeof(config));
1889            if (temp == OK) {
1890                outputFormat->setInt32("auto-frc", enabled);
1891            } else if (enabled) {
1892                ALOGI("codec does not support requested auto-frc (err %d)", temp);
1893            }
1894        }
1895        // END of temporary support for automatic FRC
1896
1897        int32_t tunneled;
1898        if (msg->findInt32("feature-tunneled-playback", &tunneled) &&
1899            tunneled != 0) {
1900            ALOGI("Configuring TUNNELED video playback.");
1901            mTunneled = true;
1902
1903            int32_t audioHwSync = 0;
1904            if (!msg->findInt32("audio-hw-sync", &audioHwSync)) {
1905                ALOGW("No Audio HW Sync provided for video tunnel");
1906            }
1907            err = configureTunneledVideoPlayback(audioHwSync, nativeWindow);
1908            if (err != OK) {
1909                ALOGE("configureTunneledVideoPlayback(%d,%p) failed!",
1910                        audioHwSync, nativeWindow.get());
1911                return err;
1912            }
1913
1914            int32_t maxWidth = 0, maxHeight = 0;
1915            if (msg->findInt32("max-width", &maxWidth) &&
1916                    msg->findInt32("max-height", &maxHeight)) {
1917
1918                err = mOMXNode->prepareForAdaptivePlayback(
1919                        kPortIndexOutput, OMX_TRUE, maxWidth, maxHeight);
1920                if (err != OK) {
1921                    ALOGW("[%s] prepareForAdaptivePlayback failed w/ err %d",
1922                            mComponentName.c_str(), err);
1923                    // allow failure
1924                    err = OK;
1925                } else {
1926                    inputFormat->setInt32("max-width", maxWidth);
1927                    inputFormat->setInt32("max-height", maxHeight);
1928                    inputFormat->setInt32("adaptive-playback", true);
1929                }
1930            }
1931        } else {
1932            ALOGV("Configuring CPU controlled video playback.");
1933            mTunneled = false;
1934
1935            // Explicity reset the sideband handle of the window for
1936            // non-tunneled video in case the window was previously used
1937            // for a tunneled video playback.
1938            err = native_window_set_sideband_stream(nativeWindow.get(), NULL);
1939            if (err != OK) {
1940                ALOGE("set_sideband_stream(NULL) failed! (err %d).", err);
1941                return err;
1942            }
1943
1944            err = setPortMode(kPortIndexOutput, IOMX::kPortModeDynamicANWBuffer);
1945            if (err != OK) {
1946                // if adaptive playback has been requested, try JB fallback
1947                // NOTE: THIS FALLBACK MECHANISM WILL BE REMOVED DUE TO ITS
1948                // LARGE MEMORY REQUIREMENT
1949
1950                // we will not do adaptive playback on software accessed
1951                // surfaces as they never had to respond to changes in the
1952                // crop window, and we don't trust that they will be able to.
1953                int usageBits = 0;
1954                bool canDoAdaptivePlayback;
1955
1956                if (nativeWindow->query(
1957                        nativeWindow.get(),
1958                        NATIVE_WINDOW_CONSUMER_USAGE_BITS,
1959                        &usageBits) != OK) {
1960                    canDoAdaptivePlayback = false;
1961                } else {
1962                    canDoAdaptivePlayback =
1963                        (usageBits &
1964                                (GRALLOC_USAGE_SW_READ_MASK |
1965                                 GRALLOC_USAGE_SW_WRITE_MASK)) == 0;
1966                }
1967
1968                int32_t maxWidth = 0, maxHeight = 0;
1969                if (canDoAdaptivePlayback &&
1970                        msg->findInt32("max-width", &maxWidth) &&
1971                        msg->findInt32("max-height", &maxHeight)) {
1972                    ALOGV("[%s] prepareForAdaptivePlayback(%dx%d)",
1973                            mComponentName.c_str(), maxWidth, maxHeight);
1974
1975                    err = mOMXNode->prepareForAdaptivePlayback(
1976                            kPortIndexOutput, OMX_TRUE, maxWidth, maxHeight);
1977                    ALOGW_IF(err != OK,
1978                            "[%s] prepareForAdaptivePlayback failed w/ err %d",
1979                            mComponentName.c_str(), err);
1980
1981                    if (err == OK) {
1982                        inputFormat->setInt32("max-width", maxWidth);
1983                        inputFormat->setInt32("max-height", maxHeight);
1984                        inputFormat->setInt32("adaptive-playback", true);
1985                    }
1986                }
1987                // allow failure
1988                err = OK;
1989            } else {
1990                ALOGV("[%s] setPortMode on output to %s succeeded",
1991                        mComponentName.c_str(), asString(IOMX::kPortModeDynamicANWBuffer));
1992                CHECK(storingMetadataInDecodedBuffers());
1993                inputFormat->setInt32("adaptive-playback", true);
1994            }
1995
1996            int32_t push;
1997            if (msg->findInt32("push-blank-buffers-on-shutdown", &push)
1998                    && push != 0) {
1999                mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
2000            }
2001        }
2002
2003        int32_t rotationDegrees;
2004        if (msg->findInt32("rotation-degrees", &rotationDegrees)) {
2005            mRotationDegrees = rotationDegrees;
2006        } else {
2007            mRotationDegrees = 0;
2008        }
2009    }
2010
2011    AudioEncoding pcmEncoding = kAudioEncodingPcm16bit;
2012    (void)msg->findInt32("pcm-encoding", (int32_t*)&pcmEncoding);
2013    // invalid encodings will default to PCM-16bit in setupRawAudioFormat.
2014
2015    if (mIsVideo || mIsImage) {
2016        // determine need for software renderer
2017        bool usingSwRenderer = false;
2018        if (haveNativeWindow && mComponentName.startsWith("OMX.google.")) {
2019            usingSwRenderer = true;
2020            haveNativeWindow = false;
2021            (void)setPortMode(kPortIndexOutput, IOMX::kPortModePresetByteBuffer);
2022        } else if (haveNativeWindow && !storingMetadataInDecodedBuffers()) {
2023            err = setPortMode(kPortIndexOutput, IOMX::kPortModePresetANWBuffer);
2024            if (err != OK) {
2025                return err;
2026            }
2027        }
2028
2029        if (encoder) {
2030            err = setupVideoEncoder(mime, msg, outputFormat, inputFormat);
2031        } else {
2032            err = setupVideoDecoder(mime, msg, haveNativeWindow, usingSwRenderer, outputFormat);
2033        }
2034
2035        if (err != OK) {
2036            return err;
2037        }
2038
2039        if (haveNativeWindow) {
2040            mNativeWindow = static_cast<Surface *>(obj.get());
2041
2042            // fallback for devices that do not handle flex-YUV for native buffers
2043            int32_t requestedColorFormat = OMX_COLOR_FormatUnused;
2044            if (msg->findInt32("color-format", &requestedColorFormat) &&
2045                    requestedColorFormat == OMX_COLOR_FormatYUV420Flexible) {
2046                status_t err = getPortFormat(kPortIndexOutput, outputFormat);
2047                if (err != OK) {
2048                    return err;
2049                }
2050                int32_t colorFormat = OMX_COLOR_FormatUnused;
2051                OMX_U32 flexibleEquivalent = OMX_COLOR_FormatUnused;
2052                if (!outputFormat->findInt32("color-format", &colorFormat)) {
2053                    ALOGE("ouptut port did not have a color format (wrong domain?)");
2054                    return BAD_VALUE;
2055                }
2056                ALOGD("[%s] Requested output format %#x and got %#x.",
2057                        mComponentName.c_str(), requestedColorFormat, colorFormat);
2058                if (!IsFlexibleColorFormat(
2059                        mOMXNode, colorFormat, haveNativeWindow, &flexibleEquivalent)
2060                        || flexibleEquivalent != (OMX_U32)requestedColorFormat) {
2061                    // device did not handle flex-YUV request for native window, fall back
2062                    // to SW renderer
2063                    ALOGI("[%s] Falling back to software renderer", mComponentName.c_str());
2064                    mNativeWindow.clear();
2065                    mNativeWindowUsageBits = 0;
2066                    haveNativeWindow = false;
2067                    usingSwRenderer = true;
2068                    // TODO: implement adaptive-playback support for bytebuffer mode.
2069                    // This is done by SW codecs, but most HW codecs don't support it.
2070                    err = setPortMode(kPortIndexOutput, IOMX::kPortModePresetByteBuffer);
2071                    inputFormat->setInt32("adaptive-playback", false);
2072                    if (mFlags & kFlagIsGrallocUsageProtected) {
2073                        // fallback is not supported for protected playback
2074                        err = PERMISSION_DENIED;
2075                    } else if (err == OK) {
2076                        err = setupVideoDecoder(
2077                                mime, msg, haveNativeWindow, usingSwRenderer, outputFormat);
2078                    }
2079                }
2080            }
2081        }
2082
2083        if (usingSwRenderer) {
2084            outputFormat->setInt32("using-sw-renderer", 1);
2085        }
2086    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
2087        int32_t numChannels, sampleRate;
2088        if (!msg->findInt32("channel-count", &numChannels)
2089                || !msg->findInt32("sample-rate", &sampleRate)) {
2090            // Since we did not always check for these, leave them optional
2091            // and have the decoder figure it all out.
2092            err = OK;
2093        } else {
2094            err = setupRawAudioFormat(
2095                    encoder ? kPortIndexInput : kPortIndexOutput,
2096                    sampleRate,
2097                    numChannels);
2098        }
2099    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
2100        int32_t numChannels, sampleRate;
2101        if (!msg->findInt32("channel-count", &numChannels)
2102                || !msg->findInt32("sample-rate", &sampleRate)) {
2103            err = INVALID_OPERATION;
2104        } else {
2105            int32_t isADTS, aacProfile;
2106            int32_t sbrMode;
2107            int32_t maxOutputChannelCount;
2108            int32_t pcmLimiterEnable;
2109            drcParams_t drc;
2110            if (!msg->findInt32("is-adts", &isADTS)) {
2111                isADTS = 0;
2112            }
2113            if (!msg->findInt32("aac-profile", &aacProfile)) {
2114                aacProfile = OMX_AUDIO_AACObjectNull;
2115            }
2116            if (!msg->findInt32("aac-sbr-mode", &sbrMode)) {
2117                sbrMode = -1;
2118            }
2119
2120            if (!msg->findInt32("aac-max-output-channel_count", &maxOutputChannelCount)) {
2121                maxOutputChannelCount = -1;
2122            }
2123            if (!msg->findInt32("aac-pcm-limiter-enable", &pcmLimiterEnable)) {
2124                // value is unknown
2125                pcmLimiterEnable = -1;
2126            }
2127            if (!msg->findInt32("aac-encoded-target-level", &drc.encodedTargetLevel)) {
2128                // value is unknown
2129                drc.encodedTargetLevel = -1;
2130            }
2131            if (!msg->findInt32("aac-drc-cut-level", &drc.drcCut)) {
2132                // value is unknown
2133                drc.drcCut = -1;
2134            }
2135            if (!msg->findInt32("aac-drc-boost-level", &drc.drcBoost)) {
2136                // value is unknown
2137                drc.drcBoost = -1;
2138            }
2139            if (!msg->findInt32("aac-drc-heavy-compression", &drc.heavyCompression)) {
2140                // value is unknown
2141                drc.heavyCompression = -1;
2142            }
2143            if (!msg->findInt32("aac-target-ref-level", &drc.targetRefLevel)) {
2144                // value is unknown
2145                drc.targetRefLevel = -1;
2146            }
2147
2148            err = setupAACCodec(
2149                    encoder, numChannels, sampleRate, bitrate, aacProfile,
2150                    isADTS != 0, sbrMode, maxOutputChannelCount, drc,
2151                    pcmLimiterEnable);
2152        }
2153    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) {
2154        err = setupAMRCodec(encoder, false /* isWAMR */, bitrate);
2155    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
2156        err = setupAMRCodec(encoder, true /* isWAMR */, bitrate);
2157    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW)
2158            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) {
2159        // These are PCM-like formats with a fixed sample rate but
2160        // a variable number of channels.
2161
2162        int32_t numChannels;
2163        if (!msg->findInt32("channel-count", &numChannels)) {
2164            err = INVALID_OPERATION;
2165        } else {
2166            int32_t sampleRate;
2167            if (!msg->findInt32("sample-rate", &sampleRate)) {
2168                sampleRate = 8000;
2169            }
2170            err = setupG711Codec(encoder, sampleRate, numChannels);
2171        }
2172    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)) {
2173        int32_t numChannels = 0, sampleRate = 0, compressionLevel = -1;
2174        if (encoder &&
2175                (!msg->findInt32("channel-count", &numChannels)
2176                        || !msg->findInt32("sample-rate", &sampleRate))) {
2177            ALOGE("missing channel count or sample rate for FLAC encoder");
2178            err = INVALID_OPERATION;
2179        } else {
2180            if (encoder) {
2181                if (!msg->findInt32(
2182                            "complexity", &compressionLevel) &&
2183                    !msg->findInt32(
2184                            "flac-compression-level", &compressionLevel)) {
2185                    compressionLevel = 5; // default FLAC compression level
2186                } else if (compressionLevel < 0) {
2187                    ALOGW("compression level %d outside [0..8] range, "
2188                          "using 0",
2189                          compressionLevel);
2190                    compressionLevel = 0;
2191                } else if (compressionLevel > 8) {
2192                    ALOGW("compression level %d outside [0..8] range, "
2193                          "using 8",
2194                          compressionLevel);
2195                    compressionLevel = 8;
2196                }
2197            }
2198            err = setupFlacCodec(
2199                    encoder, numChannels, sampleRate, compressionLevel);
2200        }
2201    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
2202        int32_t numChannels, sampleRate;
2203        if (encoder
2204                || !msg->findInt32("channel-count", &numChannels)
2205                || !msg->findInt32("sample-rate", &sampleRate)) {
2206            err = INVALID_OPERATION;
2207        } else {
2208            err = setupRawAudioFormat(kPortIndexInput, sampleRate, numChannels, pcmEncoding);
2209        }
2210    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AC3)) {
2211        int32_t numChannels;
2212        int32_t sampleRate;
2213        if (!msg->findInt32("channel-count", &numChannels)
2214                || !msg->findInt32("sample-rate", &sampleRate)) {
2215            err = INVALID_OPERATION;
2216        } else {
2217            err = setupAC3Codec(encoder, numChannels, sampleRate);
2218        }
2219    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_EAC3)) {
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 = setupEAC3Codec(encoder, numChannels, sampleRate);
2227        }
2228    }
2229
2230    if (err != OK) {
2231        return err;
2232    }
2233
2234    if (!msg->findInt32("encoder-delay", &mEncoderDelay)) {
2235        mEncoderDelay = 0;
2236    }
2237
2238    if (!msg->findInt32("encoder-padding", &mEncoderPadding)) {
2239        mEncoderPadding = 0;
2240    }
2241
2242    if (msg->findInt32("channel-mask", &mChannelMask)) {
2243        mChannelMaskPresent = true;
2244    } else {
2245        mChannelMaskPresent = false;
2246    }
2247
2248    int32_t maxInputSize;
2249    if (msg->findInt32("max-input-size", &maxInputSize)) {
2250        err = setMinBufferSize(kPortIndexInput, (size_t)maxInputSize);
2251        err = OK; // ignore error
2252    } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) {
2253        err = setMinBufferSize(kPortIndexInput, 8192);  // XXX
2254        err = OK; // ignore error
2255    }
2256
2257    int32_t priority;
2258    if (msg->findInt32("priority", &priority)) {
2259        err = setPriority(priority);
2260        err = OK; // ignore error
2261    }
2262
2263    int32_t rateInt = -1;
2264    float rateFloat = -1;
2265    if (!msg->findFloat("operating-rate", &rateFloat)) {
2266        msg->findInt32("operating-rate", &rateInt);
2267        rateFloat = (float)rateInt;  // 16MHz (FLINTMAX) is OK for upper bound.
2268    }
2269    if (rateFloat > 0) {
2270        err = setOperatingRate(rateFloat, mIsVideo);
2271        err = OK; // ignore errors
2272    }
2273
2274    if (err == OK) {
2275        err = setVendorParameters(msg);
2276        if (err != OK) {
2277            return err;
2278        }
2279    }
2280
2281    // NOTE: both mBaseOutputFormat and mOutputFormat are outputFormat to signal first frame.
2282    mBaseOutputFormat = outputFormat;
2283    mLastOutputFormat.clear();
2284
2285    err = getPortFormat(kPortIndexInput, inputFormat);
2286    if (err == OK) {
2287        err = getPortFormat(kPortIndexOutput, outputFormat);
2288        if (err == OK) {
2289            mInputFormat = inputFormat;
2290            mOutputFormat = outputFormat;
2291        }
2292    }
2293
2294    // create data converters if needed
2295    if (!mIsVideo && !mIsImage && err == OK) {
2296        AudioEncoding codecPcmEncoding = kAudioEncodingPcm16bit;
2297        if (encoder) {
2298            (void)mInputFormat->findInt32("pcm-encoding", (int32_t*)&codecPcmEncoding);
2299            mConverter[kPortIndexInput] = AudioConverter::Create(pcmEncoding, codecPcmEncoding);
2300            if (mConverter[kPortIndexInput] != NULL) {
2301                mInputFormat->setInt32("pcm-encoding", pcmEncoding);
2302            }
2303        } else {
2304            (void)mOutputFormat->findInt32("pcm-encoding", (int32_t*)&codecPcmEncoding);
2305            mConverter[kPortIndexOutput] = AudioConverter::Create(codecPcmEncoding, pcmEncoding);
2306            if (mConverter[kPortIndexOutput] != NULL) {
2307                mOutputFormat->setInt32("pcm-encoding", pcmEncoding);
2308            }
2309        }
2310    }
2311
2312    return err;
2313}
2314
2315status_t ACodec::setLatency(uint32_t latency) {
2316    OMX_PARAM_U32TYPE config;
2317    InitOMXParams(&config);
2318    config.nPortIndex = kPortIndexInput;
2319    config.nU32 = (OMX_U32)latency;
2320    status_t err = mOMXNode->setConfig(
2321            (OMX_INDEXTYPE)OMX_IndexConfigLatency,
2322            &config, sizeof(config));
2323    return err;
2324}
2325
2326status_t ACodec::getLatency(uint32_t *latency) {
2327    OMX_PARAM_U32TYPE config;
2328    InitOMXParams(&config);
2329    config.nPortIndex = kPortIndexInput;
2330    status_t err = mOMXNode->getConfig(
2331            (OMX_INDEXTYPE)OMX_IndexConfigLatency,
2332            &config, sizeof(config));
2333    if (err == OK) {
2334        *latency = config.nU32;
2335    }
2336    return err;
2337}
2338
2339status_t ACodec::setPriority(int32_t priority) {
2340    if (priority < 0) {
2341        return BAD_VALUE;
2342    }
2343    OMX_PARAM_U32TYPE config;
2344    InitOMXParams(&config);
2345    config.nU32 = (OMX_U32)priority;
2346    status_t temp = mOMXNode->setConfig(
2347            (OMX_INDEXTYPE)OMX_IndexConfigPriority,
2348            &config, sizeof(config));
2349    if (temp != OK) {
2350        ALOGI("codec does not support config priority (err %d)", temp);
2351    }
2352    return OK;
2353}
2354
2355status_t ACodec::setOperatingRate(float rateFloat, bool isVideo) {
2356    if (rateFloat < 0) {
2357        return BAD_VALUE;
2358    }
2359    OMX_U32 rate;
2360    if (isVideo) {
2361        if (rateFloat > 65535) {
2362            return BAD_VALUE;
2363        }
2364        rate = (OMX_U32)(rateFloat * 65536.0f + 0.5f);
2365    } else {
2366        if (rateFloat > UINT_MAX) {
2367            return BAD_VALUE;
2368        }
2369        rate = (OMX_U32)(rateFloat);
2370    }
2371    OMX_PARAM_U32TYPE config;
2372    InitOMXParams(&config);
2373    config.nU32 = rate;
2374    status_t err = mOMXNode->setConfig(
2375            (OMX_INDEXTYPE)OMX_IndexConfigOperatingRate,
2376            &config, sizeof(config));
2377    if (err != OK) {
2378        ALOGI("codec does not support config operating rate (err %d)", err);
2379    }
2380    return OK;
2381}
2382
2383status_t ACodec::getIntraRefreshPeriod(uint32_t *intraRefreshPeriod) {
2384    OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE params;
2385    InitOMXParams(&params);
2386    params.nPortIndex = kPortIndexOutput;
2387    status_t err = mOMXNode->getConfig(
2388            (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh, &params, sizeof(params));
2389    if (err == OK) {
2390        *intraRefreshPeriod = params.nRefreshPeriod;
2391        return OK;
2392    }
2393
2394    // Fallback to query through standard OMX index.
2395    OMX_VIDEO_PARAM_INTRAREFRESHTYPE refreshParams;
2396    InitOMXParams(&refreshParams);
2397    refreshParams.nPortIndex = kPortIndexOutput;
2398    refreshParams.eRefreshMode = OMX_VIDEO_IntraRefreshCyclic;
2399    err = mOMXNode->getParameter(
2400            OMX_IndexParamVideoIntraRefresh, &refreshParams, sizeof(refreshParams));
2401    if (err != OK || refreshParams.nCirMBs == 0) {
2402        *intraRefreshPeriod = 0;
2403        return OK;
2404    }
2405
2406    // Calculate period based on width and height
2407    uint32_t width, height;
2408    OMX_PARAM_PORTDEFINITIONTYPE def;
2409    InitOMXParams(&def);
2410    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
2411    def.nPortIndex = kPortIndexOutput;
2412    err = mOMXNode->getParameter(
2413            OMX_IndexParamPortDefinition, &def, sizeof(def));
2414    if (err != OK) {
2415        *intraRefreshPeriod = 0;
2416        return err;
2417    }
2418    width = video_def->nFrameWidth;
2419    height = video_def->nFrameHeight;
2420    // Use H.264/AVC MacroBlock size 16x16
2421    *intraRefreshPeriod = divUp((divUp(width, 16u) * divUp(height, 16u)), refreshParams.nCirMBs);
2422
2423    return OK;
2424}
2425
2426status_t ACodec::setIntraRefreshPeriod(uint32_t intraRefreshPeriod, bool inConfigure) {
2427    OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE params;
2428    InitOMXParams(&params);
2429    params.nPortIndex = kPortIndexOutput;
2430    params.nRefreshPeriod = intraRefreshPeriod;
2431    status_t err = mOMXNode->setConfig(
2432            (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh, &params, sizeof(params));
2433    if (err == OK) {
2434        return OK;
2435    }
2436
2437    // Only in configure state, a component could invoke setParameter.
2438    if (!inConfigure) {
2439        return INVALID_OPERATION;
2440    } else {
2441        ALOGI("[%s] try falling back to Cyclic", mComponentName.c_str());
2442    }
2443
2444    OMX_VIDEO_PARAM_INTRAREFRESHTYPE refreshParams;
2445    InitOMXParams(&refreshParams);
2446    refreshParams.nPortIndex = kPortIndexOutput;
2447    refreshParams.eRefreshMode = OMX_VIDEO_IntraRefreshCyclic;
2448
2449    if (intraRefreshPeriod == 0) {
2450        // 0 means disable intra refresh.
2451        refreshParams.nCirMBs = 0;
2452    } else {
2453        // Calculate macroblocks that need to be intra coded base on width and height
2454        uint32_t width, height;
2455        OMX_PARAM_PORTDEFINITIONTYPE def;
2456        InitOMXParams(&def);
2457        OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
2458        def.nPortIndex = kPortIndexOutput;
2459        err = mOMXNode->getParameter(
2460                OMX_IndexParamPortDefinition, &def, sizeof(def));
2461        if (err != OK) {
2462            return err;
2463        }
2464        width = video_def->nFrameWidth;
2465        height = video_def->nFrameHeight;
2466        // Use H.264/AVC MacroBlock size 16x16
2467        refreshParams.nCirMBs = divUp((divUp(width, 16u) * divUp(height, 16u)), intraRefreshPeriod);
2468    }
2469
2470    err = mOMXNode->setParameter(
2471            OMX_IndexParamVideoIntraRefresh,
2472            &refreshParams, sizeof(refreshParams));
2473    if (err != OK) {
2474        return err;
2475    }
2476
2477    return OK;
2478}
2479
2480status_t ACodec::configureTemporalLayers(
2481        const sp<AMessage> &msg, bool inConfigure, sp<AMessage> &outputFormat) {
2482    if (!mIsVideo || !mIsEncoder) {
2483        return INVALID_OPERATION;
2484    }
2485
2486    AString tsSchema;
2487    if (!msg->findString("ts-schema", &tsSchema)) {
2488        return OK;
2489    }
2490
2491    unsigned int numLayers = 0;
2492    unsigned int numBLayers = 0;
2493    int tags;
2494    char dummy;
2495    OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE pattern =
2496        OMX_VIDEO_AndroidTemporalLayeringPatternNone;
2497    if (sscanf(tsSchema.c_str(), "webrtc.vp8.%u-layer%c", &numLayers, &dummy) == 1
2498            && numLayers > 0) {
2499        pattern = OMX_VIDEO_AndroidTemporalLayeringPatternWebRTC;
2500    } else if ((tags = sscanf(tsSchema.c_str(), "android.generic.%u%c%u%c",
2501                    &numLayers, &dummy, &numBLayers, &dummy))
2502            && (tags == 1 || (tags == 3 && dummy == '+'))
2503            && numLayers > 0 && numLayers < UINT32_MAX - numBLayers) {
2504        numLayers += numBLayers;
2505        pattern = OMX_VIDEO_AndroidTemporalLayeringPatternAndroid;
2506    } else {
2507        ALOGI("Ignoring unsupported ts-schema [%s]", tsSchema.c_str());
2508        return BAD_VALUE;
2509    }
2510
2511    OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE layerParams;
2512    InitOMXParams(&layerParams);
2513    layerParams.nPortIndex = kPortIndexOutput;
2514
2515    status_t err = mOMXNode->getParameter(
2516            (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering,
2517            &layerParams, sizeof(layerParams));
2518
2519    if (err != OK) {
2520        return err;
2521    } else if (!(layerParams.eSupportedPatterns & pattern)) {
2522        return BAD_VALUE;
2523    }
2524
2525    numLayers = min(numLayers, layerParams.nLayerCountMax);
2526    numBLayers = min(numBLayers, layerParams.nBLayerCountMax);
2527
2528    if (!inConfigure) {
2529        OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE layerConfig;
2530        InitOMXParams(&layerConfig);
2531        layerConfig.nPortIndex = kPortIndexOutput;
2532        layerConfig.ePattern = pattern;
2533        layerConfig.nPLayerCountActual = numLayers - numBLayers;
2534        layerConfig.nBLayerCountActual = numBLayers;
2535        layerConfig.bBitrateRatiosSpecified = OMX_FALSE;
2536
2537        err = mOMXNode->setConfig(
2538                (OMX_INDEXTYPE)OMX_IndexConfigAndroidVideoTemporalLayering,
2539                &layerConfig, sizeof(layerConfig));
2540    } else {
2541        layerParams.ePattern = pattern;
2542        layerParams.nPLayerCountActual = numLayers - numBLayers;
2543        layerParams.nBLayerCountActual = numBLayers;
2544        layerParams.bBitrateRatiosSpecified = OMX_FALSE;
2545
2546        err = mOMXNode->setParameter(
2547                (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering,
2548                &layerParams, sizeof(layerParams));
2549    }
2550
2551    AString configSchema;
2552    if (pattern == OMX_VIDEO_AndroidTemporalLayeringPatternAndroid) {
2553        configSchema = AStringPrintf("android.generic.%u+%u", numLayers - numBLayers, numBLayers);
2554    } else if (pattern == OMX_VIDEO_AndroidTemporalLayeringPatternWebRTC) {
2555        configSchema = AStringPrintf("webrtc.vp8.%u", numLayers);
2556    }
2557
2558    if (err != OK) {
2559        ALOGW("Failed to set temporal layers to %s (requested %s)",
2560                configSchema.c_str(), tsSchema.c_str());
2561        return err;
2562    }
2563
2564    err = mOMXNode->getParameter(
2565            (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering,
2566            &layerParams, sizeof(layerParams));
2567
2568    if (err == OK) {
2569        ALOGD("Temporal layers requested:%s configured:%s got:%s(%u: P=%u, B=%u)",
2570                tsSchema.c_str(), configSchema.c_str(),
2571                asString(layerParams.ePattern), layerParams.ePattern,
2572                layerParams.nPLayerCountActual, layerParams.nBLayerCountActual);
2573
2574        if (outputFormat.get() == mOutputFormat.get()) {
2575            mOutputFormat = mOutputFormat->dup(); // trigger an output format change event
2576        }
2577        // assume we got what we configured
2578        outputFormat->setString("ts-schema", configSchema);
2579    }
2580    return err;
2581}
2582
2583status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) {
2584    OMX_PARAM_PORTDEFINITIONTYPE def;
2585    InitOMXParams(&def);
2586    def.nPortIndex = portIndex;
2587
2588    status_t err = mOMXNode->getParameter(
2589            OMX_IndexParamPortDefinition, &def, sizeof(def));
2590
2591    if (err != OK) {
2592        return err;
2593    }
2594
2595    if (def.nBufferSize >= size) {
2596        return OK;
2597    }
2598
2599    def.nBufferSize = size;
2600
2601    err = mOMXNode->setParameter(
2602            OMX_IndexParamPortDefinition, &def, sizeof(def));
2603
2604    if (err != OK) {
2605        return err;
2606    }
2607
2608    err = mOMXNode->getParameter(
2609            OMX_IndexParamPortDefinition, &def, sizeof(def));
2610
2611    if (err != OK) {
2612        return err;
2613    }
2614
2615    if (def.nBufferSize < size) {
2616        ALOGE("failed to set min buffer size to %zu (is still %u)", size, def.nBufferSize);
2617        return FAILED_TRANSACTION;
2618    }
2619
2620    return OK;
2621}
2622
2623status_t ACodec::selectAudioPortFormat(
2624        OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat) {
2625    OMX_AUDIO_PARAM_PORTFORMATTYPE format;
2626    InitOMXParams(&format);
2627
2628    format.nPortIndex = portIndex;
2629    for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
2630        format.nIndex = index;
2631        status_t err = mOMXNode->getParameter(
2632                OMX_IndexParamAudioPortFormat, &format, sizeof(format));
2633
2634        if (err != OK) {
2635            return err;
2636        }
2637
2638        if (format.eEncoding == desiredFormat) {
2639            break;
2640        }
2641
2642        if (index == kMaxIndicesToCheck) {
2643            ALOGW("[%s] stopping checking formats after %u: %s(%x)",
2644                    mComponentName.c_str(), index,
2645                    asString(format.eEncoding), format.eEncoding);
2646            return ERROR_UNSUPPORTED;
2647        }
2648    }
2649
2650    return mOMXNode->setParameter(
2651            OMX_IndexParamAudioPortFormat, &format, sizeof(format));
2652}
2653
2654status_t ACodec::setupAACCodec(
2655        bool encoder, int32_t numChannels, int32_t sampleRate,
2656        int32_t bitRate, int32_t aacProfile, bool isADTS, int32_t sbrMode,
2657        int32_t maxOutputChannelCount, const drcParams_t& drc,
2658        int32_t pcmLimiterEnable) {
2659    if (encoder && isADTS) {
2660        return -EINVAL;
2661    }
2662
2663    status_t err = setupRawAudioFormat(
2664            encoder ? kPortIndexInput : kPortIndexOutput,
2665            sampleRate,
2666            numChannels);
2667
2668    if (err != OK) {
2669        return err;
2670    }
2671
2672    if (encoder) {
2673        err = selectAudioPortFormat(kPortIndexOutput, OMX_AUDIO_CodingAAC);
2674
2675        if (err != OK) {
2676            return err;
2677        }
2678
2679        OMX_PARAM_PORTDEFINITIONTYPE def;
2680        InitOMXParams(&def);
2681        def.nPortIndex = kPortIndexOutput;
2682
2683        err = mOMXNode->getParameter(
2684                OMX_IndexParamPortDefinition, &def, sizeof(def));
2685
2686        if (err != OK) {
2687            return err;
2688        }
2689
2690        def.format.audio.bFlagErrorConcealment = OMX_TRUE;
2691        def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
2692
2693        err = mOMXNode->setParameter(
2694                OMX_IndexParamPortDefinition, &def, sizeof(def));
2695
2696        if (err != OK) {
2697            return err;
2698        }
2699
2700        OMX_AUDIO_PARAM_AACPROFILETYPE profile;
2701        InitOMXParams(&profile);
2702        profile.nPortIndex = kPortIndexOutput;
2703
2704        err = mOMXNode->getParameter(
2705                OMX_IndexParamAudioAac, &profile, sizeof(profile));
2706
2707        if (err != OK) {
2708            return err;
2709        }
2710
2711        profile.nChannels = numChannels;
2712
2713        profile.eChannelMode =
2714            (numChannels == 1)
2715                ? OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo;
2716
2717        profile.nSampleRate = sampleRate;
2718        profile.nBitRate = bitRate;
2719        profile.nAudioBandWidth = 0;
2720        profile.nFrameLength = 0;
2721        profile.nAACtools = OMX_AUDIO_AACToolAll;
2722        profile.nAACERtools = OMX_AUDIO_AACERNone;
2723        profile.eAACProfile = (OMX_AUDIO_AACPROFILETYPE) aacProfile;
2724        profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
2725        switch (sbrMode) {
2726        case 0:
2727            // disable sbr
2728            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR;
2729            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR;
2730            break;
2731        case 1:
2732            // enable single-rate sbr
2733            profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR;
2734            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR;
2735            break;
2736        case 2:
2737            // enable dual-rate sbr
2738            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR;
2739            profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR;
2740            break;
2741        case -1:
2742            // enable both modes -> the codec will decide which mode should be used
2743            profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR;
2744            profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR;
2745            break;
2746        default:
2747            // unsupported sbr mode
2748            return BAD_VALUE;
2749        }
2750
2751
2752        err = mOMXNode->setParameter(
2753                OMX_IndexParamAudioAac, &profile, sizeof(profile));
2754
2755        if (err != OK) {
2756            return err;
2757        }
2758
2759        return err;
2760    }
2761
2762    OMX_AUDIO_PARAM_AACPROFILETYPE profile;
2763    InitOMXParams(&profile);
2764    profile.nPortIndex = kPortIndexInput;
2765
2766    err = mOMXNode->getParameter(
2767            OMX_IndexParamAudioAac, &profile, sizeof(profile));
2768
2769    if (err != OK) {
2770        return err;
2771    }
2772
2773    profile.nChannels = numChannels;
2774    profile.nSampleRate = sampleRate;
2775
2776    profile.eAACStreamFormat =
2777        isADTS
2778            ? OMX_AUDIO_AACStreamFormatMP4ADTS
2779            : OMX_AUDIO_AACStreamFormatMP4FF;
2780
2781    OMX_AUDIO_PARAM_ANDROID_AACPRESENTATIONTYPE presentation;
2782    InitOMXParams(&presentation);
2783    presentation.nMaxOutputChannels = maxOutputChannelCount;
2784    presentation.nDrcCut = drc.drcCut;
2785    presentation.nDrcBoost = drc.drcBoost;
2786    presentation.nHeavyCompression = drc.heavyCompression;
2787    presentation.nTargetReferenceLevel = drc.targetRefLevel;
2788    presentation.nEncodedTargetLevel = drc.encodedTargetLevel;
2789    presentation.nPCMLimiterEnable = pcmLimiterEnable;
2790
2791    status_t res = mOMXNode->setParameter(
2792            OMX_IndexParamAudioAac, &profile, sizeof(profile));
2793    if (res == OK) {
2794        // optional parameters, will not cause configuration failure
2795        mOMXNode->setParameter(
2796                (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAacPresentation,
2797                &presentation, sizeof(presentation));
2798    } else {
2799        ALOGW("did not set AudioAndroidAacPresentation due to error %d when setting AudioAac", res);
2800    }
2801    mSampleRate = sampleRate;
2802    return res;
2803}
2804
2805status_t ACodec::setupAC3Codec(
2806        bool encoder, int32_t numChannels, int32_t sampleRate) {
2807    status_t err = setupRawAudioFormat(
2808            encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels);
2809
2810    if (err != OK) {
2811        return err;
2812    }
2813
2814    if (encoder) {
2815        ALOGW("AC3 encoding is not supported.");
2816        return INVALID_OPERATION;
2817    }
2818
2819    OMX_AUDIO_PARAM_ANDROID_AC3TYPE def;
2820    InitOMXParams(&def);
2821    def.nPortIndex = kPortIndexInput;
2822
2823    err = mOMXNode->getParameter(
2824            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, &def, sizeof(def));
2825
2826    if (err != OK) {
2827        return err;
2828    }
2829
2830    def.nChannels = numChannels;
2831    def.nSampleRate = sampleRate;
2832
2833    return mOMXNode->setParameter(
2834            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, &def, sizeof(def));
2835}
2836
2837status_t ACodec::setupEAC3Codec(
2838        bool encoder, int32_t numChannels, int32_t sampleRate) {
2839    status_t err = setupRawAudioFormat(
2840            encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels);
2841
2842    if (err != OK) {
2843        return err;
2844    }
2845
2846    if (encoder) {
2847        ALOGW("EAC3 encoding is not supported.");
2848        return INVALID_OPERATION;
2849    }
2850
2851    OMX_AUDIO_PARAM_ANDROID_EAC3TYPE def;
2852    InitOMXParams(&def);
2853    def.nPortIndex = kPortIndexInput;
2854
2855    err = mOMXNode->getParameter(
2856            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3, &def, sizeof(def));
2857
2858    if (err != OK) {
2859        return err;
2860    }
2861
2862    def.nChannels = numChannels;
2863    def.nSampleRate = sampleRate;
2864
2865    return mOMXNode->setParameter(
2866            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3, &def, sizeof(def));
2867}
2868
2869static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate(
2870        bool isAMRWB, int32_t bps) {
2871    if (isAMRWB) {
2872        if (bps <= 6600) {
2873            return OMX_AUDIO_AMRBandModeWB0;
2874        } else if (bps <= 8850) {
2875            return OMX_AUDIO_AMRBandModeWB1;
2876        } else if (bps <= 12650) {
2877            return OMX_AUDIO_AMRBandModeWB2;
2878        } else if (bps <= 14250) {
2879            return OMX_AUDIO_AMRBandModeWB3;
2880        } else if (bps <= 15850) {
2881            return OMX_AUDIO_AMRBandModeWB4;
2882        } else if (bps <= 18250) {
2883            return OMX_AUDIO_AMRBandModeWB5;
2884        } else if (bps <= 19850) {
2885            return OMX_AUDIO_AMRBandModeWB6;
2886        } else if (bps <= 23050) {
2887            return OMX_AUDIO_AMRBandModeWB7;
2888        }
2889
2890        // 23850 bps
2891        return OMX_AUDIO_AMRBandModeWB8;
2892    } else {  // AMRNB
2893        if (bps <= 4750) {
2894            return OMX_AUDIO_AMRBandModeNB0;
2895        } else if (bps <= 5150) {
2896            return OMX_AUDIO_AMRBandModeNB1;
2897        } else if (bps <= 5900) {
2898            return OMX_AUDIO_AMRBandModeNB2;
2899        } else if (bps <= 6700) {
2900            return OMX_AUDIO_AMRBandModeNB3;
2901        } else if (bps <= 7400) {
2902            return OMX_AUDIO_AMRBandModeNB4;
2903        } else if (bps <= 7950) {
2904            return OMX_AUDIO_AMRBandModeNB5;
2905        } else if (bps <= 10200) {
2906            return OMX_AUDIO_AMRBandModeNB6;
2907        }
2908
2909        // 12200 bps
2910        return OMX_AUDIO_AMRBandModeNB7;
2911    }
2912}
2913
2914status_t ACodec::setupAMRCodec(bool encoder, bool isWAMR, int32_t bitrate) {
2915    OMX_AUDIO_PARAM_AMRTYPE def;
2916    InitOMXParams(&def);
2917    def.nPortIndex = encoder ? kPortIndexOutput : kPortIndexInput;
2918
2919    status_t err = mOMXNode->getParameter(
2920            OMX_IndexParamAudioAmr, &def, sizeof(def));
2921
2922    if (err != OK) {
2923        return err;
2924    }
2925
2926    def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
2927    def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitrate);
2928
2929    err = mOMXNode->setParameter(
2930            OMX_IndexParamAudioAmr, &def, sizeof(def));
2931
2932    if (err != OK) {
2933        return err;
2934    }
2935
2936    return setupRawAudioFormat(
2937            encoder ? kPortIndexInput : kPortIndexOutput,
2938            isWAMR ? 16000 : 8000 /* sampleRate */,
2939            1 /* numChannels */);
2940}
2941
2942status_t ACodec::setupG711Codec(bool encoder, int32_t sampleRate, int32_t numChannels) {
2943    if (encoder) {
2944        return INVALID_OPERATION;
2945    }
2946
2947    return setupRawAudioFormat(
2948            kPortIndexInput, sampleRate, numChannels);
2949}
2950
2951status_t ACodec::setupFlacCodec(
2952        bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel) {
2953
2954    if (encoder) {
2955        OMX_AUDIO_PARAM_FLACTYPE def;
2956        InitOMXParams(&def);
2957        def.nPortIndex = kPortIndexOutput;
2958
2959        // configure compression level
2960        status_t err = mOMXNode->getParameter(OMX_IndexParamAudioFlac, &def, sizeof(def));
2961        if (err != OK) {
2962            ALOGE("setupFlacCodec(): Error %d getting OMX_IndexParamAudioFlac parameter", err);
2963            return err;
2964        }
2965        def.nCompressionLevel = compressionLevel;
2966        err = mOMXNode->setParameter(OMX_IndexParamAudioFlac, &def, sizeof(def));
2967        if (err != OK) {
2968            ALOGE("setupFlacCodec(): Error %d setting OMX_IndexParamAudioFlac parameter", err);
2969            return err;
2970        }
2971    }
2972
2973    return setupRawAudioFormat(
2974            encoder ? kPortIndexInput : kPortIndexOutput,
2975            sampleRate,
2976            numChannels);
2977}
2978
2979status_t ACodec::setupRawAudioFormat(
2980        OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels, AudioEncoding encoding) {
2981    OMX_PARAM_PORTDEFINITIONTYPE def;
2982    InitOMXParams(&def);
2983    def.nPortIndex = portIndex;
2984
2985    status_t err = mOMXNode->getParameter(
2986            OMX_IndexParamPortDefinition, &def, sizeof(def));
2987
2988    if (err != OK) {
2989        return err;
2990    }
2991
2992    def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
2993
2994    err = mOMXNode->setParameter(
2995            OMX_IndexParamPortDefinition, &def, sizeof(def));
2996
2997    if (err != OK) {
2998        return err;
2999    }
3000
3001    OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
3002    InitOMXParams(&pcmParams);
3003    pcmParams.nPortIndex = portIndex;
3004
3005    err = mOMXNode->getParameter(
3006            OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
3007
3008    if (err != OK) {
3009        return err;
3010    }
3011
3012    pcmParams.nChannels = numChannels;
3013    switch (encoding) {
3014        case kAudioEncodingPcm8bit:
3015            pcmParams.eNumData = OMX_NumericalDataUnsigned;
3016            pcmParams.nBitPerSample = 8;
3017            break;
3018        case kAudioEncodingPcmFloat:
3019            pcmParams.eNumData = OMX_NumericalDataFloat;
3020            pcmParams.nBitPerSample = 32;
3021            break;
3022        case kAudioEncodingPcm16bit:
3023            pcmParams.eNumData = OMX_NumericalDataSigned;
3024            pcmParams.nBitPerSample = 16;
3025            break;
3026        default:
3027            return BAD_VALUE;
3028    }
3029    pcmParams.bInterleaved = OMX_TRUE;
3030    pcmParams.nSamplingRate = sampleRate;
3031    pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
3032
3033    if (getOMXChannelMapping(numChannels, pcmParams.eChannelMapping) != OK) {
3034        return OMX_ErrorNone;
3035    }
3036
3037    err = mOMXNode->setParameter(
3038            OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
3039    // if we could not set up raw format to non-16-bit, try with 16-bit
3040    // NOTE: we will also verify this via readback, in case codec ignores these fields
3041    if (err != OK && encoding != kAudioEncodingPcm16bit) {
3042        pcmParams.eNumData = OMX_NumericalDataSigned;
3043        pcmParams.nBitPerSample = 16;
3044        err = mOMXNode->setParameter(
3045                OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
3046    }
3047    return err;
3048}
3049
3050status_t ACodec::configureTunneledVideoPlayback(
3051        int32_t audioHwSync, const sp<ANativeWindow> &nativeWindow) {
3052    native_handle_t* sidebandHandle;
3053
3054    status_t err = mOMXNode->configureVideoTunnelMode(
3055            kPortIndexOutput, OMX_TRUE, audioHwSync, &sidebandHandle);
3056    if (err != OK) {
3057        ALOGE("configureVideoTunnelMode failed! (err %d).", err);
3058        return err;
3059    }
3060
3061    err = native_window_set_sideband_stream(nativeWindow.get(), sidebandHandle);
3062    if (err != OK) {
3063        ALOGE("native_window_set_sideband_stream(%p) failed! (err %d).",
3064                sidebandHandle, err);
3065        return err;
3066    }
3067
3068    return OK;
3069}
3070
3071status_t ACodec::setVideoPortFormatType(
3072        OMX_U32 portIndex,
3073        OMX_VIDEO_CODINGTYPE compressionFormat,
3074        OMX_COLOR_FORMATTYPE colorFormat,
3075        bool usingNativeBuffers) {
3076    OMX_VIDEO_PARAM_PORTFORMATTYPE format;
3077    InitOMXParams(&format);
3078    format.nPortIndex = portIndex;
3079    format.nIndex = 0;
3080    bool found = false;
3081
3082    for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
3083        format.nIndex = index;
3084        status_t err = mOMXNode->getParameter(
3085                OMX_IndexParamVideoPortFormat,
3086                &format, sizeof(format));
3087
3088        if (err != OK) {
3089            return err;
3090        }
3091
3092        // substitute back flexible color format to codec supported format
3093        OMX_U32 flexibleEquivalent;
3094        if (compressionFormat == OMX_VIDEO_CodingUnused
3095                && IsFlexibleColorFormat(
3096                        mOMXNode, format.eColorFormat, usingNativeBuffers, &flexibleEquivalent)
3097                && colorFormat == flexibleEquivalent) {
3098            ALOGI("[%s] using color format %#x in place of %#x",
3099                    mComponentName.c_str(), format.eColorFormat, colorFormat);
3100            colorFormat = format.eColorFormat;
3101        }
3102
3103        // The following assertion is violated by TI's video decoder.
3104        // CHECK_EQ(format.nIndex, index);
3105
3106        if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) {
3107            if (portIndex == kPortIndexInput
3108                    && colorFormat == format.eColorFormat) {
3109                // eCompressionFormat does not seem right.
3110                found = true;
3111                break;
3112            }
3113            if (portIndex == kPortIndexOutput
3114                    && compressionFormat == format.eCompressionFormat) {
3115                // eColorFormat does not seem right.
3116                found = true;
3117                break;
3118            }
3119        }
3120
3121        if (format.eCompressionFormat == compressionFormat
3122            && format.eColorFormat == colorFormat) {
3123            found = true;
3124            break;
3125        }
3126
3127        if (index == kMaxIndicesToCheck) {
3128            ALOGW("[%s] stopping checking formats after %u: %s(%x)/%s(%x)",
3129                    mComponentName.c_str(), index,
3130                    asString(format.eCompressionFormat), format.eCompressionFormat,
3131                    asString(format.eColorFormat), format.eColorFormat);
3132        }
3133    }
3134
3135    if (!found) {
3136        return UNKNOWN_ERROR;
3137    }
3138
3139    status_t err = mOMXNode->setParameter(
3140            OMX_IndexParamVideoPortFormat, &format, sizeof(format));
3141
3142    return err;
3143}
3144
3145// Set optimal output format. OMX component lists output formats in the order
3146// of preference, but this got more complicated since the introduction of flexible
3147// YUV formats. We support a legacy behavior for applications that do not use
3148// surface output, do not specify an output format, but expect a "usable" standard
3149// OMX format. SW readable and standard formats must be flex-YUV.
3150//
3151// Suggested preference order:
3152// - optimal format for texture rendering (mediaplayer behavior)
3153// - optimal SW readable & texture renderable format (flex-YUV support)
3154// - optimal SW readable non-renderable format (flex-YUV bytebuffer support)
3155// - legacy "usable" standard formats
3156//
3157// For legacy support, we prefer a standard format, but will settle for a SW readable
3158// flex-YUV format.
3159status_t ACodec::setSupportedOutputFormat(bool getLegacyFlexibleFormat) {
3160    OMX_VIDEO_PARAM_PORTFORMATTYPE format, legacyFormat;
3161    InitOMXParams(&format);
3162    format.nPortIndex = kPortIndexOutput;
3163
3164    InitOMXParams(&legacyFormat);
3165    // this field will change when we find a suitable legacy format
3166    legacyFormat.eColorFormat = OMX_COLOR_FormatUnused;
3167
3168    for (OMX_U32 index = 0; ; ++index) {
3169        format.nIndex = index;
3170        status_t err = mOMXNode->getParameter(
3171                OMX_IndexParamVideoPortFormat, &format, sizeof(format));
3172        if (err != OK) {
3173            // no more formats, pick legacy format if found
3174            if (legacyFormat.eColorFormat != OMX_COLOR_FormatUnused) {
3175                 memcpy(&format, &legacyFormat, sizeof(format));
3176                 break;
3177            }
3178            return err;
3179        }
3180        if (format.eCompressionFormat != OMX_VIDEO_CodingUnused) {
3181            return OMX_ErrorBadParameter;
3182        }
3183        if (!getLegacyFlexibleFormat) {
3184            break;
3185        }
3186        // standard formats that were exposed to users before
3187        if (format.eColorFormat == OMX_COLOR_FormatYUV420Planar
3188                || format.eColorFormat == OMX_COLOR_FormatYUV420PackedPlanar
3189                || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
3190                || format.eColorFormat == OMX_COLOR_FormatYUV420PackedSemiPlanar
3191                || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar) {
3192            break;
3193        }
3194        // find best legacy non-standard format
3195        OMX_U32 flexibleEquivalent;
3196        if (legacyFormat.eColorFormat == OMX_COLOR_FormatUnused
3197                && IsFlexibleColorFormat(
3198                        mOMXNode, format.eColorFormat, false /* usingNativeBuffers */,
3199                        &flexibleEquivalent)
3200                && flexibleEquivalent == OMX_COLOR_FormatYUV420Flexible) {
3201            memcpy(&legacyFormat, &format, sizeof(format));
3202        }
3203    }
3204    return mOMXNode->setParameter(
3205            OMX_IndexParamVideoPortFormat, &format, sizeof(format));
3206}
3207
3208static const struct VideoCodingMapEntry {
3209    const char *mMime;
3210    OMX_VIDEO_CODINGTYPE mVideoCodingType;
3211} kVideoCodingMapEntry[] = {
3212    { MEDIA_MIMETYPE_VIDEO_AVC, OMX_VIDEO_CodingAVC },
3213    { MEDIA_MIMETYPE_VIDEO_HEVC, OMX_VIDEO_CodingHEVC },
3214    { MEDIA_MIMETYPE_VIDEO_MPEG4, OMX_VIDEO_CodingMPEG4 },
3215    { MEDIA_MIMETYPE_VIDEO_H263, OMX_VIDEO_CodingH263 },
3216    { MEDIA_MIMETYPE_VIDEO_MPEG2, OMX_VIDEO_CodingMPEG2 },
3217    { MEDIA_MIMETYPE_VIDEO_VP8, OMX_VIDEO_CodingVP8 },
3218    { MEDIA_MIMETYPE_VIDEO_VP9, OMX_VIDEO_CodingVP9 },
3219    { MEDIA_MIMETYPE_VIDEO_DOLBY_VISION, OMX_VIDEO_CodingDolbyVision },
3220    { MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC, OMX_VIDEO_CodingImageHEIC },
3221};
3222
3223static status_t GetVideoCodingTypeFromMime(
3224        const char *mime, OMX_VIDEO_CODINGTYPE *codingType) {
3225    for (size_t i = 0;
3226         i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]);
3227         ++i) {
3228        if (!strcasecmp(mime, kVideoCodingMapEntry[i].mMime)) {
3229            *codingType = kVideoCodingMapEntry[i].mVideoCodingType;
3230            return OK;
3231        }
3232    }
3233
3234    *codingType = OMX_VIDEO_CodingUnused;
3235
3236    return ERROR_UNSUPPORTED;
3237}
3238
3239static status_t GetMimeTypeForVideoCoding(
3240        OMX_VIDEO_CODINGTYPE codingType, AString *mime) {
3241    for (size_t i = 0;
3242         i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]);
3243         ++i) {
3244        if (codingType == kVideoCodingMapEntry[i].mVideoCodingType) {
3245            *mime = kVideoCodingMapEntry[i].mMime;
3246            return OK;
3247        }
3248    }
3249
3250    mime->clear();
3251
3252    return ERROR_UNSUPPORTED;
3253}
3254
3255status_t ACodec::setPortBufferNum(OMX_U32 portIndex, int bufferNum) {
3256    OMX_PARAM_PORTDEFINITIONTYPE def;
3257    InitOMXParams(&def);
3258    def.nPortIndex = portIndex;
3259    status_t err;
3260    ALOGD("Setting [%s] %s port buffer number: %d", mComponentName.c_str(),
3261            portIndex == kPortIndexInput ? "input" : "output", bufferNum);
3262    err = mOMXNode->getParameter(
3263        OMX_IndexParamPortDefinition, &def, sizeof(def));
3264    if (err != OK) {
3265        return err;
3266    }
3267    def.nBufferCountActual = bufferNum;
3268    err = mOMXNode->setParameter(
3269        OMX_IndexParamPortDefinition, &def, sizeof(def));
3270    if (err != OK) {
3271        // Component could reject this request.
3272        ALOGW("Fail to set [%s] %s port buffer number: %d", mComponentName.c_str(),
3273            portIndex == kPortIndexInput ? "input" : "output", bufferNum);
3274    }
3275    return OK;
3276}
3277
3278status_t ACodec::setupVideoDecoder(
3279        const char *mime, const sp<AMessage> &msg, bool haveNativeWindow,
3280        bool usingSwRenderer, sp<AMessage> &outputFormat) {
3281    int32_t width, height;
3282    if (!msg->findInt32("width", &width)
3283            || !msg->findInt32("height", &height)) {
3284        return INVALID_OPERATION;
3285    }
3286
3287    OMX_VIDEO_CODINGTYPE compressionFormat;
3288    status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
3289
3290    if (err != OK) {
3291        return err;
3292    }
3293
3294    if (compressionFormat == OMX_VIDEO_CodingHEVC) {
3295        int32_t profile;
3296        if (msg->findInt32("profile", &profile)) {
3297            // verify if Main10 profile is supported at all, and fail
3298            // immediately if it's not supported.
3299            if (profile == OMX_VIDEO_HEVCProfileMain10 ||
3300                profile == OMX_VIDEO_HEVCProfileMain10HDR10) {
3301                err = verifySupportForProfileAndLevel(
3302                        kPortIndexInput, profile, 0);
3303                if (err != OK) {
3304                    return err;
3305                }
3306            }
3307        }
3308    }
3309
3310    if (compressionFormat == OMX_VIDEO_CodingVP9) {
3311        OMX_VIDEO_PARAM_PROFILELEVELTYPE params;
3312        InitOMXParams(&params);
3313        params.nPortIndex = kPortIndexInput;
3314        // Check if VP9 decoder advertises supported profiles.
3315        params.nProfileIndex = 0;
3316        status_t err = mOMXNode->getParameter(
3317                OMX_IndexParamVideoProfileLevelQuerySupported,
3318                &params, sizeof(params));
3319        mIsLegacyVP9Decoder = err != OK;
3320    }
3321
3322    err = setVideoPortFormatType(
3323            kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
3324
3325    if (err != OK) {
3326        return err;
3327    }
3328
3329    int32_t tmp;
3330    if (msg->findInt32("color-format", &tmp)) {
3331        OMX_COLOR_FORMATTYPE colorFormat =
3332            static_cast<OMX_COLOR_FORMATTYPE>(tmp);
3333        err = setVideoPortFormatType(
3334                kPortIndexOutput, OMX_VIDEO_CodingUnused, colorFormat, haveNativeWindow);
3335        if (err != OK) {
3336            ALOGW("[%s] does not support color format %d",
3337                  mComponentName.c_str(), colorFormat);
3338            err = setSupportedOutputFormat(!haveNativeWindow /* getLegacyFlexibleFormat */);
3339        }
3340    } else {
3341        err = setSupportedOutputFormat(!haveNativeWindow /* getLegacyFlexibleFormat */);
3342    }
3343
3344    if (err != OK) {
3345        return err;
3346    }
3347
3348    // Set the component input buffer number to be |tmp|. If succeed,
3349    // component will set input port buffer number to be |tmp|. If fail,
3350    // component will keep the same buffer number as before.
3351    if (msg->findInt32("android._num-input-buffers", &tmp)) {
3352        err = setPortBufferNum(kPortIndexInput, tmp);
3353        if (err != OK)
3354            return err;
3355    }
3356
3357    // Set the component output buffer number to be |tmp|. If succeed,
3358    // component will set output port buffer number to be |tmp|. If fail,
3359    // component will keep the same buffer number as before.
3360    if (msg->findInt32("android._num-output-buffers", &tmp)) {
3361        err = setPortBufferNum(kPortIndexOutput, tmp);
3362        if (err != OK)
3363            return err;
3364    }
3365
3366    int32_t frameRateInt;
3367    float frameRateFloat;
3368    if (!msg->findFloat("frame-rate", &frameRateFloat)) {
3369        if (!msg->findInt32("frame-rate", &frameRateInt)) {
3370            frameRateInt = -1;
3371        }
3372        frameRateFloat = (float)frameRateInt;
3373    }
3374
3375    err = setVideoFormatOnPort(
3376            kPortIndexInput, width, height, compressionFormat, frameRateFloat);
3377
3378    if (err != OK) {
3379        return err;
3380    }
3381
3382    err = setVideoFormatOnPort(
3383            kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused);
3384
3385    if (err != OK) {
3386        return err;
3387    }
3388
3389    err = setColorAspectsForVideoDecoder(
3390            width, height, haveNativeWindow | usingSwRenderer, msg, outputFormat);
3391    if (err == ERROR_UNSUPPORTED) { // support is optional
3392        err = OK;
3393    }
3394
3395    if (err != OK) {
3396        return err;
3397    }
3398
3399    err = setHDRStaticInfoForVideoCodec(kPortIndexOutput, msg, outputFormat);
3400    if (err == ERROR_UNSUPPORTED) { // support is optional
3401        err = OK;
3402    }
3403    return err;
3404}
3405
3406status_t ACodec::initDescribeColorAspectsIndex() {
3407    status_t err = mOMXNode->getExtensionIndex(
3408            "OMX.google.android.index.describeColorAspects", &mDescribeColorAspectsIndex);
3409    if (err != OK) {
3410        mDescribeColorAspectsIndex = (OMX_INDEXTYPE)0;
3411    }
3412    return err;
3413}
3414
3415status_t ACodec::setCodecColorAspects(DescribeColorAspectsParams &params, bool verify) {
3416    status_t err = ERROR_UNSUPPORTED;
3417    if (mDescribeColorAspectsIndex) {
3418        err = mOMXNode->setConfig(mDescribeColorAspectsIndex, &params, sizeof(params));
3419    }
3420    ALOGV("[%s] setting color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) err=%d(%s)",
3421            mComponentName.c_str(),
3422            params.sAspects.mRange, asString(params.sAspects.mRange),
3423            params.sAspects.mPrimaries, asString(params.sAspects.mPrimaries),
3424            params.sAspects.mMatrixCoeffs, asString(params.sAspects.mMatrixCoeffs),
3425            params.sAspects.mTransfer, asString(params.sAspects.mTransfer),
3426            err, asString(err));
3427
3428    if (verify && err == OK) {
3429        err = getCodecColorAspects(params);
3430    }
3431
3432    ALOGW_IF(err == ERROR_UNSUPPORTED && mDescribeColorAspectsIndex,
3433            "[%s] setting color aspects failed even though codec advertises support",
3434            mComponentName.c_str());
3435    return err;
3436}
3437
3438status_t ACodec::setColorAspectsForVideoDecoder(
3439        int32_t width, int32_t height, bool usingNativeWindow,
3440        const sp<AMessage> &configFormat, sp<AMessage> &outputFormat) {
3441    DescribeColorAspectsParams params;
3442    InitOMXParams(&params);
3443    params.nPortIndex = kPortIndexOutput;
3444
3445    getColorAspectsFromFormat(configFormat, params.sAspects);
3446    if (usingNativeWindow) {
3447        setDefaultCodecColorAspectsIfNeeded(params.sAspects, width, height);
3448        // The default aspects will be set back to the output format during the
3449        // getFormat phase of configure(). Set non-Unspecified values back into the
3450        // format, in case component does not support this enumeration.
3451        setColorAspectsIntoFormat(params.sAspects, outputFormat);
3452    }
3453
3454    (void)initDescribeColorAspectsIndex();
3455
3456    // communicate color aspects to codec
3457    return setCodecColorAspects(params);
3458}
3459
3460status_t ACodec::getCodecColorAspects(DescribeColorAspectsParams &params) {
3461    status_t err = ERROR_UNSUPPORTED;
3462    if (mDescribeColorAspectsIndex) {
3463        err = mOMXNode->getConfig(mDescribeColorAspectsIndex, &params, sizeof(params));
3464    }
3465    ALOGV("[%s] got color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) err=%d(%s)",
3466            mComponentName.c_str(),
3467            params.sAspects.mRange, asString(params.sAspects.mRange),
3468            params.sAspects.mPrimaries, asString(params.sAspects.mPrimaries),
3469            params.sAspects.mMatrixCoeffs, asString(params.sAspects.mMatrixCoeffs),
3470            params.sAspects.mTransfer, asString(params.sAspects.mTransfer),
3471            err, asString(err));
3472    if (params.bRequestingDataSpace) {
3473        ALOGV("for dataspace %#x", params.nDataSpace);
3474    }
3475    if (err == ERROR_UNSUPPORTED && mDescribeColorAspectsIndex
3476            && !params.bRequestingDataSpace && !params.bDataSpaceChanged) {
3477        ALOGW("[%s] getting color aspects failed even though codec advertises support",
3478                mComponentName.c_str());
3479    }
3480    return err;
3481}
3482
3483status_t ACodec::getInputColorAspectsForVideoEncoder(sp<AMessage> &format) {
3484    DescribeColorAspectsParams params;
3485    InitOMXParams(&params);
3486    params.nPortIndex = kPortIndexInput;
3487    status_t err = getCodecColorAspects(params);
3488    if (err == OK) {
3489        // we only set encoder input aspects if codec supports them
3490        setColorAspectsIntoFormat(params.sAspects, format, true /* force */);
3491    }
3492    return err;
3493}
3494
3495status_t ACodec::getDataSpace(
3496        DescribeColorAspectsParams &params, android_dataspace *dataSpace /* nonnull */,
3497        bool tryCodec) {
3498    status_t err = OK;
3499    if (tryCodec) {
3500        // request dataspace guidance from codec.
3501        params.bRequestingDataSpace = OMX_TRUE;
3502        err = getCodecColorAspects(params);
3503        params.bRequestingDataSpace = OMX_FALSE;
3504        if (err == OK && params.nDataSpace != HAL_DATASPACE_UNKNOWN) {
3505            *dataSpace = (android_dataspace)params.nDataSpace;
3506            return err;
3507        } else if (err == ERROR_UNSUPPORTED) {
3508            // ignore not-implemented error for dataspace requests
3509            err = OK;
3510        }
3511    }
3512
3513    // this returns legacy versions if available
3514    *dataSpace = getDataSpaceForColorAspects(params.sAspects, true /* mayexpand */);
3515    ALOGV("[%s] using color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) "
3516          "and dataspace %#x",
3517            mComponentName.c_str(),
3518            params.sAspects.mRange, asString(params.sAspects.mRange),
3519            params.sAspects.mPrimaries, asString(params.sAspects.mPrimaries),
3520            params.sAspects.mMatrixCoeffs, asString(params.sAspects.mMatrixCoeffs),
3521            params.sAspects.mTransfer, asString(params.sAspects.mTransfer),
3522            *dataSpace);
3523    return err;
3524}
3525
3526
3527status_t ACodec::getColorAspectsAndDataSpaceForVideoDecoder(
3528        int32_t width, int32_t height, const sp<AMessage> &configFormat, sp<AMessage> &outputFormat,
3529        android_dataspace *dataSpace) {
3530    DescribeColorAspectsParams params;
3531    InitOMXParams(&params);
3532    params.nPortIndex = kPortIndexOutput;
3533
3534    // reset default format and get resulting format
3535    getColorAspectsFromFormat(configFormat, params.sAspects);
3536    if (dataSpace != NULL) {
3537        setDefaultCodecColorAspectsIfNeeded(params.sAspects, width, height);
3538    }
3539    status_t err = setCodecColorAspects(params, true /* readBack */);
3540
3541    // we always set specified aspects for decoders
3542    setColorAspectsIntoFormat(params.sAspects, outputFormat);
3543
3544    if (dataSpace != NULL) {
3545        status_t res = getDataSpace(params, dataSpace, err == OK /* tryCodec */);
3546        if (err == OK) {
3547            err = res;
3548        }
3549    }
3550
3551    return err;
3552}
3553
3554// initial video encoder setup for bytebuffer mode
3555status_t ACodec::setColorAspectsForVideoEncoder(
3556        const sp<AMessage> &configFormat, sp<AMessage> &outputFormat, sp<AMessage> &inputFormat) {
3557    // copy config to output format as this is not exposed via getFormat
3558    copyColorConfig(configFormat, outputFormat);
3559
3560    DescribeColorAspectsParams params;
3561    InitOMXParams(&params);
3562    params.nPortIndex = kPortIndexInput;
3563    getColorAspectsFromFormat(configFormat, params.sAspects);
3564
3565    (void)initDescribeColorAspectsIndex();
3566
3567    int32_t usingRecorder;
3568    if (configFormat->findInt32("android._using-recorder", &usingRecorder) && usingRecorder) {
3569        android_dataspace dataSpace = HAL_DATASPACE_BT709;
3570        int32_t width, height;
3571        if (configFormat->findInt32("width", &width)
3572                && configFormat->findInt32("height", &height)) {
3573            setDefaultCodecColorAspectsIfNeeded(params.sAspects, width, height);
3574            status_t err = getDataSpace(
3575                    params, &dataSpace, mDescribeColorAspectsIndex /* tryCodec */);
3576            if (err != OK) {
3577                return err;
3578            }
3579            setColorAspectsIntoFormat(params.sAspects, outputFormat);
3580        }
3581        inputFormat->setInt32("android._dataspace", (int32_t)dataSpace);
3582    }
3583
3584    // communicate color aspects to codec, but do not allow change of the platform aspects
3585    ColorAspects origAspects = params.sAspects;
3586    for (int triesLeft = 2; --triesLeft >= 0; ) {
3587        status_t err = setCodecColorAspects(params, true /* readBack */);
3588        if (err != OK
3589                || !ColorUtils::checkIfAspectsChangedAndUnspecifyThem(
3590                        params.sAspects, origAspects, true /* usePlatformAspects */)) {
3591            return err;
3592        }
3593        ALOGW_IF(triesLeft == 0, "[%s] Codec repeatedly changed requested ColorAspects.",
3594                mComponentName.c_str());
3595    }
3596    return OK;
3597}
3598
3599status_t ACodec::setHDRStaticInfoForVideoCodec(
3600        OMX_U32 portIndex, const sp<AMessage> &configFormat, sp<AMessage> &outputFormat) {
3601    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
3602
3603    DescribeHDRStaticInfoParams params;
3604    InitOMXParams(&params);
3605    params.nPortIndex = portIndex;
3606
3607    HDRStaticInfo *info = &params.sInfo;
3608    if (getHDRStaticInfoFromFormat(configFormat, info)) {
3609        setHDRStaticInfoIntoFormat(params.sInfo, outputFormat);
3610    }
3611
3612    (void)initDescribeHDRStaticInfoIndex();
3613
3614    // communicate HDR static Info to codec
3615    return setHDRStaticInfo(params);
3616}
3617
3618// subsequent initial video encoder setup for surface mode
3619status_t ACodec::setInitialColorAspectsForVideoEncoderSurfaceAndGetDataSpace(
3620        android_dataspace *dataSpace /* nonnull */) {
3621    DescribeColorAspectsParams params;
3622    InitOMXParams(&params);
3623    params.nPortIndex = kPortIndexInput;
3624    ColorAspects &aspects = params.sAspects;
3625
3626    // reset default format and store resulting format into both input and output formats
3627    getColorAspectsFromFormat(mConfigFormat, aspects);
3628    int32_t width, height;
3629    if (mInputFormat->findInt32("width", &width) && mInputFormat->findInt32("height", &height)) {
3630        setDefaultCodecColorAspectsIfNeeded(aspects, width, height);
3631    }
3632    setColorAspectsIntoFormat(aspects, mInputFormat);
3633    setColorAspectsIntoFormat(aspects, mOutputFormat);
3634
3635    // communicate color aspects to codec, but do not allow any change
3636    ColorAspects origAspects = aspects;
3637    status_t err = OK;
3638    for (int triesLeft = 2; mDescribeColorAspectsIndex && --triesLeft >= 0; ) {
3639        status_t err = setCodecColorAspects(params, true /* readBack */);
3640        if (err != OK || !ColorUtils::checkIfAspectsChangedAndUnspecifyThem(aspects, origAspects)) {
3641            break;
3642        }
3643        ALOGW_IF(triesLeft == 0, "[%s] Codec repeatedly changed requested ColorAspects.",
3644                mComponentName.c_str());
3645    }
3646
3647    *dataSpace = HAL_DATASPACE_BT709;
3648    aspects = origAspects; // restore desired color aspects
3649    status_t res = getDataSpace(
3650            params, dataSpace, err == OK && mDescribeColorAspectsIndex /* tryCodec */);
3651    if (err == OK) {
3652        err = res;
3653    }
3654    mInputFormat->setInt32("android._dataspace", (int32_t)*dataSpace);
3655    mInputFormat->setBuffer(
3656            "android._color-aspects", ABuffer::CreateAsCopy(&aspects, sizeof(aspects)));
3657
3658    // update input format with codec supported color aspects (basically set unsupported
3659    // aspects to Unspecified)
3660    if (err == OK) {
3661        (void)getInputColorAspectsForVideoEncoder(mInputFormat);
3662    }
3663
3664    ALOGV("set default color aspects, updated input format to %s, output format to %s",
3665            mInputFormat->debugString(4).c_str(), mOutputFormat->debugString(4).c_str());
3666
3667    return err;
3668}
3669
3670status_t ACodec::getHDRStaticInfoForVideoCodec(OMX_U32 portIndex, sp<AMessage> &format) {
3671    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
3672    DescribeHDRStaticInfoParams params;
3673    InitOMXParams(&params);
3674    params.nPortIndex = portIndex;
3675
3676    status_t err = getHDRStaticInfo(params);
3677    if (err == OK) {
3678        // we only set decodec output HDRStaticInfo if codec supports them
3679        setHDRStaticInfoIntoFormat(params.sInfo, format);
3680    }
3681    return err;
3682}
3683
3684status_t ACodec::initDescribeHDRStaticInfoIndex() {
3685    status_t err = mOMXNode->getExtensionIndex(
3686            "OMX.google.android.index.describeHDRStaticInfo", &mDescribeHDRStaticInfoIndex);
3687    if (err != OK) {
3688        mDescribeHDRStaticInfoIndex = (OMX_INDEXTYPE)0;
3689    }
3690    return err;
3691}
3692
3693status_t ACodec::setHDRStaticInfo(const DescribeHDRStaticInfoParams &params) {
3694    status_t err = ERROR_UNSUPPORTED;
3695    if (mDescribeHDRStaticInfoIndex) {
3696        err = mOMXNode->setConfig(mDescribeHDRStaticInfoIndex, &params, sizeof(params));
3697    }
3698
3699    const HDRStaticInfo *info = &params.sInfo;
3700    ALOGV("[%s] setting  HDRStaticInfo (R: %u %u, G: %u %u, B: %u, %u, W: %u, %u, "
3701            "MaxDispL: %u, MinDispL: %u, MaxContentL: %u, MaxFrameAvgL: %u)",
3702            mComponentName.c_str(),
3703            info->sType1.mR.x, info->sType1.mR.y, info->sType1.mG.x, info->sType1.mG.y,
3704            info->sType1.mB.x, info->sType1.mB.y, info->sType1.mW.x, info->sType1.mW.y,
3705            info->sType1.mMaxDisplayLuminance, info->sType1.mMinDisplayLuminance,
3706            info->sType1.mMaxContentLightLevel, info->sType1.mMaxFrameAverageLightLevel);
3707
3708    ALOGW_IF(err == ERROR_UNSUPPORTED && mDescribeHDRStaticInfoIndex,
3709            "[%s] setting HDRStaticInfo failed even though codec advertises support",
3710            mComponentName.c_str());
3711    return err;
3712}
3713
3714status_t ACodec::getHDRStaticInfo(DescribeHDRStaticInfoParams &params) {
3715    status_t err = ERROR_UNSUPPORTED;
3716    if (mDescribeHDRStaticInfoIndex) {
3717        err = mOMXNode->getConfig(mDescribeHDRStaticInfoIndex, &params, sizeof(params));
3718    }
3719
3720    ALOGW_IF(err == ERROR_UNSUPPORTED && mDescribeHDRStaticInfoIndex,
3721            "[%s] getting HDRStaticInfo failed even though codec advertises support",
3722            mComponentName.c_str());
3723    return err;
3724}
3725
3726status_t ACodec::setupVideoEncoder(
3727        const char *mime, const sp<AMessage> &msg,
3728        sp<AMessage> &outputFormat, sp<AMessage> &inputFormat) {
3729    int32_t tmp;
3730    if (!msg->findInt32("color-format", &tmp)) {
3731        return INVALID_OPERATION;
3732    }
3733
3734    OMX_COLOR_FORMATTYPE colorFormat =
3735        static_cast<OMX_COLOR_FORMATTYPE>(tmp);
3736
3737    status_t err = setVideoPortFormatType(
3738            kPortIndexInput, OMX_VIDEO_CodingUnused, colorFormat);
3739
3740    if (err != OK) {
3741        ALOGE("[%s] does not support color format %d",
3742              mComponentName.c_str(), colorFormat);
3743
3744        return err;
3745    }
3746
3747    /* Input port configuration */
3748
3749    OMX_PARAM_PORTDEFINITIONTYPE def;
3750    InitOMXParams(&def);
3751
3752    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
3753
3754    def.nPortIndex = kPortIndexInput;
3755
3756    err = mOMXNode->getParameter(
3757            OMX_IndexParamPortDefinition, &def, sizeof(def));
3758
3759    if (err != OK) {
3760        return err;
3761    }
3762
3763    OMX_VIDEO_CONTROLRATETYPE bitrateMode;
3764    int32_t width, height, bitrate = 0, quality;
3765    if (!msg->findInt32("width", &width)
3766            || !msg->findInt32("height", &height)
3767            || !findVideoBitrateControlInfo(
3768                    msg, &bitrateMode, &bitrate, &quality)) {
3769        return INVALID_OPERATION;
3770    }
3771
3772    video_def->nFrameWidth = width;
3773    video_def->nFrameHeight = height;
3774
3775    int32_t stride;
3776    if (!msg->findInt32("stride", &stride)) {
3777        stride = width;
3778    }
3779
3780    video_def->nStride = stride;
3781
3782    int32_t sliceHeight;
3783    if (!msg->findInt32("slice-height", &sliceHeight)) {
3784        sliceHeight = height;
3785    }
3786
3787    video_def->nSliceHeight = sliceHeight;
3788
3789    def.nBufferSize = (video_def->nStride * video_def->nSliceHeight * 3) / 2;
3790
3791    float framerate;
3792    if (!msg->findFloat("frame-rate", &framerate)) {
3793        int32_t tmp;
3794        if (!msg->findInt32("frame-rate", &tmp)) {
3795            return INVALID_OPERATION;
3796        }
3797        mFps = (double)tmp;
3798    } else {
3799        mFps = (double)framerate;
3800    }
3801    // propagate framerate to the output so that the muxer has it
3802    outputFormat->setInt32("frame-rate", (int32_t)mFps);
3803
3804    video_def->xFramerate = (OMX_U32)(mFps * 65536);
3805    video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
3806    // this is redundant as it was already set up in setVideoPortFormatType
3807    // FIXME for now skip this only for flexible YUV formats
3808    if (colorFormat != OMX_COLOR_FormatYUV420Flexible) {
3809        video_def->eColorFormat = colorFormat;
3810    }
3811
3812    err = mOMXNode->setParameter(
3813            OMX_IndexParamPortDefinition, &def, sizeof(def));
3814
3815    if (err != OK) {
3816        ALOGE("[%s] failed to set input port definition parameters.",
3817              mComponentName.c_str());
3818
3819        return err;
3820    }
3821
3822    /* Output port configuration */
3823
3824    OMX_VIDEO_CODINGTYPE compressionFormat;
3825    err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
3826
3827    if (err != OK) {
3828        return err;
3829    }
3830
3831    err = setVideoPortFormatType(
3832            kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused);
3833
3834    if (err != OK) {
3835        ALOGE("[%s] does not support compression format %d",
3836             mComponentName.c_str(), compressionFormat);
3837
3838        return err;
3839    }
3840
3841    def.nPortIndex = kPortIndexOutput;
3842
3843    err = mOMXNode->getParameter(
3844            OMX_IndexParamPortDefinition, &def, sizeof(def));
3845
3846    if (err != OK) {
3847        return err;
3848    }
3849
3850    video_def->nFrameWidth = width;
3851    video_def->nFrameHeight = height;
3852    video_def->xFramerate = 0;
3853    video_def->nBitrate = bitrate;
3854    video_def->eCompressionFormat = compressionFormat;
3855    video_def->eColorFormat = OMX_COLOR_FormatUnused;
3856
3857    err = mOMXNode->setParameter(
3858            OMX_IndexParamPortDefinition, &def, sizeof(def));
3859
3860    if (err != OK) {
3861        ALOGE("[%s] failed to set output port definition parameters.",
3862              mComponentName.c_str());
3863
3864        return err;
3865    }
3866
3867    int32_t intraRefreshPeriod = 0;
3868    if (msg->findInt32("intra-refresh-period", &intraRefreshPeriod)
3869            && intraRefreshPeriod >= 0) {
3870        err = setIntraRefreshPeriod((uint32_t)intraRefreshPeriod, true);
3871        if (err != OK) {
3872            ALOGI("[%s] failed setIntraRefreshPeriod. Failure is fine since this key is optional",
3873                    mComponentName.c_str());
3874            err = OK;
3875        }
3876    }
3877
3878    configureEncoderLatency(msg);
3879
3880    switch (compressionFormat) {
3881        case OMX_VIDEO_CodingMPEG4:
3882            err = setupMPEG4EncoderParameters(msg);
3883            break;
3884
3885        case OMX_VIDEO_CodingH263:
3886            err = setupH263EncoderParameters(msg);
3887            break;
3888
3889        case OMX_VIDEO_CodingAVC:
3890            err = setupAVCEncoderParameters(msg);
3891            break;
3892
3893        case OMX_VIDEO_CodingHEVC:
3894        case OMX_VIDEO_CodingImageHEIC:
3895            err = setupHEVCEncoderParameters(msg, outputFormat);
3896            break;
3897
3898        case OMX_VIDEO_CodingVP8:
3899        case OMX_VIDEO_CodingVP9:
3900            err = setupVPXEncoderParameters(msg, outputFormat);
3901            break;
3902
3903        default:
3904            break;
3905    }
3906
3907    if (err != OK) {
3908        return err;
3909    }
3910
3911    // Set up color aspects on input, but propagate them to the output format, as they will
3912    // not be read back from encoder.
3913    err = setColorAspectsForVideoEncoder(msg, outputFormat, inputFormat);
3914    if (err == ERROR_UNSUPPORTED) {
3915        ALOGI("[%s] cannot encode color aspects. Ignoring.", mComponentName.c_str());
3916        err = OK;
3917    }
3918
3919    if (err != OK) {
3920        return err;
3921    }
3922
3923    err = setHDRStaticInfoForVideoCodec(kPortIndexInput, msg, outputFormat);
3924    if (err == ERROR_UNSUPPORTED) { // support is optional
3925        ALOGI("[%s] cannot encode HDR static metadata. Ignoring.", mComponentName.c_str());
3926        err = OK;
3927    }
3928
3929    if (err != OK) {
3930        return err;
3931    }
3932
3933    switch (compressionFormat) {
3934        case OMX_VIDEO_CodingAVC:
3935        case OMX_VIDEO_CodingHEVC:
3936            err = configureTemporalLayers(msg, true /* inConfigure */, outputFormat);
3937            if (err != OK) {
3938                err = OK; // ignore failure
3939            }
3940            break;
3941
3942        case OMX_VIDEO_CodingVP8:
3943        case OMX_VIDEO_CodingVP9:
3944            // TODO: do we need to support android.generic layering? webrtc layering is
3945            // already set up in setupVPXEncoderParameters.
3946            break;
3947
3948        default:
3949            break;
3950    }
3951
3952    if (err == OK) {
3953        ALOGI("setupVideoEncoder succeeded");
3954    }
3955
3956    return err;
3957}
3958
3959status_t ACodec::setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode) {
3960    OMX_VIDEO_PARAM_INTRAREFRESHTYPE params;
3961    InitOMXParams(&params);
3962    params.nPortIndex = kPortIndexOutput;
3963
3964    params.eRefreshMode = static_cast<OMX_VIDEO_INTRAREFRESHTYPE>(mode);
3965
3966    if (params.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic ||
3967            params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) {
3968        int32_t mbs;
3969        if (!msg->findInt32("intra-refresh-CIR-mbs", &mbs)) {
3970            return INVALID_OPERATION;
3971        }
3972        params.nCirMBs = mbs;
3973    }
3974
3975    if (params.eRefreshMode == OMX_VIDEO_IntraRefreshAdaptive ||
3976            params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) {
3977        int32_t mbs;
3978        if (!msg->findInt32("intra-refresh-AIR-mbs", &mbs)) {
3979            return INVALID_OPERATION;
3980        }
3981        params.nAirMBs = mbs;
3982
3983        int32_t ref;
3984        if (!msg->findInt32("intra-refresh-AIR-ref", &ref)) {
3985            return INVALID_OPERATION;
3986        }
3987        params.nAirRef = ref;
3988    }
3989
3990    status_t err = mOMXNode->setParameter(
3991            OMX_IndexParamVideoIntraRefresh, &params, sizeof(params));
3992    return err;
3993}
3994
3995static OMX_U32 setPFramesSpacing(
3996        float iFramesInterval /* seconds */, int32_t frameRate, uint32_t BFramesSpacing = 0) {
3997    // BFramesSpacing is the number of B frames between I/P frames
3998    // PFramesSpacing (the value to be returned) is the number of P frames between I frames
3999    //
4000    // keyFrameInterval = ((PFramesSpacing + 1) * BFramesSpacing) + PFramesSpacing + 1
4001    //                                     ^^^                            ^^^        ^^^
4002    //                              number of B frames                number of P    I frame
4003    //
4004    //                  = (PFramesSpacing + 1) * (BFramesSpacing + 1)
4005    //
4006    // E.g.
4007    //      I   P   I  : I-interval: 8, nPFrames 1, nBFrames 3
4008    //       BBB BBB
4009
4010    if (iFramesInterval < 0) { // just 1 key frame
4011        return 0xFFFFFFFE; // don't use maxint as key-frame-interval calculation will add 1
4012    } else if (iFramesInterval == 0) { // just key frames
4013        return 0;
4014    }
4015
4016    // round down as key-frame-interval is an upper limit
4017    uint32_t keyFrameInterval = uint32_t(frameRate * iFramesInterval);
4018    OMX_U32 ret = keyFrameInterval / (BFramesSpacing + 1);
4019    return ret > 0 ? ret - 1 : 0;
4020}
4021
4022status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) {
4023    int32_t bitrate;
4024    float iFrameInterval;
4025    if (!msg->findInt32("bitrate", &bitrate)
4026            || !msg->findAsFloat("i-frame-interval", &iFrameInterval)) {
4027        return INVALID_OPERATION;
4028    }
4029
4030    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getVideoBitrateMode(msg);
4031
4032    float frameRate;
4033    if (!msg->findFloat("frame-rate", &frameRate)) {
4034        int32_t tmp;
4035        if (!msg->findInt32("frame-rate", &tmp)) {
4036            return INVALID_OPERATION;
4037        }
4038        frameRate = (float)tmp;
4039    }
4040
4041    OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type;
4042    InitOMXParams(&mpeg4type);
4043    mpeg4type.nPortIndex = kPortIndexOutput;
4044
4045    status_t err = mOMXNode->getParameter(
4046            OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
4047
4048    if (err != OK) {
4049        return err;
4050    }
4051
4052    mpeg4type.nSliceHeaderSpacing = 0;
4053    mpeg4type.bSVH = OMX_FALSE;
4054    mpeg4type.bGov = OMX_FALSE;
4055
4056    mpeg4type.nAllowedPictureTypes =
4057        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
4058
4059    mpeg4type.nBFrames = 0;
4060    mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, mpeg4type.nBFrames);
4061    if (mpeg4type.nPFrames == 0) {
4062        mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
4063    }
4064    mpeg4type.nIDCVLCThreshold = 0;
4065    mpeg4type.bACPred = OMX_TRUE;
4066    mpeg4type.nMaxPacketSize = 256;
4067    mpeg4type.nTimeIncRes = 1000;
4068    mpeg4type.nHeaderExtension = 0;
4069    mpeg4type.bReversibleVLC = OMX_FALSE;
4070
4071    int32_t profile;
4072    if (msg->findInt32("profile", &profile)) {
4073        int32_t level;
4074        if (!msg->findInt32("level", &level)) {
4075            return INVALID_OPERATION;
4076        }
4077
4078        err = verifySupportForProfileAndLevel(kPortIndexOutput, profile, level);
4079
4080        if (err != OK) {
4081            return err;
4082        }
4083
4084        mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile);
4085        mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level);
4086    }
4087
4088    err = mOMXNode->setParameter(
4089            OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
4090
4091    if (err != OK) {
4092        return err;
4093    }
4094
4095    err = configureBitrate(bitrateMode, bitrate);
4096
4097    if (err != OK) {
4098        return err;
4099    }
4100
4101    return setupErrorCorrectionParameters();
4102}
4103
4104status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) {
4105    int32_t bitrate;
4106    float iFrameInterval;
4107    if (!msg->findInt32("bitrate", &bitrate)
4108            || !msg->findAsFloat("i-frame-interval", &iFrameInterval)) {
4109        return INVALID_OPERATION;
4110    }
4111
4112    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getVideoBitrateMode(msg);
4113
4114    float frameRate;
4115    if (!msg->findFloat("frame-rate", &frameRate)) {
4116        int32_t tmp;
4117        if (!msg->findInt32("frame-rate", &tmp)) {
4118            return INVALID_OPERATION;
4119        }
4120        frameRate = (float)tmp;
4121    }
4122
4123    OMX_VIDEO_PARAM_H263TYPE h263type;
4124    InitOMXParams(&h263type);
4125    h263type.nPortIndex = kPortIndexOutput;
4126
4127    status_t err = mOMXNode->getParameter(
4128            OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
4129
4130    if (err != OK) {
4131        return err;
4132    }
4133
4134    h263type.nAllowedPictureTypes =
4135        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
4136
4137    h263type.nBFrames = 0;
4138    h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, h263type.nBFrames);
4139    if (h263type.nPFrames == 0) {
4140        h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
4141    }
4142
4143    int32_t profile;
4144    if (msg->findInt32("profile", &profile)) {
4145        int32_t level;
4146        if (!msg->findInt32("level", &level)) {
4147            return INVALID_OPERATION;
4148        }
4149
4150        err = verifySupportForProfileAndLevel(kPortIndexOutput, profile, level);
4151
4152        if (err != OK) {
4153            return err;
4154        }
4155
4156        h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile);
4157        h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level);
4158    }
4159
4160    h263type.bPLUSPTYPEAllowed = OMX_FALSE;
4161    h263type.bForceRoundingTypeToZero = OMX_FALSE;
4162    h263type.nPictureHeaderRepetition = 0;
4163    h263type.nGOBHeaderInterval = 0;
4164
4165    err = mOMXNode->setParameter(
4166            OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
4167
4168    if (err != OK) {
4169        return err;
4170    }
4171
4172    err = configureBitrate(bitrateMode, bitrate);
4173
4174    if (err != OK) {
4175        return err;
4176    }
4177
4178    return setupErrorCorrectionParameters();
4179}
4180
4181// static
4182int /* OMX_VIDEO_AVCLEVELTYPE */ ACodec::getAVCLevelFor(
4183        int width, int height, int rate, int bitrate,
4184        OMX_VIDEO_AVCPROFILEEXTTYPE profile) {
4185    // convert bitrate to main/baseline profile kbps equivalent
4186    switch ((uint32_t)profile) {
4187        case OMX_VIDEO_AVCProfileHigh10:
4188            bitrate = divUp(bitrate, 3000); break;
4189        case OMX_VIDEO_AVCProfileConstrainedHigh:
4190        case OMX_VIDEO_AVCProfileHigh:
4191            bitrate = divUp(bitrate, 1250); break;
4192        default:
4193            bitrate = divUp(bitrate, 1000); break;
4194    }
4195
4196    // convert size and rate to MBs
4197    width = divUp(width, 16);
4198    height = divUp(height, 16);
4199    int mbs = width * height;
4200    rate *= mbs;
4201    int maxDimension = max(width, height);
4202
4203    static const int limits[][5] = {
4204        /*   MBps     MB   dim  bitrate        level */
4205        {    1485,    99,  28,     64, OMX_VIDEO_AVCLevel1  },
4206        {    1485,    99,  28,    128, OMX_VIDEO_AVCLevel1b },
4207        {    3000,   396,  56,    192, OMX_VIDEO_AVCLevel11 },
4208        {    6000,   396,  56,    384, OMX_VIDEO_AVCLevel12 },
4209        {   11880,   396,  56,    768, OMX_VIDEO_AVCLevel13 },
4210        {   11880,   396,  56,   2000, OMX_VIDEO_AVCLevel2  },
4211        {   19800,   792,  79,   4000, OMX_VIDEO_AVCLevel21 },
4212        {   20250,  1620, 113,   4000, OMX_VIDEO_AVCLevel22 },
4213        {   40500,  1620, 113,  10000, OMX_VIDEO_AVCLevel3  },
4214        {  108000,  3600, 169,  14000, OMX_VIDEO_AVCLevel31 },
4215        {  216000,  5120, 202,  20000, OMX_VIDEO_AVCLevel32 },
4216        {  245760,  8192, 256,  20000, OMX_VIDEO_AVCLevel4  },
4217        {  245760,  8192, 256,  50000, OMX_VIDEO_AVCLevel41 },
4218        {  522240,  8704, 263,  50000, OMX_VIDEO_AVCLevel42 },
4219        {  589824, 22080, 420, 135000, OMX_VIDEO_AVCLevel5  },
4220        {  983040, 36864, 543, 240000, OMX_VIDEO_AVCLevel51 },
4221        { 2073600, 36864, 543, 240000, OMX_VIDEO_AVCLevel52 },
4222    };
4223
4224    for (size_t i = 0; i < ARRAY_SIZE(limits); i++) {
4225        const int (&limit)[5] = limits[i];
4226        if (rate <= limit[0] && mbs <= limit[1] && maxDimension <= limit[2]
4227                && bitrate <= limit[3]) {
4228            return limit[4];
4229        }
4230    }
4231    return 0;
4232}
4233
4234status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) {
4235    int32_t bitrate;
4236    float iFrameInterval;
4237    if (!msg->findInt32("bitrate", &bitrate)
4238            || !msg->findAsFloat("i-frame-interval", &iFrameInterval)) {
4239        return INVALID_OPERATION;
4240    }
4241
4242    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getVideoBitrateMode(msg);
4243
4244    float frameRate;
4245    if (!msg->findFloat("frame-rate", &frameRate)) {
4246        int32_t tmp;
4247        if (!msg->findInt32("frame-rate", &tmp)) {
4248            return INVALID_OPERATION;
4249        }
4250        frameRate = (float)tmp;
4251    }
4252
4253    status_t err = OK;
4254    int32_t intraRefreshMode = 0;
4255    if (msg->findInt32("intra-refresh-mode", &intraRefreshMode)) {
4256        err = setCyclicIntraMacroblockRefresh(msg, intraRefreshMode);
4257        if (err != OK) {
4258            ALOGE("Setting intra macroblock refresh mode (%d) failed: 0x%x",
4259                    err, intraRefreshMode);
4260            return err;
4261        }
4262    }
4263
4264    OMX_VIDEO_PARAM_AVCTYPE h264type;
4265    InitOMXParams(&h264type);
4266    h264type.nPortIndex = kPortIndexOutput;
4267
4268    err = mOMXNode->getParameter(
4269            OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
4270
4271    if (err != OK) {
4272        return err;
4273    }
4274
4275    h264type.nAllowedPictureTypes =
4276        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
4277
4278    int32_t profile;
4279    if (msg->findInt32("profile", &profile)) {
4280        int32_t level;
4281        if (!msg->findInt32("level", &level)) {
4282            return INVALID_OPERATION;
4283        }
4284
4285        err = verifySupportForProfileAndLevel(kPortIndexOutput, profile, level);
4286
4287        if (err != OK) {
4288            return err;
4289        }
4290
4291        h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile);
4292        h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level);
4293    } else {
4294        h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
4295#if 0   /* DON'T YET DEFAULT TO HIGHEST PROFILE */
4296        // Use largest supported profile for AVC recording if profile is not specified.
4297        for (OMX_VIDEO_AVCPROFILETYPE profile : {
4298                OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCProfileMain }) {
4299            if (verifySupportForProfileAndLevel(kPortIndexOutput, profile, 0) == OK) {
4300                h264type.eProfile = profile;
4301                break;
4302            }
4303        }
4304#endif
4305    }
4306
4307    ALOGI("setupAVCEncoderParameters with [profile: %s] [level: %s]",
4308            asString(h264type.eProfile), asString(h264type.eLevel));
4309
4310    if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
4311        h264type.nSliceHeaderSpacing = 0;
4312        h264type.bUseHadamard = OMX_TRUE;
4313        h264type.nRefFrames = 1;
4314        h264type.nBFrames = 0;
4315        h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, h264type.nBFrames);
4316        if (h264type.nPFrames == 0) {
4317            h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
4318        }
4319        h264type.nRefIdx10ActiveMinus1 = 0;
4320        h264type.nRefIdx11ActiveMinus1 = 0;
4321        h264type.bEntropyCodingCABAC = OMX_FALSE;
4322        h264type.bWeightedPPrediction = OMX_FALSE;
4323        h264type.bconstIpred = OMX_FALSE;
4324        h264type.bDirect8x8Inference = OMX_FALSE;
4325        h264type.bDirectSpatialTemporal = OMX_FALSE;
4326        h264type.nCabacInitIdc = 0;
4327    } else if (h264type.eProfile == OMX_VIDEO_AVCProfileMain ||
4328            h264type.eProfile == OMX_VIDEO_AVCProfileHigh) {
4329        h264type.nSliceHeaderSpacing = 0;
4330        h264type.bUseHadamard = OMX_TRUE;
4331        h264type.nRefFrames = 2;
4332        h264type.nBFrames = mLatency == 0 ? 1 : std::min(1U, mLatency - 1);
4333
4334        // disable B-frames until MPEG4Writer can guarantee finalizing files with B-frames
4335        h264type.nRefFrames = 1;
4336        h264type.nBFrames = 0;
4337
4338        h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, h264type.nBFrames);
4339        h264type.nAllowedPictureTypes =
4340            OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
4341        h264type.nRefIdx10ActiveMinus1 = 0;
4342        h264type.nRefIdx11ActiveMinus1 = 0;
4343        h264type.bEntropyCodingCABAC = OMX_TRUE;
4344        h264type.bWeightedPPrediction = OMX_TRUE;
4345        h264type.bconstIpred = OMX_TRUE;
4346        h264type.bDirect8x8Inference = OMX_TRUE;
4347        h264type.bDirectSpatialTemporal = OMX_TRUE;
4348        h264type.nCabacInitIdc = 1;
4349    }
4350
4351    if (h264type.nBFrames != 0) {
4352        h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
4353    }
4354
4355    h264type.bEnableUEP = OMX_FALSE;
4356    h264type.bEnableFMO = OMX_FALSE;
4357    h264type.bEnableASO = OMX_FALSE;
4358    h264type.bEnableRS = OMX_FALSE;
4359    h264type.bFrameMBsOnly = OMX_TRUE;
4360    h264type.bMBAFF = OMX_FALSE;
4361    h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
4362
4363    err = mOMXNode->setParameter(
4364            OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
4365
4366    if (err != OK) {
4367        return err;
4368    }
4369
4370    // TRICKY: if we are enabling temporal layering as well, some codecs may not support layering
4371    // when B-frames are enabled. Detect this now so we can disable B frames if temporal layering
4372    // is preferred.
4373    AString tsSchema;
4374    int32_t preferBFrames = (int32_t)false;
4375    if (msg->findString("ts-schema", &tsSchema)
4376            && (!msg->findInt32("android._prefer-b-frames", &preferBFrames) || !preferBFrames)) {
4377        OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE layering;
4378        InitOMXParams(&layering);
4379        layering.nPortIndex = kPortIndexOutput;
4380        if (mOMXNode->getParameter(
4381                        (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering,
4382                        &layering, sizeof(layering)) == OK
4383                && layering.eSupportedPatterns
4384                && layering.nBLayerCountMax == 0) {
4385            h264type.nBFrames = 0;
4386            h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, h264type.nBFrames);
4387            h264type.nAllowedPictureTypes &= ~OMX_VIDEO_PictureTypeB;
4388            ALOGI("disabling B-frames");
4389            err = mOMXNode->setParameter(
4390                    OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
4391
4392            if (err != OK) {
4393                return err;
4394            }
4395        }
4396    }
4397
4398    return configureBitrate(bitrateMode, bitrate);
4399}
4400
4401status_t ACodec::configureImageGrid(
4402        const sp<AMessage> &msg, sp<AMessage> &outputFormat) {
4403    int32_t tileWidth, tileHeight, gridRows, gridCols;
4404    if (!msg->findInt32("tile-width", &tileWidth) ||
4405        !msg->findInt32("tile-height", &tileHeight) ||
4406        !msg->findInt32("grid-rows", &gridRows) ||
4407        !msg->findInt32("grid-cols", &gridCols)) {
4408        return OK;
4409    }
4410
4411    OMX_VIDEO_PARAM_ANDROID_IMAGEGRIDTYPE gridType;
4412    InitOMXParams(&gridType);
4413    gridType.nPortIndex = kPortIndexOutput;
4414    gridType.bEnabled = OMX_TRUE;
4415    gridType.nTileWidth = tileWidth;
4416    gridType.nTileHeight = tileHeight;
4417    gridType.nGridRows = gridRows;
4418    gridType.nGridCols = gridCols;
4419
4420    status_t err = mOMXNode->setParameter(
4421            (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidImageGrid,
4422            &gridType, sizeof(gridType));
4423
4424    // for video encoders, grid config is only a hint.
4425    if (!mIsImage) {
4426        return OK;
4427    }
4428
4429    // image encoders must support grid config.
4430    if (err != OK) {
4431        return err;
4432    }
4433
4434    // query to get the image encoder's real grid config as it might be
4435    // different from the requested, and transfer that to the output.
4436    err = mOMXNode->getParameter(
4437            (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidImageGrid,
4438            &gridType, sizeof(gridType));
4439
4440    if (err == OK && gridType.bEnabled) {
4441        outputFormat->setInt32("tile-width", gridType.nTileWidth);
4442        outputFormat->setInt32("tile-height", gridType.nTileHeight);
4443        outputFormat->setInt32("grid-rows", gridType.nGridRows);
4444        outputFormat->setInt32("grid-cols", gridType.nGridCols);
4445    }
4446
4447    return err;
4448}
4449
4450status_t ACodec::setupHEVCEncoderParameters(
4451        const sp<AMessage> &msg, sp<AMessage> &outputFormat) {
4452    OMX_VIDEO_CONTROLRATETYPE bitrateMode;
4453    int32_t bitrate, quality;
4454    if (!findVideoBitrateControlInfo(msg, &bitrateMode, &bitrate, &quality)) {
4455        return INVALID_OPERATION;
4456    }
4457
4458    OMX_VIDEO_PARAM_HEVCTYPE hevcType;
4459    InitOMXParams(&hevcType);
4460    hevcType.nPortIndex = kPortIndexOutput;
4461
4462    status_t err = OK;
4463    err = mOMXNode->getParameter(
4464            (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
4465    if (err != OK) {
4466        return err;
4467    }
4468
4469    int32_t profile;
4470    if (msg->findInt32("profile", &profile)) {
4471        int32_t level;
4472        if (!msg->findInt32("level", &level)) {
4473            return INVALID_OPERATION;
4474        }
4475
4476        err = verifySupportForProfileAndLevel(kPortIndexOutput, profile, level);
4477        if (err != OK) {
4478            return err;
4479        }
4480
4481        hevcType.eProfile = static_cast<OMX_VIDEO_HEVCPROFILETYPE>(profile);
4482        hevcType.eLevel = static_cast<OMX_VIDEO_HEVCLEVELTYPE>(level);
4483    }
4484    // TODO: finer control?
4485    if (mIsImage) {
4486        hevcType.nKeyFrameInterval = 1;
4487    } else {
4488        float iFrameInterval;
4489        if (!msg->findAsFloat("i-frame-interval", &iFrameInterval)) {
4490            return INVALID_OPERATION;
4491        }
4492
4493        float frameRate;
4494        if (!msg->findFloat("frame-rate", &frameRate)) {
4495            int32_t tmp;
4496            if (!msg->findInt32("frame-rate", &tmp)) {
4497                return INVALID_OPERATION;
4498            }
4499            frameRate = (float)tmp;
4500        }
4501
4502        hevcType.nKeyFrameInterval =
4503                setPFramesSpacing(iFrameInterval, frameRate) + 1;
4504    }
4505
4506
4507    err = mOMXNode->setParameter(
4508            (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
4509    if (err != OK) {
4510        return err;
4511    }
4512
4513    err = configureImageGrid(msg, outputFormat);
4514
4515    if (err != OK) {
4516        return err;
4517    }
4518
4519    return configureBitrate(bitrateMode, bitrate, quality);
4520}
4521
4522status_t ACodec::setupVPXEncoderParameters(const sp<AMessage> &msg, sp<AMessage> &outputFormat) {
4523    int32_t bitrate;
4524    float iFrameInterval = 0;
4525    size_t tsLayers = 0;
4526    OMX_VIDEO_ANDROID_VPXTEMPORALLAYERPATTERNTYPE pattern =
4527        OMX_VIDEO_VPXTemporalLayerPatternNone;
4528    static const uint32_t kVp8LayerRateAlloction
4529        [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS]
4530        [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS] = {
4531        {100, 100, 100},  // 1 layer
4532        { 60, 100, 100},  // 2 layers {60%, 40%}
4533        { 40,  60, 100},  // 3 layers {40%, 20%, 40%}
4534    };
4535    if (!msg->findInt32("bitrate", &bitrate)) {
4536        return INVALID_OPERATION;
4537    }
4538    msg->findAsFloat("i-frame-interval", &iFrameInterval);
4539
4540    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getVideoBitrateMode(msg);
4541
4542    float frameRate;
4543    if (!msg->findFloat("frame-rate", &frameRate)) {
4544        int32_t tmp;
4545        if (!msg->findInt32("frame-rate", &tmp)) {
4546            return INVALID_OPERATION;
4547        }
4548        frameRate = (float)tmp;
4549    }
4550
4551    AString tsSchema;
4552    OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE tsType =
4553        OMX_VIDEO_AndroidTemporalLayeringPatternNone;
4554
4555    if (msg->findString("ts-schema", &tsSchema)) {
4556        unsigned int numLayers = 0;
4557        unsigned int numBLayers = 0;
4558        int tags;
4559        char dummy;
4560        if (sscanf(tsSchema.c_str(), "webrtc.vp8.%u-layer%c", &numLayers, &dummy) == 1
4561                && numLayers > 0) {
4562            pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
4563            tsType = OMX_VIDEO_AndroidTemporalLayeringPatternWebRTC;
4564            tsLayers = numLayers;
4565        } else if ((tags = sscanf(tsSchema.c_str(), "android.generic.%u%c%u%c",
4566                        &numLayers, &dummy, &numBLayers, &dummy))
4567                && (tags == 1 || (tags == 3 && dummy == '+'))
4568                && numLayers > 0 && numLayers < UINT32_MAX - numBLayers) {
4569            pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
4570            // VPX does not have a concept of B-frames, so just count all layers
4571            tsType = OMX_VIDEO_AndroidTemporalLayeringPatternAndroid;
4572            tsLayers = numLayers + numBLayers;
4573        } else {
4574            ALOGW("Ignoring unsupported ts-schema [%s]", tsSchema.c_str());
4575        }
4576        tsLayers = min(tsLayers, (size_t)OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS);
4577    }
4578
4579    OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type;
4580    InitOMXParams(&vp8type);
4581    vp8type.nPortIndex = kPortIndexOutput;
4582    status_t err = mOMXNode->getParameter(
4583            (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
4584            &vp8type, sizeof(vp8type));
4585
4586    if (err == OK) {
4587        if (iFrameInterval > 0) {
4588            vp8type.nKeyFrameInterval = setPFramesSpacing(iFrameInterval, frameRate) + 1;
4589        }
4590        vp8type.eTemporalPattern = pattern;
4591        vp8type.nTemporalLayerCount = tsLayers;
4592        if (tsLayers > 0) {
4593            for (size_t i = 0; i < OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS; i++) {
4594                vp8type.nTemporalLayerBitrateRatio[i] =
4595                    kVp8LayerRateAlloction[tsLayers - 1][i];
4596            }
4597        }
4598        if (bitrateMode == OMX_Video_ControlRateConstant) {
4599            vp8type.nMinQuantizer = 2;
4600            vp8type.nMaxQuantizer = 63;
4601        }
4602
4603        err = mOMXNode->setParameter(
4604                (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
4605                &vp8type, sizeof(vp8type));
4606        if (err != OK) {
4607            ALOGW("Extended VP8 parameters set failed: %d", err);
4608        } else if (tsType == OMX_VIDEO_AndroidTemporalLayeringPatternWebRTC) {
4609            // advertise even single layer WebRTC layering, as it is defined
4610            outputFormat->setString("ts-schema", AStringPrintf("webrtc.vp8.%u-layer", tsLayers));
4611        } else if (tsLayers > 0) {
4612            // tsType == OMX_VIDEO_AndroidTemporalLayeringPatternAndroid
4613            outputFormat->setString("ts-schema", AStringPrintf("android.generic.%u", tsLayers));
4614        }
4615    }
4616
4617    return configureBitrate(bitrateMode, bitrate);
4618}
4619
4620status_t ACodec::verifySupportForProfileAndLevel(
4621        OMX_U32 portIndex, int32_t profile, int32_t level) {
4622    OMX_VIDEO_PARAM_PROFILELEVELTYPE params;
4623    InitOMXParams(&params);
4624    params.nPortIndex = portIndex;
4625
4626    for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
4627        params.nProfileIndex = index;
4628        status_t err = mOMXNode->getParameter(
4629                OMX_IndexParamVideoProfileLevelQuerySupported,
4630                &params, sizeof(params));
4631
4632        if (err != OK) {
4633            return err;
4634        }
4635
4636        int32_t supportedProfile = static_cast<int32_t>(params.eProfile);
4637        int32_t supportedLevel = static_cast<int32_t>(params.eLevel);
4638
4639        if (profile == supportedProfile && level <= supportedLevel) {
4640            return OK;
4641        }
4642
4643        if (index == kMaxIndicesToCheck) {
4644            ALOGW("[%s] stopping checking profiles after %u: %x/%x",
4645                    mComponentName.c_str(), index,
4646                    params.eProfile, params.eLevel);
4647        }
4648    }
4649    return ERROR_UNSUPPORTED;
4650}
4651
4652status_t ACodec::configureBitrate(
4653        OMX_VIDEO_CONTROLRATETYPE bitrateMode, int32_t bitrate, int32_t quality) {
4654    OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
4655    InitOMXParams(&bitrateType);
4656    bitrateType.nPortIndex = kPortIndexOutput;
4657
4658    status_t err = mOMXNode->getParameter(
4659            OMX_IndexParamVideoBitrate, &bitrateType, sizeof(bitrateType));
4660
4661    if (err != OK) {
4662        return err;
4663    }
4664
4665    bitrateType.eControlRate = bitrateMode;
4666
4667    // write it out explicitly even if it's a union
4668    if (bitrateMode == OMX_Video_ControlRateConstantQuality) {
4669        bitrateType.nQualityFactor = quality;
4670    } else {
4671        bitrateType.nTargetBitrate = bitrate;
4672    }
4673
4674    return mOMXNode->setParameter(
4675            OMX_IndexParamVideoBitrate, &bitrateType, sizeof(bitrateType));
4676}
4677
4678void ACodec::configureEncoderLatency(const sp<AMessage> &msg) {
4679    if (!mIsEncoder || !mIsVideo) {
4680        return;
4681    }
4682
4683    int32_t latency = 0, bitrateMode;
4684    if (msg->findInt32("latency", &latency) && latency > 0) {
4685        status_t err = setLatency(latency);
4686        if (err != OK) {
4687            ALOGW("[%s] failed setLatency. Failure is fine since this key is optional",
4688                    mComponentName.c_str());
4689            err = OK;
4690        } else {
4691            mLatency = latency;
4692        }
4693    } else if ((!msg->findInt32("bitrate-mode", &bitrateMode) &&
4694            bitrateMode == OMX_Video_ControlRateConstant)) {
4695        // default the latency to be 1 if latency key is not specified or unsupported and bitrateMode
4696        // is CBR.
4697        mLatency = 1;
4698    }
4699}
4700
4701status_t ACodec::setupErrorCorrectionParameters() {
4702    OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
4703    InitOMXParams(&errorCorrectionType);
4704    errorCorrectionType.nPortIndex = kPortIndexOutput;
4705
4706    status_t err = mOMXNode->getParameter(
4707            OMX_IndexParamVideoErrorCorrection,
4708            &errorCorrectionType, sizeof(errorCorrectionType));
4709
4710    if (err != OK) {
4711        return OK;  // Optional feature. Ignore this failure
4712    }
4713
4714    errorCorrectionType.bEnableHEC = OMX_FALSE;
4715    errorCorrectionType.bEnableResync = OMX_TRUE;
4716    errorCorrectionType.nResynchMarkerSpacing = 256;
4717    errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
4718    errorCorrectionType.bEnableRVLC = OMX_FALSE;
4719
4720    return mOMXNode->setParameter(
4721            OMX_IndexParamVideoErrorCorrection,
4722            &errorCorrectionType, sizeof(errorCorrectionType));
4723}
4724
4725status_t ACodec::setVideoFormatOnPort(
4726        OMX_U32 portIndex,
4727        int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat,
4728        float frameRate) {
4729    OMX_PARAM_PORTDEFINITIONTYPE def;
4730    InitOMXParams(&def);
4731    def.nPortIndex = portIndex;
4732
4733    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
4734
4735    status_t err = mOMXNode->getParameter(
4736            OMX_IndexParamPortDefinition, &def, sizeof(def));
4737    if (err != OK) {
4738        return err;
4739    }
4740
4741    if (portIndex == kPortIndexInput) {
4742        // XXX Need a (much) better heuristic to compute input buffer sizes.
4743        const size_t X = 64 * 1024;
4744        if (def.nBufferSize < X) {
4745            def.nBufferSize = X;
4746        }
4747    }
4748
4749    if (def.eDomain != OMX_PortDomainVideo) {
4750        ALOGE("expected video port, got %s(%d)", asString(def.eDomain), def.eDomain);
4751        return FAILED_TRANSACTION;
4752    }
4753
4754    video_def->nFrameWidth = width;
4755    video_def->nFrameHeight = height;
4756
4757    if (portIndex == kPortIndexInput) {
4758        video_def->eCompressionFormat = compressionFormat;
4759        video_def->eColorFormat = OMX_COLOR_FormatUnused;
4760        if (frameRate >= 0) {
4761            video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f);
4762        }
4763    }
4764
4765    err = mOMXNode->setParameter(
4766            OMX_IndexParamPortDefinition, &def, sizeof(def));
4767
4768    return err;
4769}
4770
4771size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const {
4772    size_t n = 0;
4773
4774    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
4775        const BufferInfo &info = mBuffers[portIndex].itemAt(i);
4776
4777        if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) {
4778            ++n;
4779        }
4780    }
4781
4782    return n;
4783}
4784
4785size_t ACodec::countBuffersOwnedByNativeWindow() const {
4786    size_t n = 0;
4787
4788    for (size_t i = 0; i < mBuffers[kPortIndexOutput].size(); ++i) {
4789        const BufferInfo &info = mBuffers[kPortIndexOutput].itemAt(i);
4790
4791        if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
4792            ++n;
4793        }
4794    }
4795
4796    return n;
4797}
4798
4799void ACodec::waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs() {
4800    if (mNativeWindow == NULL) {
4801        return;
4802    }
4803
4804    while (countBuffersOwnedByNativeWindow() > mNumUndequeuedBuffers
4805            && dequeueBufferFromNativeWindow() != NULL) {
4806        // these buffers will be submitted as regular buffers; account for this
4807        if (storingMetadataInDecodedBuffers() && mMetadataBuffersToSubmit > 0) {
4808            --mMetadataBuffersToSubmit;
4809        }
4810    }
4811}
4812
4813bool ACodec::allYourBuffersAreBelongToUs(
4814        OMX_U32 portIndex) {
4815    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
4816        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
4817
4818        if (info->mStatus != BufferInfo::OWNED_BY_US
4819                && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
4820            ALOGV("[%s] Buffer %u on port %u still has status %d",
4821                    mComponentName.c_str(),
4822                    info->mBufferID, portIndex, info->mStatus);
4823            return false;
4824        }
4825    }
4826
4827    return true;
4828}
4829
4830bool ACodec::allYourBuffersAreBelongToUs() {
4831    return allYourBuffersAreBelongToUs(kPortIndexInput)
4832        && allYourBuffersAreBelongToUs(kPortIndexOutput);
4833}
4834
4835void ACodec::deferMessage(const sp<AMessage> &msg) {
4836    mDeferredQueue.push_back(msg);
4837}
4838
4839void ACodec::processDeferredMessages() {
4840    List<sp<AMessage> > queue = mDeferredQueue;
4841    mDeferredQueue.clear();
4842
4843    List<sp<AMessage> >::iterator it = queue.begin();
4844    while (it != queue.end()) {
4845        onMessageReceived(*it++);
4846    }
4847}
4848
4849status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> &notify) {
4850    const char *niceIndex = portIndex == kPortIndexInput ? "input" : "output";
4851    OMX_PARAM_PORTDEFINITIONTYPE def;
4852    InitOMXParams(&def);
4853    def.nPortIndex = portIndex;
4854
4855    status_t err = mOMXNode->getParameter(OMX_IndexParamPortDefinition, &def, sizeof(def));
4856    if (err != OK) {
4857        return err;
4858    }
4859
4860    if (def.eDir != (portIndex == kPortIndexOutput ? OMX_DirOutput : OMX_DirInput)) {
4861        ALOGE("unexpected dir: %s(%d) on %s port", asString(def.eDir), def.eDir, niceIndex);
4862        return BAD_VALUE;
4863    }
4864
4865    switch (def.eDomain) {
4866        case OMX_PortDomainVideo:
4867        {
4868            OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
4869            switch ((int)videoDef->eCompressionFormat) {
4870                case OMX_VIDEO_CodingUnused:
4871                {
4872                    CHECK(mIsEncoder ^ (portIndex == kPortIndexOutput));
4873                    notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW);
4874
4875                    notify->setInt32("stride", videoDef->nStride);
4876                    notify->setInt32("slice-height", videoDef->nSliceHeight);
4877                    notify->setInt32("color-format", videoDef->eColorFormat);
4878
4879                    if (mNativeWindow == NULL) {
4880                        DescribeColorFormat2Params describeParams;
4881                        InitOMXParams(&describeParams);
4882                        describeParams.eColorFormat = videoDef->eColorFormat;
4883                        describeParams.nFrameWidth = videoDef->nFrameWidth;
4884                        describeParams.nFrameHeight = videoDef->nFrameHeight;
4885                        describeParams.nStride = videoDef->nStride;
4886                        describeParams.nSliceHeight = videoDef->nSliceHeight;
4887                        describeParams.bUsingNativeBuffers = OMX_FALSE;
4888
4889                        if (DescribeColorFormat(mOMXNode, describeParams)) {
4890                            notify->setBuffer(
4891                                    "image-data",
4892                                    ABuffer::CreateAsCopy(
4893                                            &describeParams.sMediaImage,
4894                                            sizeof(describeParams.sMediaImage)));
4895
4896                            MediaImage2 &img = describeParams.sMediaImage;
4897                            MediaImage2::PlaneInfo *plane = img.mPlane;
4898                            ALOGV("[%s] MediaImage { F(%ux%u) @%u+%d+%d @%u+%d+%d @%u+%d+%d }",
4899                                    mComponentName.c_str(), img.mWidth, img.mHeight,
4900                                    plane[0].mOffset, plane[0].mColInc, plane[0].mRowInc,
4901                                    plane[1].mOffset, plane[1].mColInc, plane[1].mRowInc,
4902                                    plane[2].mOffset, plane[2].mColInc, plane[2].mRowInc);
4903                        }
4904                    }
4905
4906                    int32_t width = (int32_t)videoDef->nFrameWidth;
4907                    int32_t height = (int32_t)videoDef->nFrameHeight;
4908
4909                    if (portIndex == kPortIndexOutput) {
4910                        OMX_CONFIG_RECTTYPE rect;
4911                        InitOMXParams(&rect);
4912                        rect.nPortIndex = portIndex;
4913
4914                        if (mOMXNode->getConfig(
4915                                    (portIndex == kPortIndexOutput ?
4916                                            OMX_IndexConfigCommonOutputCrop :
4917                                            OMX_IndexConfigCommonInputCrop),
4918                                    &rect, sizeof(rect)) != OK) {
4919                            rect.nLeft = 0;
4920                            rect.nTop = 0;
4921                            rect.nWidth = videoDef->nFrameWidth;
4922                            rect.nHeight = videoDef->nFrameHeight;
4923                        }
4924
4925                        if (rect.nLeft < 0 || rect.nTop < 0 ||
4926                            rect.nWidth == 0 || rect.nHeight == 0 ||
4927                            rect.nLeft + rect.nWidth > videoDef->nFrameWidth ||
4928                            rect.nTop + rect.nHeight > videoDef->nFrameHeight) {
4929                            ALOGE("Wrong cropped rect (%d, %d, %u, %u) vs. frame (%u, %u)",
4930                                    rect.nLeft, rect.nTop,
4931                                    rect.nWidth, rect.nHeight,
4932                                    videoDef->nFrameWidth, videoDef->nFrameHeight);
4933                            return BAD_VALUE;
4934                        }
4935
4936                        notify->setRect(
4937                                "crop",
4938                                rect.nLeft,
4939                                rect.nTop,
4940                                rect.nLeft + rect.nWidth - 1,
4941                                rect.nTop + rect.nHeight - 1);
4942
4943                        width = rect.nWidth;
4944                        height = rect.nHeight;
4945
4946                        android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN;
4947                        (void)getColorAspectsAndDataSpaceForVideoDecoder(
4948                                width, height, mConfigFormat, notify,
4949                                mUsingNativeWindow ? &dataSpace : NULL);
4950                        if (mUsingNativeWindow) {
4951                            notify->setInt32("android._dataspace", dataSpace);
4952                        }
4953                        (void)getHDRStaticInfoForVideoCodec(kPortIndexOutput, notify);
4954                    } else {
4955                        (void)getInputColorAspectsForVideoEncoder(notify);
4956                        if (mConfigFormat->contains("hdr-static-info")) {
4957                            (void)getHDRStaticInfoForVideoCodec(kPortIndexInput, notify);
4958                        }
4959                        uint32_t latency = 0;
4960                        if (mIsEncoder && !mIsImage &&
4961                                getLatency(&latency) == OK && latency > 0) {
4962                            notify->setInt32("latency", latency);
4963                        }
4964                    }
4965
4966                    break;
4967                }
4968
4969                case OMX_VIDEO_CodingVP8:
4970                case OMX_VIDEO_CodingVP9:
4971                {
4972                    OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type;
4973                    InitOMXParams(&vp8type);
4974                    vp8type.nPortIndex = kPortIndexOutput;
4975                    status_t err = mOMXNode->getParameter(
4976                            (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
4977                            &vp8type,
4978                            sizeof(vp8type));
4979
4980                    if (err == OK) {
4981                        if (vp8type.eTemporalPattern == OMX_VIDEO_VPXTemporalLayerPatternWebRTC
4982                                && vp8type.nTemporalLayerCount > 0
4983                                && vp8type.nTemporalLayerCount
4984                                        <= OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS) {
4985                            // advertise as android.generic if we configured for android.generic
4986                            AString origSchema;
4987                            if (notify->findString("ts-schema", &origSchema)
4988                                    && origSchema.startsWith("android.generic")) {
4989                                notify->setString("ts-schema", AStringPrintf(
4990                                        "android.generic.%u", vp8type.nTemporalLayerCount));
4991                            } else {
4992                                notify->setString("ts-schema", AStringPrintf(
4993                                        "webrtc.vp8.%u-layer", vp8type.nTemporalLayerCount));
4994                            }
4995                        }
4996                    }
4997                    // Fall through to set up mime.
4998                }
4999
5000                default:
5001                {
5002                    if (mIsEncoder ^ (portIndex == kPortIndexOutput)) {
5003                        // should be CodingUnused
5004                        ALOGE("Raw port video compression format is %s(%d)",
5005                                asString(videoDef->eCompressionFormat),
5006                                videoDef->eCompressionFormat);
5007                        return BAD_VALUE;
5008                    }
5009                    AString mime;
5010                    if (GetMimeTypeForVideoCoding(
5011                        videoDef->eCompressionFormat, &mime) != OK) {
5012                        notify->setString("mime", "application/octet-stream");
5013                    } else {
5014                        notify->setString("mime", mime.c_str());
5015                    }
5016                    uint32_t intraRefreshPeriod = 0;
5017                    if (mIsEncoder && !mIsImage &&
5018                            getIntraRefreshPeriod(&intraRefreshPeriod) == OK
5019                            && intraRefreshPeriod > 0) {
5020                        notify->setInt32("intra-refresh-period", intraRefreshPeriod);
5021                    }
5022                    break;
5023                }
5024            }
5025            notify->setInt32("width", videoDef->nFrameWidth);
5026            notify->setInt32("height", videoDef->nFrameHeight);
5027            ALOGV("[%s] %s format is %s", mComponentName.c_str(),
5028                    portIndex == kPortIndexInput ? "input" : "output",
5029                    notify->debugString().c_str());
5030
5031            break;
5032        }
5033
5034        case OMX_PortDomainAudio:
5035        {
5036            OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
5037
5038            switch ((int)audioDef->eEncoding) {
5039                case OMX_AUDIO_CodingPCM:
5040                {
5041                    OMX_AUDIO_PARAM_PCMMODETYPE params;
5042                    InitOMXParams(&params);
5043                    params.nPortIndex = portIndex;
5044
5045                    err = mOMXNode->getParameter(
5046                            OMX_IndexParamAudioPcm, &params, sizeof(params));
5047                    if (err != OK) {
5048                        return err;
5049                    }
5050
5051                    if (params.nChannels <= 0
5052                            || (params.nChannels != 1 && !params.bInterleaved)
5053                            || params.ePCMMode != OMX_AUDIO_PCMModeLinear) {
5054                        ALOGE("unsupported PCM port: %u channels%s, %u-bit",
5055                                params.nChannels,
5056                                params.bInterleaved ? " interleaved" : "",
5057                                params.nBitPerSample);
5058                        return FAILED_TRANSACTION;
5059                    }
5060
5061                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
5062                    notify->setInt32("channel-count", params.nChannels);
5063                    notify->setInt32("sample-rate", params.nSamplingRate);
5064
5065                    AudioEncoding encoding = kAudioEncodingPcm16bit;
5066                    if (params.eNumData == OMX_NumericalDataUnsigned
5067                            && params.nBitPerSample == 8u) {
5068                        encoding = kAudioEncodingPcm8bit;
5069                    } else if (params.eNumData == OMX_NumericalDataFloat
5070                            && params.nBitPerSample == 32u) {
5071                        encoding = kAudioEncodingPcmFloat;
5072                    } else if (params.nBitPerSample != 16u
5073                            || params.eNumData != OMX_NumericalDataSigned) {
5074                        ALOGE("unsupported PCM port: %s(%d), %s(%d) mode ",
5075                                asString(params.eNumData), params.eNumData,
5076                                asString(params.ePCMMode), params.ePCMMode);
5077                        return FAILED_TRANSACTION;
5078                    }
5079                    notify->setInt32("pcm-encoding", encoding);
5080
5081                    if (mChannelMaskPresent) {
5082                        notify->setInt32("channel-mask", mChannelMask);
5083                    }
5084                    break;
5085                }
5086
5087                case OMX_AUDIO_CodingAAC:
5088                {
5089                    OMX_AUDIO_PARAM_AACPROFILETYPE params;
5090                    InitOMXParams(&params);
5091                    params.nPortIndex = portIndex;
5092
5093                    err = mOMXNode->getParameter(
5094                            OMX_IndexParamAudioAac, &params, sizeof(params));
5095                    if (err != OK) {
5096                        return err;
5097                    }
5098
5099                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
5100                    notify->setInt32("channel-count", params.nChannels);
5101                    notify->setInt32("sample-rate", params.nSampleRate);
5102                    break;
5103                }
5104
5105                case OMX_AUDIO_CodingAMR:
5106                {
5107                    OMX_AUDIO_PARAM_AMRTYPE params;
5108                    InitOMXParams(&params);
5109                    params.nPortIndex = portIndex;
5110
5111                    err = mOMXNode->getParameter(
5112                            OMX_IndexParamAudioAmr, &params, sizeof(params));
5113                    if (err != OK) {
5114                        return err;
5115                    }
5116
5117                    notify->setInt32("channel-count", 1);
5118                    if (params.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0) {
5119                        notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_WB);
5120                        notify->setInt32("sample-rate", 16000);
5121                    } else {
5122                        notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_NB);
5123                        notify->setInt32("sample-rate", 8000);
5124                    }
5125                    break;
5126                }
5127
5128                case OMX_AUDIO_CodingFLAC:
5129                {
5130                    OMX_AUDIO_PARAM_FLACTYPE params;
5131                    InitOMXParams(&params);
5132                    params.nPortIndex = portIndex;
5133
5134                    err = mOMXNode->getParameter(
5135                            OMX_IndexParamAudioFlac, &params, sizeof(params));
5136                    if (err != OK) {
5137                        return err;
5138                    }
5139
5140                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_FLAC);
5141                    notify->setInt32("channel-count", params.nChannels);
5142                    notify->setInt32("sample-rate", params.nSampleRate);
5143                    break;
5144                }
5145
5146                case OMX_AUDIO_CodingMP3:
5147                {
5148                    OMX_AUDIO_PARAM_MP3TYPE params;
5149                    InitOMXParams(&params);
5150                    params.nPortIndex = portIndex;
5151
5152                    err = mOMXNode->getParameter(
5153                            OMX_IndexParamAudioMp3, &params, sizeof(params));
5154                    if (err != OK) {
5155                        return err;
5156                    }
5157
5158                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MPEG);
5159                    notify->setInt32("channel-count", params.nChannels);
5160                    notify->setInt32("sample-rate", params.nSampleRate);
5161                    break;
5162                }
5163
5164                case OMX_AUDIO_CodingVORBIS:
5165                {
5166                    OMX_AUDIO_PARAM_VORBISTYPE params;
5167                    InitOMXParams(&params);
5168                    params.nPortIndex = portIndex;
5169
5170                    err = mOMXNode->getParameter(
5171                            OMX_IndexParamAudioVorbis, &params, sizeof(params));
5172                    if (err != OK) {
5173                        return err;
5174                    }
5175
5176                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_VORBIS);
5177                    notify->setInt32("channel-count", params.nChannels);
5178                    notify->setInt32("sample-rate", params.nSampleRate);
5179                    break;
5180                }
5181
5182                case OMX_AUDIO_CodingAndroidAC3:
5183                {
5184                    OMX_AUDIO_PARAM_ANDROID_AC3TYPE params;
5185                    InitOMXParams(&params);
5186                    params.nPortIndex = portIndex;
5187
5188                    err = mOMXNode->getParameter(
5189                            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
5190                            &params, sizeof(params));
5191                    if (err != OK) {
5192                        return err;
5193                    }
5194
5195                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AC3);
5196                    notify->setInt32("channel-count", params.nChannels);
5197                    notify->setInt32("sample-rate", params.nSampleRate);
5198                    break;
5199                }
5200
5201                case OMX_AUDIO_CodingAndroidEAC3:
5202                {
5203                    OMX_AUDIO_PARAM_ANDROID_EAC3TYPE params;
5204                    InitOMXParams(&params);
5205                    params.nPortIndex = portIndex;
5206
5207                    err = mOMXNode->getParameter(
5208                            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
5209                            &params, sizeof(params));
5210                    if (err != OK) {
5211                        return err;
5212                    }
5213
5214                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_EAC3);
5215                    notify->setInt32("channel-count", params.nChannels);
5216                    notify->setInt32("sample-rate", params.nSampleRate);
5217                    break;
5218                }
5219
5220                case OMX_AUDIO_CodingAndroidOPUS:
5221                {
5222                    OMX_AUDIO_PARAM_ANDROID_OPUSTYPE params;
5223                    InitOMXParams(&params);
5224                    params.nPortIndex = portIndex;
5225
5226                    err = mOMXNode->getParameter(
5227                            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus,
5228                            &params, sizeof(params));
5229                    if (err != OK) {
5230                        return err;
5231                    }
5232
5233                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_OPUS);
5234                    notify->setInt32("channel-count", params.nChannels);
5235                    notify->setInt32("sample-rate", params.nSampleRate);
5236                    break;
5237                }
5238
5239                case OMX_AUDIO_CodingG711:
5240                {
5241                    OMX_AUDIO_PARAM_PCMMODETYPE params;
5242                    InitOMXParams(&params);
5243                    params.nPortIndex = portIndex;
5244
5245                    err = mOMXNode->getParameter(
5246                            (OMX_INDEXTYPE)OMX_IndexParamAudioPcm, &params, sizeof(params));
5247                    if (err != OK) {
5248                        return err;
5249                    }
5250
5251                    const char *mime = NULL;
5252                    if (params.ePCMMode == OMX_AUDIO_PCMModeMULaw) {
5253                        mime = MEDIA_MIMETYPE_AUDIO_G711_MLAW;
5254                    } else if (params.ePCMMode == OMX_AUDIO_PCMModeALaw) {
5255                        mime = MEDIA_MIMETYPE_AUDIO_G711_ALAW;
5256                    } else { // params.ePCMMode == OMX_AUDIO_PCMModeLinear
5257                        mime = MEDIA_MIMETYPE_AUDIO_RAW;
5258                    }
5259                    notify->setString("mime", mime);
5260                    notify->setInt32("channel-count", params.nChannels);
5261                    notify->setInt32("sample-rate", params.nSamplingRate);
5262                    notify->setInt32("pcm-encoding", kAudioEncodingPcm16bit);
5263                    break;
5264                }
5265
5266                case OMX_AUDIO_CodingGSMFR:
5267                {
5268                    OMX_AUDIO_PARAM_PCMMODETYPE params;
5269                    InitOMXParams(&params);
5270                    params.nPortIndex = portIndex;
5271
5272                    err = mOMXNode->getParameter(
5273                                OMX_IndexParamAudioPcm, &params, sizeof(params));
5274                    if (err != OK) {
5275                        return err;
5276                    }
5277
5278                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MSGSM);
5279                    notify->setInt32("channel-count", params.nChannels);
5280                    notify->setInt32("sample-rate", params.nSamplingRate);
5281                    break;
5282                }
5283
5284                default:
5285                    ALOGE("Unsupported audio coding: %s(%d)\n",
5286                            asString(audioDef->eEncoding), audioDef->eEncoding);
5287                    return BAD_TYPE;
5288            }
5289            break;
5290        }
5291
5292        default:
5293            ALOGE("Unsupported domain: %s(%d)", asString(def.eDomain), def.eDomain);
5294            return BAD_TYPE;
5295    }
5296
5297    return getVendorParameters(portIndex, notify);
5298}
5299
5300void ACodec::onDataSpaceChanged(android_dataspace dataSpace, const ColorAspects &aspects) {
5301    // aspects are normally communicated in ColorAspects
5302    int32_t range, standard, transfer;
5303    convertCodecColorAspectsToPlatformAspects(aspects, &range, &standard, &transfer);
5304
5305    // if some aspects are unspecified, use dataspace fields
5306    if (range != 0) {
5307        range = (dataSpace & HAL_DATASPACE_RANGE_MASK) >> HAL_DATASPACE_RANGE_SHIFT;
5308    }
5309    if (standard != 0) {
5310        standard = (dataSpace & HAL_DATASPACE_STANDARD_MASK) >> HAL_DATASPACE_STANDARD_SHIFT;
5311    }
5312    if (transfer != 0) {
5313        transfer = (dataSpace & HAL_DATASPACE_TRANSFER_MASK) >> HAL_DATASPACE_TRANSFER_SHIFT;
5314    }
5315
5316    mOutputFormat = mOutputFormat->dup(); // trigger an output format changed event
5317    if (range != 0) {
5318        mOutputFormat->setInt32("color-range", range);
5319    }
5320    if (standard != 0) {
5321        mOutputFormat->setInt32("color-standard", standard);
5322    }
5323    if (transfer != 0) {
5324        mOutputFormat->setInt32("color-transfer", transfer);
5325    }
5326
5327    ALOGD("dataspace changed to %#x (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) "
5328          "(R:%d(%s), S:%d(%s), T:%d(%s))",
5329            dataSpace,
5330            aspects.mRange, asString(aspects.mRange),
5331            aspects.mPrimaries, asString(aspects.mPrimaries),
5332            aspects.mMatrixCoeffs, asString(aspects.mMatrixCoeffs),
5333            aspects.mTransfer, asString(aspects.mTransfer),
5334            range, asString((ColorRange)range),
5335            standard, asString((ColorStandard)standard),
5336            transfer, asString((ColorTransfer)transfer));
5337}
5338
5339void ACodec::onOutputFormatChanged(sp<const AMessage> expectedFormat) {
5340    // store new output format, at the same time mark that this is no longer the first frame
5341    mOutputFormat = mBaseOutputFormat->dup();
5342
5343    if (getPortFormat(kPortIndexOutput, mOutputFormat) != OK) {
5344        ALOGE("[%s] Failed to get port format to send format change", mComponentName.c_str());
5345        return;
5346    }
5347
5348    if (expectedFormat != NULL) {
5349        sp<const AMessage> changes = expectedFormat->changesFrom(mOutputFormat);
5350        sp<const AMessage> to = mOutputFormat->changesFrom(expectedFormat);
5351        if (changes->countEntries() != 0 || to->countEntries() != 0) {
5352            ALOGW("[%s] BAD CODEC: Output format changed unexpectedly from (diff) %s to (diff) %s",
5353                    mComponentName.c_str(),
5354                    changes->debugString(4).c_str(), to->debugString(4).c_str());
5355        }
5356    }
5357
5358    if (!mIsVideo && !mIsEncoder) {
5359        AudioEncoding pcmEncoding = kAudioEncodingPcm16bit;
5360        (void)mConfigFormat->findInt32("pcm-encoding", (int32_t*)&pcmEncoding);
5361        AudioEncoding codecPcmEncoding = kAudioEncodingPcm16bit;
5362        (void)mOutputFormat->findInt32("pcm-encoding", (int32_t*)&pcmEncoding);
5363
5364        mConverter[kPortIndexOutput] = AudioConverter::Create(codecPcmEncoding, pcmEncoding);
5365        if (mConverter[kPortIndexOutput] != NULL) {
5366            mOutputFormat->setInt32("pcm-encoding", pcmEncoding);
5367        }
5368    }
5369
5370    if (mTunneled) {
5371        sendFormatChange();
5372    }
5373}
5374
5375void ACodec::sendFormatChange() {
5376    AString mime;
5377    CHECK(mOutputFormat->findString("mime", &mime));
5378
5379    if (mime == MEDIA_MIMETYPE_AUDIO_RAW && (mEncoderDelay || mEncoderPadding)) {
5380        int32_t channelCount, sampleRate;
5381        CHECK(mOutputFormat->findInt32("channel-count", &channelCount));
5382        CHECK(mOutputFormat->findInt32("sample-rate", &sampleRate));
5383        if (mSampleRate != 0 && sampleRate != 0) {
5384            // avoiding 32-bit overflows in intermediate values
5385            mEncoderDelay = (int32_t)((((int64_t)mEncoderDelay) * sampleRate) / mSampleRate);
5386            mEncoderPadding = (int32_t)((((int64_t)mEncoderPadding) * sampleRate) / mSampleRate);
5387            mSampleRate = sampleRate;
5388        }
5389        if (mSkipCutBuffer != NULL) {
5390            size_t prevbufsize = mSkipCutBuffer->size();
5391            if (prevbufsize != 0) {
5392                ALOGW("Replacing SkipCutBuffer holding %zu bytes", prevbufsize);
5393            }
5394        }
5395        mSkipCutBuffer = new SkipCutBuffer(mEncoderDelay, mEncoderPadding, channelCount);
5396    }
5397
5398    // mLastOutputFormat is not used when tunneled; doing this just to stay consistent
5399    mLastOutputFormat = mOutputFormat;
5400}
5401
5402void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) {
5403    ALOGE("signalError(omxError %#x, internalError %d)", error, internalError);
5404
5405    if (internalError == UNKNOWN_ERROR) { // find better error code
5406        const status_t omxStatus = statusFromOMXError(error);
5407        if (omxStatus != 0) {
5408            internalError = omxStatus;
5409        } else {
5410            ALOGW("Invalid OMX error %#x", error);
5411        }
5412    }
5413
5414    mFatalError = true;
5415    mCallback->onError(internalError, ACTION_CODE_FATAL);
5416}
5417
5418status_t ACodec::requestIDRFrame() {
5419    if (!mIsEncoder) {
5420        return ERROR_UNSUPPORTED;
5421    }
5422
5423    OMX_CONFIG_INTRAREFRESHVOPTYPE params;
5424    InitOMXParams(&params);
5425
5426    params.nPortIndex = kPortIndexOutput;
5427    params.IntraRefreshVOP = OMX_TRUE;
5428
5429    return mOMXNode->setConfig(
5430            OMX_IndexConfigVideoIntraVOPRefresh,
5431            &params,
5432            sizeof(params));
5433}
5434
5435////////////////////////////////////////////////////////////////////////////////
5436
5437ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
5438    : AState(parentState),
5439      mCodec(codec) {
5440}
5441
5442ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(
5443        OMX_U32 /* portIndex */) {
5444    return KEEP_BUFFERS;
5445}
5446
5447void ACodec::BaseState::stateExited() {
5448    ++mCodec->mStateGeneration;
5449}
5450
5451bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) {
5452    switch (msg->what()) {
5453        case kWhatInputBufferFilled:
5454        {
5455            onInputBufferFilled(msg);
5456            break;
5457        }
5458
5459        case kWhatOutputBufferDrained:
5460        {
5461            onOutputBufferDrained(msg);
5462            break;
5463        }
5464
5465        case ACodec::kWhatOMXMessageList:
5466        {
5467            return checkOMXMessage(msg) ? onOMXMessageList(msg) : true;
5468        }
5469
5470        case ACodec::kWhatOMXMessageItem:
5471        {
5472            // no need to check as we already did it for kWhatOMXMessageList
5473            return onOMXMessage(msg);
5474        }
5475
5476        case ACodec::kWhatOMXMessage:
5477        {
5478            return checkOMXMessage(msg) ? onOMXMessage(msg) : true;
5479        }
5480
5481        case ACodec::kWhatSetSurface:
5482        {
5483            sp<AReplyToken> replyID;
5484            CHECK(msg->senderAwaitsResponse(&replyID));
5485
5486            sp<RefBase> obj;
5487            CHECK(msg->findObject("surface", &obj));
5488
5489            status_t err = mCodec->handleSetSurface(static_cast<Surface *>(obj.get()));
5490
5491            sp<AMessage> response = new AMessage;
5492            response->setInt32("err", err);
5493            response->postReply(replyID);
5494            break;
5495        }
5496
5497        case ACodec::kWhatCreateInputSurface:
5498        case ACodec::kWhatSetInputSurface:
5499        case ACodec::kWhatSignalEndOfInputStream:
5500        {
5501            // This may result in an app illegal state exception.
5502            ALOGE("Message 0x%x was not handled", msg->what());
5503            mCodec->signalError(OMX_ErrorUndefined, INVALID_OPERATION);
5504            return true;
5505        }
5506
5507        case ACodec::kWhatOMXDied:
5508        {
5509            // This will result in kFlagSawMediaServerDie handling in MediaCodec.
5510            ALOGE("OMX/mediaserver died, signalling error!");
5511            mCodec->mGraphicBufferSource.clear();
5512            mCodec->signalError(OMX_ErrorResourcesLost, DEAD_OBJECT);
5513            break;
5514        }
5515
5516        case ACodec::kWhatReleaseCodecInstance:
5517        {
5518            ALOGI("[%s] forcing the release of codec",
5519                    mCodec->mComponentName.c_str());
5520            status_t err = mCodec->mOMXNode->freeNode();
5521            ALOGE_IF("[%s] failed to release codec instance: err=%d",
5522                       mCodec->mComponentName.c_str(), err);
5523            mCodec->mCallback->onReleaseCompleted();
5524
5525            mCodec->changeState(mCodec->mUninitializedState);
5526            break;
5527        }
5528
5529        case ACodec::kWhatForceStateTransition:
5530        {
5531            ALOGV("Already transitioned --- ignore");
5532            break;
5533        }
5534
5535        default:
5536            return false;
5537    }
5538
5539    return true;
5540}
5541
5542bool ACodec::BaseState::checkOMXMessage(const sp<AMessage> &msg) {
5543    // there is a possibility that this is an outstanding message for a
5544    // codec that we have already destroyed
5545    if (mCodec->mOMXNode == NULL) {
5546        ALOGI("ignoring message as already freed component: %s",
5547                msg->debugString().c_str());
5548        return false;
5549    }
5550
5551    int32_t generation;
5552    CHECK(msg->findInt32("generation", (int32_t*)&generation));
5553    if (generation != mCodec->mNodeGeneration) {
5554        ALOGW("Unexpected message for component: %s, gen %u, cur %u",
5555                msg->debugString().c_str(), generation, mCodec->mNodeGeneration);
5556        return false;
5557    }
5558    return true;
5559}
5560
5561bool ACodec::BaseState::onOMXMessageList(const sp<AMessage> &msg) {
5562    sp<RefBase> obj;
5563    CHECK(msg->findObject("messages", &obj));
5564    sp<MessageList> msgList = static_cast<MessageList *>(obj.get());
5565
5566    bool receivedRenderedEvents = false;
5567    for (std::list<sp<AMessage>>::const_iterator it = msgList->getList().cbegin();
5568          it != msgList->getList().cend(); ++it) {
5569        (*it)->setWhat(ACodec::kWhatOMXMessageItem);
5570        mCodec->handleMessage(*it);
5571        int32_t type;
5572        CHECK((*it)->findInt32("type", &type));
5573        if (type == omx_message::FRAME_RENDERED) {
5574            receivedRenderedEvents = true;
5575        }
5576    }
5577
5578    if (receivedRenderedEvents) {
5579        // NOTE: all buffers are rendered in this case
5580        mCodec->notifyOfRenderedFrames();
5581    }
5582    return true;
5583}
5584
5585bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) {
5586    int32_t type;
5587    CHECK(msg->findInt32("type", &type));
5588
5589    switch (type) {
5590        case omx_message::EVENT:
5591        {
5592            int32_t event, data1, data2;
5593            CHECK(msg->findInt32("event", &event));
5594            CHECK(msg->findInt32("data1", &data1));
5595            CHECK(msg->findInt32("data2", &data2));
5596
5597            if (event == OMX_EventCmdComplete
5598                    && data1 == OMX_CommandFlush
5599                    && data2 == (int32_t)OMX_ALL) {
5600                // Use of this notification is not consistent across
5601                // implementations. We'll drop this notification and rely
5602                // on flush-complete notifications on the individual port
5603                // indices instead.
5604
5605                return true;
5606            }
5607
5608            return onOMXEvent(
5609                    static_cast<OMX_EVENTTYPE>(event),
5610                    static_cast<OMX_U32>(data1),
5611                    static_cast<OMX_U32>(data2));
5612        }
5613
5614        case omx_message::EMPTY_BUFFER_DONE:
5615        {
5616            IOMX::buffer_id bufferID;
5617            int32_t fenceFd;
5618
5619            CHECK(msg->findInt32("buffer", (int32_t*)&bufferID));
5620            CHECK(msg->findInt32("fence_fd", &fenceFd));
5621
5622            return onOMXEmptyBufferDone(bufferID, fenceFd);
5623        }
5624
5625        case omx_message::FILL_BUFFER_DONE:
5626        {
5627            IOMX::buffer_id bufferID;
5628            CHECK(msg->findInt32("buffer", (int32_t*)&bufferID));
5629
5630            int32_t rangeOffset, rangeLength, flags, fenceFd;
5631            int64_t timeUs;
5632
5633            CHECK(msg->findInt32("range_offset", &rangeOffset));
5634            CHECK(msg->findInt32("range_length", &rangeLength));
5635            CHECK(msg->findInt32("flags", &flags));
5636            CHECK(msg->findInt64("timestamp", &timeUs));
5637            CHECK(msg->findInt32("fence_fd", &fenceFd));
5638
5639            return onOMXFillBufferDone(
5640                    bufferID,
5641                    (size_t)rangeOffset, (size_t)rangeLength,
5642                    (OMX_U32)flags,
5643                    timeUs,
5644                    fenceFd);
5645        }
5646
5647        case omx_message::FRAME_RENDERED:
5648        {
5649            int64_t mediaTimeUs, systemNano;
5650
5651            CHECK(msg->findInt64("media_time_us", &mediaTimeUs));
5652            CHECK(msg->findInt64("system_nano", &systemNano));
5653
5654            return onOMXFrameRendered(
5655                    mediaTimeUs, systemNano);
5656        }
5657
5658        default:
5659            ALOGE("Unexpected message type: %d", type);
5660            return false;
5661    }
5662}
5663
5664bool ACodec::BaseState::onOMXFrameRendered(
5665        int64_t mediaTimeUs __unused, nsecs_t systemNano __unused) {
5666    // ignore outside of Executing and PortSettingsChanged states
5667    return true;
5668}
5669
5670bool ACodec::BaseState::onOMXEvent(
5671        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5672    if (event == OMX_EventDataSpaceChanged) {
5673        ColorAspects aspects = ColorUtils::unpackToColorAspects(data2);
5674
5675        mCodec->onDataSpaceChanged((android_dataspace)data1, aspects);
5676        return true;
5677    }
5678
5679    if (event != OMX_EventError) {
5680        ALOGV("[%s] EVENT(%d, 0x%08x, 0x%08x)",
5681             mCodec->mComponentName.c_str(), event, data1, data2);
5682
5683        return false;
5684    }
5685
5686    ALOGE("[%s] ERROR(0x%08x)", mCodec->mComponentName.c_str(), data1);
5687
5688    // verify OMX component sends back an error we expect.
5689    OMX_ERRORTYPE omxError = (OMX_ERRORTYPE)data1;
5690    if (!isOMXError(omxError)) {
5691        ALOGW("Invalid OMX error %#x", omxError);
5692        omxError = OMX_ErrorUndefined;
5693    }
5694    mCodec->signalError(omxError);
5695
5696    return true;
5697}
5698
5699bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID, int fenceFd) {
5700    ALOGV("[%s] onOMXEmptyBufferDone %u",
5701         mCodec->mComponentName.c_str(), bufferID);
5702
5703    BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
5704    BufferInfo::Status status = BufferInfo::getSafeStatus(info);
5705    if (status != BufferInfo::OWNED_BY_COMPONENT) {
5706        ALOGE("Wrong ownership in EBD: %s(%d) buffer #%u", _asString(status), status, bufferID);
5707        mCodec->dumpBuffers(kPortIndexInput);
5708        if (fenceFd >= 0) {
5709            ::close(fenceFd);
5710        }
5711        return false;
5712    }
5713    info->mStatus = BufferInfo::OWNED_BY_US;
5714
5715    // input buffers cannot take fences, so wait for any fence now
5716    (void)mCodec->waitForFence(fenceFd, "onOMXEmptyBufferDone");
5717    fenceFd = -1;
5718
5719    // still save fence for completeness
5720    info->setWriteFence(fenceFd, "onOMXEmptyBufferDone");
5721
5722    // We're in "store-metadata-in-buffers" mode, the underlying
5723    // OMX component had access to data that's implicitly refcounted
5724    // by this "MediaBuffer" object. Now that the OMX component has
5725    // told us that it's done with the input buffer, we can decrement
5726    // the mediaBuffer's reference count.
5727    info->mData->meta()->setObject("mediaBufferHolder", sp<MediaBufferHolder>(nullptr));
5728
5729    PortMode mode = getPortMode(kPortIndexInput);
5730
5731    switch (mode) {
5732        case KEEP_BUFFERS:
5733            break;
5734
5735        case RESUBMIT_BUFFERS:
5736            postFillThisBuffer(info);
5737            break;
5738
5739        case FREE_BUFFERS:
5740        default:
5741            ALOGE("SHOULD NOT REACH HERE: cannot free empty output buffers");
5742            return false;
5743    }
5744
5745    return true;
5746}
5747
5748void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) {
5749    if (mCodec->mPortEOS[kPortIndexInput]) {
5750        return;
5751    }
5752
5753    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
5754
5755    info->mData->setFormat(mCodec->mInputFormat);
5756    mCodec->mBufferChannel->fillThisBuffer(info->mBufferID);
5757    info->mData.clear();
5758    info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
5759}
5760
5761void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
5762    IOMX::buffer_id bufferID;
5763    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
5764    sp<MediaCodecBuffer> buffer;
5765    int32_t err = OK;
5766    bool eos = false;
5767    PortMode mode = getPortMode(kPortIndexInput);
5768    int32_t discarded = 0;
5769    if (msg->findInt32("discarded", &discarded) && discarded) {
5770        // these are unfilled buffers returned by client
5771        // buffers are returned on MediaCodec.flush
5772        mode = KEEP_BUFFERS;
5773    }
5774    sp<RefBase> obj;
5775    CHECK(msg->findObject("buffer", &obj));
5776    buffer = static_cast<MediaCodecBuffer *>(obj.get());
5777
5778    int32_t tmp;
5779    if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) {
5780        eos = true;
5781        err = ERROR_END_OF_STREAM;
5782    }
5783
5784    BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
5785    BufferInfo::Status status = BufferInfo::getSafeStatus(info);
5786    if (status != BufferInfo::OWNED_BY_UPSTREAM) {
5787        ALOGE("Wrong ownership in IBF: %s(%d) buffer #%u", _asString(status), status, bufferID);
5788        mCodec->dumpBuffers(kPortIndexInput);
5789        mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
5790        return;
5791    }
5792
5793    info->mStatus = BufferInfo::OWNED_BY_US;
5794    info->mData = buffer;
5795
5796    switch (mode) {
5797        case KEEP_BUFFERS:
5798        {
5799            if (eos) {
5800                if (!mCodec->mPortEOS[kPortIndexInput]) {
5801                    mCodec->mPortEOS[kPortIndexInput] = true;
5802                    mCodec->mInputEOSResult = err;
5803                }
5804            }
5805            break;
5806        }
5807
5808        case RESUBMIT_BUFFERS:
5809        {
5810            if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) {
5811                // Do not send empty input buffer w/o EOS to the component.
5812                if (buffer->size() == 0 && !eos) {
5813                    postFillThisBuffer(info);
5814                    break;
5815                }
5816
5817                int64_t timeUs;
5818                CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
5819
5820                OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
5821
5822                int32_t isCSD = 0;
5823                if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) {
5824                    if (mCodec->mIsLegacyVP9Decoder) {
5825                        ALOGV("[%s] is legacy VP9 decoder. Ignore %u codec specific data",
5826                            mCodec->mComponentName.c_str(), bufferID);
5827                        postFillThisBuffer(info);
5828                        break;
5829                    }
5830                    flags |= OMX_BUFFERFLAG_CODECCONFIG;
5831                }
5832
5833                if (eos) {
5834                    flags |= OMX_BUFFERFLAG_EOS;
5835                }
5836
5837                size_t size = buffer->size();
5838                size_t offset = buffer->offset();
5839                if (buffer->base() != info->mCodecData->base()) {
5840                    ALOGV("[%s] Needs to copy input data for buffer %u. (%p != %p)",
5841                         mCodec->mComponentName.c_str(),
5842                         bufferID,
5843                         buffer->base(), info->mCodecData->base());
5844
5845                    sp<DataConverter> converter = mCodec->mConverter[kPortIndexInput];
5846                    if (converter == NULL || isCSD) {
5847                        converter = getCopyConverter();
5848                    }
5849                    status_t err = converter->convert(buffer, info->mCodecData);
5850                    if (err != OK) {
5851                        mCodec->signalError(OMX_ErrorUndefined, err);
5852                        return;
5853                    }
5854                    size = info->mCodecData->size();
5855                } else {
5856                    info->mCodecData->setRange(offset, size);
5857                }
5858
5859                if (flags & OMX_BUFFERFLAG_CODECCONFIG) {
5860                    ALOGV("[%s] calling emptyBuffer %u w/ codec specific data",
5861                         mCodec->mComponentName.c_str(), bufferID);
5862                } else if (flags & OMX_BUFFERFLAG_EOS) {
5863                    ALOGV("[%s] calling emptyBuffer %u w/ EOS",
5864                         mCodec->mComponentName.c_str(), bufferID);
5865                } else {
5866#if TRACK_BUFFER_TIMING
5867                    ALOGI("[%s] calling emptyBuffer %u w/ time %lld us",
5868                         mCodec->mComponentName.c_str(), bufferID, (long long)timeUs);
5869#else
5870                    ALOGV("[%s] calling emptyBuffer %u w/ time %lld us",
5871                         mCodec->mComponentName.c_str(), bufferID, (long long)timeUs);
5872#endif
5873                }
5874
5875#if TRACK_BUFFER_TIMING
5876                ACodec::BufferStats stats;
5877                stats.mEmptyBufferTimeUs = ALooper::GetNowUs();
5878                stats.mFillBufferDoneTimeUs = -1ll;
5879                mCodec->mBufferStats.add(timeUs, stats);
5880#endif
5881
5882                if (mCodec->storingMetadataInDecodedBuffers()) {
5883                    // try to submit an output buffer for each input buffer
5884                    PortMode outputMode = getPortMode(kPortIndexOutput);
5885
5886                    ALOGV("MetadataBuffersToSubmit=%u portMode=%s",
5887                            mCodec->mMetadataBuffersToSubmit,
5888                            (outputMode == FREE_BUFFERS ? "FREE" :
5889                             outputMode == KEEP_BUFFERS ? "KEEP" : "RESUBMIT"));
5890                    if (outputMode == RESUBMIT_BUFFERS) {
5891                        mCodec->submitOutputMetadataBuffer();
5892                    }
5893                }
5894                info->checkReadFence("onInputBufferFilled");
5895
5896                status_t err2 = OK;
5897                switch (mCodec->mPortMode[kPortIndexInput]) {
5898                case IOMX::kPortModePresetByteBuffer:
5899                case IOMX::kPortModePresetANWBuffer:
5900                case IOMX::kPortModePresetSecureBuffer:
5901                    {
5902                        err2 = mCodec->mOMXNode->emptyBuffer(
5903                            bufferID, info->mCodecData, flags, timeUs, info->mFenceFd);
5904                    }
5905                    break;
5906#ifndef OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
5907                case IOMX::kPortModeDynamicNativeHandle:
5908                    if (info->mCodecData->size() >= sizeof(VideoNativeHandleMetadata)) {
5909                        VideoNativeHandleMetadata *vnhmd =
5910                            (VideoNativeHandleMetadata*)info->mCodecData->base();
5911                        sp<NativeHandle> handle = NativeHandle::create(
5912                                vnhmd->pHandle, false /* ownsHandle */);
5913                        err2 = mCodec->mOMXNode->emptyBuffer(
5914                            bufferID, handle, flags, timeUs, info->mFenceFd);
5915                    }
5916                    break;
5917                case IOMX::kPortModeDynamicANWBuffer:
5918                    if (info->mCodecData->size() >= sizeof(VideoNativeMetadata)) {
5919                        VideoNativeMetadata *vnmd = (VideoNativeMetadata*)info->mCodecData->base();
5920                        sp<GraphicBuffer> graphicBuffer = GraphicBuffer::from(vnmd->pBuffer);
5921                        err2 = mCodec->mOMXNode->emptyBuffer(
5922                            bufferID, graphicBuffer, flags, timeUs, info->mFenceFd);
5923                    }
5924                    break;
5925#endif
5926                default:
5927                    ALOGW("Can't marshall %s data in %zu sized buffers in %zu-bit mode",
5928                            asString(mCodec->mPortMode[kPortIndexInput]),
5929                            info->mCodecData->size(),
5930                            sizeof(buffer_handle_t) * 8);
5931                    err2 = ERROR_UNSUPPORTED;
5932                    break;
5933                }
5934
5935                info->mFenceFd = -1;
5936                if (err2 != OK) {
5937                    mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err2));
5938                    return;
5939                }
5940                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
5941                // Hold the reference while component is using the buffer.
5942                info->mData = buffer;
5943
5944                if (!eos && err == OK) {
5945                    getMoreInputDataIfPossible();
5946                } else {
5947                    ALOGV("[%s] Signalled EOS (%d) on the input port",
5948                         mCodec->mComponentName.c_str(), err);
5949
5950                    mCodec->mPortEOS[kPortIndexInput] = true;
5951                    mCodec->mInputEOSResult = err;
5952                }
5953            } else if (!mCodec->mPortEOS[kPortIndexInput]) {
5954                if (err != OK && err != ERROR_END_OF_STREAM) {
5955                    ALOGV("[%s] Signalling EOS on the input port due to error %d",
5956                         mCodec->mComponentName.c_str(), err);
5957                } else {
5958                    ALOGV("[%s] Signalling EOS on the input port",
5959                         mCodec->mComponentName.c_str());
5960                }
5961
5962                ALOGV("[%s] calling emptyBuffer %u signalling EOS",
5963                     mCodec->mComponentName.c_str(), bufferID);
5964
5965                info->checkReadFence("onInputBufferFilled");
5966                status_t err2 = mCodec->mOMXNode->emptyBuffer(
5967                        bufferID, OMXBuffer::sPreset, OMX_BUFFERFLAG_EOS, 0, info->mFenceFd);
5968                info->mFenceFd = -1;
5969                if (err2 != OK) {
5970                    mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err2));
5971                    return;
5972                }
5973                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
5974
5975                mCodec->mPortEOS[kPortIndexInput] = true;
5976                mCodec->mInputEOSResult = err;
5977            }
5978            break;
5979        }
5980
5981        case FREE_BUFFERS:
5982            break;
5983
5984        default:
5985            ALOGE("invalid port mode: %d", mode);
5986            break;
5987    }
5988}
5989
5990void ACodec::BaseState::getMoreInputDataIfPossible() {
5991    if (mCodec->mPortEOS[kPortIndexInput]) {
5992        return;
5993    }
5994
5995    BufferInfo *eligible = NULL;
5996
5997    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
5998        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
5999
6000#if 0
6001        if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) {
6002            // There's already a "read" pending.
6003            return;
6004        }
6005#endif
6006
6007        if (info->mStatus == BufferInfo::OWNED_BY_US) {
6008            eligible = info;
6009        }
6010    }
6011
6012    if (eligible == NULL) {
6013        return;
6014    }
6015
6016    postFillThisBuffer(eligible);
6017}
6018
6019bool ACodec::BaseState::onOMXFillBufferDone(
6020        IOMX::buffer_id bufferID,
6021        size_t rangeOffset, size_t rangeLength,
6022        OMX_U32 flags,
6023        int64_t timeUs,
6024        int fenceFd) {
6025    ALOGV("[%s] onOMXFillBufferDone %u time %" PRId64 " us, flags = 0x%08x",
6026         mCodec->mComponentName.c_str(), bufferID, timeUs, flags);
6027
6028    ssize_t index;
6029    status_t err= OK;
6030
6031#if TRACK_BUFFER_TIMING
6032    index = mCodec->mBufferStats.indexOfKey(timeUs);
6033    if (index >= 0) {
6034        ACodec::BufferStats *stats = &mCodec->mBufferStats.editValueAt(index);
6035        stats->mFillBufferDoneTimeUs = ALooper::GetNowUs();
6036
6037        ALOGI("frame PTS %lld: %lld",
6038                timeUs,
6039                stats->mFillBufferDoneTimeUs - stats->mEmptyBufferTimeUs);
6040
6041        mCodec->mBufferStats.removeItemsAt(index);
6042        stats = NULL;
6043    }
6044#endif
6045
6046    BufferInfo *info =
6047        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
6048    BufferInfo::Status status = BufferInfo::getSafeStatus(info);
6049    if (status != BufferInfo::OWNED_BY_COMPONENT) {
6050        ALOGE("Wrong ownership in FBD: %s(%d) buffer #%u", _asString(status), status, bufferID);
6051        mCodec->dumpBuffers(kPortIndexOutput);
6052        mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
6053        if (fenceFd >= 0) {
6054            ::close(fenceFd);
6055        }
6056        return true;
6057    }
6058
6059    info->mDequeuedAt = ++mCodec->mDequeueCounter;
6060    info->mStatus = BufferInfo::OWNED_BY_US;
6061
6062    if (info->mRenderInfo != NULL) {
6063        // The fence for an emptied buffer must have signaled, but there still could be queued
6064        // or out-of-order dequeued buffers in the render queue prior to this buffer. Drop these,
6065        // as we will soon requeue this buffer to the surface. While in theory we could still keep
6066        // track of buffers that are requeued to the surface, it is better to add support to the
6067        // buffer-queue to notify us of released buffers and their fences (in the future).
6068        mCodec->notifyOfRenderedFrames(true /* dropIncomplete */);
6069    }
6070
6071    // byte buffers cannot take fences, so wait for any fence now
6072    if (mCodec->mNativeWindow == NULL) {
6073        (void)mCodec->waitForFence(fenceFd, "onOMXFillBufferDone");
6074        fenceFd = -1;
6075    }
6076    info->setReadFence(fenceFd, "onOMXFillBufferDone");
6077
6078    PortMode mode = getPortMode(kPortIndexOutput);
6079
6080    switch (mode) {
6081        case KEEP_BUFFERS:
6082            break;
6083
6084        case RESUBMIT_BUFFERS:
6085        {
6086            if (rangeLength == 0 && (!(flags & OMX_BUFFERFLAG_EOS)
6087                    || mCodec->mPortEOS[kPortIndexOutput])) {
6088                ALOGV("[%s] calling fillBuffer %u",
6089                     mCodec->mComponentName.c_str(), info->mBufferID);
6090
6091                err = mCodec->fillBuffer(info);
6092                if (err != OK) {
6093                    mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6094                    return true;
6095                }
6096                break;
6097            }
6098
6099            sp<MediaCodecBuffer> buffer = info->mData;
6100
6101            if (mCodec->mOutputFormat != mCodec->mLastOutputFormat && rangeLength > 0) {
6102                // pretend that output format has changed on the first frame (we used to do this)
6103                if (mCodec->mBaseOutputFormat == mCodec->mOutputFormat) {
6104                    mCodec->onOutputFormatChanged(mCodec->mOutputFormat);
6105                }
6106                mCodec->sendFormatChange();
6107            }
6108            buffer->setFormat(mCodec->mOutputFormat);
6109
6110            if (mCodec->usingSecureBufferOnEncoderOutput()) {
6111                native_handle_t *handle = NULL;
6112                sp<SecureBuffer> secureBuffer = static_cast<SecureBuffer *>(buffer.get());
6113                if (secureBuffer != NULL) {
6114#ifdef OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
6115                    // handle is only valid on 32-bit/mediaserver process
6116                    handle = NULL;
6117#else
6118                    handle = (native_handle_t *)secureBuffer->getDestinationPointer();
6119#endif
6120                }
6121                buffer->meta()->setPointer("handle", handle);
6122                buffer->meta()->setInt32("rangeOffset", rangeOffset);
6123                buffer->meta()->setInt32("rangeLength", rangeLength);
6124            } else if (buffer->base() == info->mCodecData->base()) {
6125                buffer->setRange(rangeOffset, rangeLength);
6126            } else {
6127                info->mCodecData->setRange(rangeOffset, rangeLength);
6128                // in this case we know that mConverter is not null
6129                status_t err = mCodec->mConverter[kPortIndexOutput]->convert(
6130                        info->mCodecData, buffer);
6131                if (err != OK) {
6132                    mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6133                    return true;
6134                }
6135            }
6136#if 0
6137            if (mCodec->mNativeWindow == NULL) {
6138                if (IsIDR(info->mData->data(), info->mData->size())) {
6139                    ALOGI("IDR frame");
6140                }
6141            }
6142#endif
6143
6144            if (mCodec->mSkipCutBuffer != NULL) {
6145                mCodec->mSkipCutBuffer->submit(buffer);
6146            }
6147            buffer->meta()->setInt64("timeUs", timeUs);
6148
6149            info->mData.clear();
6150
6151            mCodec->mBufferChannel->drainThisBuffer(info->mBufferID, flags);
6152
6153            info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;
6154
6155            if (flags & OMX_BUFFERFLAG_EOS) {
6156                ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str());
6157
6158                mCodec->mCallback->onEos(mCodec->mInputEOSResult);
6159                mCodec->mPortEOS[kPortIndexOutput] = true;
6160            }
6161            break;
6162        }
6163
6164        case FREE_BUFFERS:
6165            err = mCodec->freeBuffer(kPortIndexOutput, index);
6166            if (err != OK) {
6167                mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6168                return true;
6169            }
6170            break;
6171
6172        default:
6173            ALOGE("Invalid port mode: %d", mode);
6174            return false;
6175    }
6176
6177    return true;
6178}
6179
6180void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
6181    IOMX::buffer_id bufferID;
6182    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
6183    sp<RefBase> obj;
6184    CHECK(msg->findObject("buffer", &obj));
6185    sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
6186    int32_t discarded = 0;
6187    msg->findInt32("discarded", &discarded);
6188
6189    ssize_t index;
6190    BufferInfo *info = mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
6191    BufferInfo::Status status = BufferInfo::getSafeStatus(info);
6192    if (status != BufferInfo::OWNED_BY_DOWNSTREAM) {
6193        ALOGE("Wrong ownership in OBD: %s(%d) buffer #%u", _asString(status), status, bufferID);
6194        mCodec->dumpBuffers(kPortIndexOutput);
6195        mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
6196        return;
6197    }
6198    info->mData = buffer;
6199    int32_t render;
6200    if (mCodec->mNativeWindow != NULL
6201            && msg->findInt32("render", &render) && render != 0
6202            && !discarded && buffer->size() != 0) {
6203        ATRACE_NAME("render");
6204        // The client wants this buffer to be rendered.
6205
6206        android_native_rect_t crop;
6207        if (buffer->format()->findRect("crop", &crop.left, &crop.top, &crop.right, &crop.bottom)) {
6208            // NOTE: native window uses extended right-bottom coordinate
6209            ++crop.right;
6210            ++crop.bottom;
6211            if (memcmp(&crop, &mCodec->mLastNativeWindowCrop, sizeof(crop)) != 0) {
6212                mCodec->mLastNativeWindowCrop = crop;
6213                status_t err = native_window_set_crop(mCodec->mNativeWindow.get(), &crop);
6214                ALOGW_IF(err != NO_ERROR, "failed to set crop: %d", err);
6215            }
6216        }
6217
6218        int32_t dataSpace;
6219        if (buffer->format()->findInt32("android._dataspace", &dataSpace)
6220                && dataSpace != mCodec->mLastNativeWindowDataSpace) {
6221            status_t err = native_window_set_buffers_data_space(
6222                    mCodec->mNativeWindow.get(), (android_dataspace)dataSpace);
6223            mCodec->mLastNativeWindowDataSpace = dataSpace;
6224            ALOGW_IF(err != NO_ERROR, "failed to set dataspace: %d", err);
6225        }
6226        if (buffer->format()->contains("hdr-static-info")) {
6227            HDRStaticInfo info;
6228            if (ColorUtils::getHDRStaticInfoFromFormat(buffer->format(), &info)
6229                && memcmp(&mCodec->mLastHDRStaticInfo, &info, sizeof(info))) {
6230                setNativeWindowHdrMetadata(mCodec->mNativeWindow.get(), &info);
6231                mCodec->mLastHDRStaticInfo = info;
6232            }
6233        }
6234
6235        // save buffers sent to the surface so we can get render time when they return
6236        int64_t mediaTimeUs = -1;
6237        buffer->meta()->findInt64("timeUs", &mediaTimeUs);
6238        if (mediaTimeUs >= 0) {
6239            mCodec->mRenderTracker.onFrameQueued(
6240                    mediaTimeUs, info->mGraphicBuffer, new Fence(::dup(info->mFenceFd)));
6241        }
6242
6243        int64_t timestampNs = 0;
6244        if (!msg->findInt64("timestampNs", &timestampNs)) {
6245            // use media timestamp if client did not request a specific render timestamp
6246            if (buffer->meta()->findInt64("timeUs", &timestampNs)) {
6247                ALOGV("using buffer PTS of %lld", (long long)timestampNs);
6248                timestampNs *= 1000;
6249            }
6250        }
6251
6252        status_t err;
6253        err = native_window_set_buffers_timestamp(mCodec->mNativeWindow.get(), timestampNs);
6254        ALOGW_IF(err != NO_ERROR, "failed to set buffer timestamp: %d", err);
6255
6256        info->checkReadFence("onOutputBufferDrained before queueBuffer");
6257        err = mCodec->mNativeWindow->queueBuffer(
6258                    mCodec->mNativeWindow.get(), info->mGraphicBuffer.get(), info->mFenceFd);
6259        info->mFenceFd = -1;
6260        if (err == OK) {
6261            info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
6262        } else {
6263            ALOGE("queueBuffer failed in onOutputBufferDrained: %d", err);
6264            mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6265            info->mStatus = BufferInfo::OWNED_BY_US;
6266            // keeping read fence as write fence to avoid clobbering
6267            info->mIsReadFence = false;
6268        }
6269    } else {
6270        if (mCodec->mNativeWindow != NULL && (discarded || buffer->size() != 0)) {
6271            // move read fence into write fence to avoid clobbering
6272            info->mIsReadFence = false;
6273            ATRACE_NAME("frame-drop");
6274        }
6275        info->mStatus = BufferInfo::OWNED_BY_US;
6276    }
6277
6278    PortMode mode = getPortMode(kPortIndexOutput);
6279
6280    switch (mode) {
6281        case KEEP_BUFFERS:
6282        {
6283            // XXX fishy, revisit!!! What about the FREE_BUFFERS case below?
6284
6285            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
6286                // We cannot resubmit the buffer we just rendered, dequeue
6287                // the spare instead.
6288
6289                info = mCodec->dequeueBufferFromNativeWindow();
6290            }
6291            break;
6292        }
6293
6294        case RESUBMIT_BUFFERS:
6295        {
6296            if (!mCodec->mPortEOS[kPortIndexOutput]) {
6297                if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
6298                    // We cannot resubmit the buffer we just rendered, dequeue
6299                    // the spare instead.
6300
6301                    info = mCodec->dequeueBufferFromNativeWindow();
6302                }
6303
6304                if (info != NULL) {
6305                    ALOGV("[%s] calling fillBuffer %u",
6306                         mCodec->mComponentName.c_str(), info->mBufferID);
6307                    info->checkWriteFence("onOutputBufferDrained::RESUBMIT_BUFFERS");
6308                    status_t err = mCodec->fillBuffer(info);
6309                    if (err != OK) {
6310                        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6311                    }
6312                }
6313            }
6314            break;
6315        }
6316
6317        case FREE_BUFFERS:
6318        {
6319            status_t err = mCodec->freeBuffer(kPortIndexOutput, index);
6320            if (err != OK) {
6321                mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6322            }
6323            break;
6324        }
6325
6326        default:
6327            ALOGE("Invalid port mode: %d", mode);
6328            return;
6329    }
6330}
6331
6332////////////////////////////////////////////////////////////////////////////////
6333
6334ACodec::UninitializedState::UninitializedState(ACodec *codec)
6335    : BaseState(codec) {
6336}
6337
6338void ACodec::UninitializedState::stateEntered() {
6339    ALOGV("Now uninitialized");
6340
6341    if (mDeathNotifier != NULL) {
6342        if (mCodec->mOMXNode != NULL) {
6343            auto tOmxNode = mCodec->mOMXNode->getHalInterface();
6344            tOmxNode->unlinkToDeath(mDeathNotifier);
6345        }
6346        mDeathNotifier.clear();
6347    }
6348
6349    mCodec->mUsingNativeWindow = false;
6350    mCodec->mNativeWindow.clear();
6351    mCodec->mNativeWindowUsageBits = 0;
6352    mCodec->mOMX.clear();
6353    mCodec->mOMXNode.clear();
6354    mCodec->mFlags = 0;
6355    mCodec->mPortMode[kPortIndexInput] = IOMX::kPortModePresetByteBuffer;
6356    mCodec->mPortMode[kPortIndexOutput] = IOMX::kPortModePresetByteBuffer;
6357    mCodec->mConverter[0].clear();
6358    mCodec->mConverter[1].clear();
6359    mCodec->mComponentName.clear();
6360}
6361
6362bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
6363    bool handled = false;
6364
6365    switch (msg->what()) {
6366        case ACodec::kWhatSetup:
6367        {
6368            onSetup(msg);
6369
6370            handled = true;
6371            break;
6372        }
6373
6374        case ACodec::kWhatAllocateComponent:
6375        {
6376            onAllocateComponent(msg);
6377            handled = true;
6378            break;
6379        }
6380
6381        case ACodec::kWhatShutdown:
6382        {
6383            int32_t keepComponentAllocated;
6384            CHECK(msg->findInt32(
6385                        "keepComponentAllocated", &keepComponentAllocated));
6386            ALOGW_IF(keepComponentAllocated,
6387                     "cannot keep component allocated on shutdown in Uninitialized state");
6388            if (keepComponentAllocated) {
6389                mCodec->mCallback->onStopCompleted();
6390            } else {
6391                mCodec->mCallback->onReleaseCompleted();
6392            }
6393            handled = true;
6394            break;
6395        }
6396
6397        case ACodec::kWhatFlush:
6398        {
6399            mCodec->mCallback->onFlushCompleted();
6400            handled = true;
6401            break;
6402        }
6403
6404        case ACodec::kWhatReleaseCodecInstance:
6405        {
6406            // nothing to do, as we have already signaled shutdown
6407            handled = true;
6408            break;
6409        }
6410
6411        default:
6412            return BaseState::onMessageReceived(msg);
6413    }
6414
6415    return handled;
6416}
6417
6418void ACodec::UninitializedState::onSetup(
6419        const sp<AMessage> &msg) {
6420    if (onAllocateComponent(msg)
6421            && mCodec->mLoadedState->onConfigureComponent(msg)) {
6422        mCodec->mLoadedState->onStart();
6423    }
6424}
6425
6426bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
6427    ALOGV("onAllocateComponent");
6428
6429    CHECK(mCodec->mOMXNode == NULL);
6430
6431    sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec);
6432
6433    sp<RefBase> obj;
6434    CHECK(msg->findObject("codecInfo", &obj));
6435    sp<MediaCodecInfo> info = (MediaCodecInfo *)obj.get();
6436    if (info == nullptr) {
6437        ALOGE("Unexpected nullptr for codec information");
6438        mCodec->signalError(OMX_ErrorUndefined, UNKNOWN_ERROR);
6439        return false;
6440    }
6441    AString owner = (info->getOwnerName() == nullptr) ? "default" : info->getOwnerName();
6442
6443    AString componentName;
6444    CHECK(msg->findString("componentName", &componentName));
6445
6446    sp<CodecObserver> observer = new CodecObserver;
6447    sp<IOMX> omx;
6448    sp<IOMXNode> omxNode;
6449
6450    status_t err = NAME_NOT_FOUND;
6451    OMXClient client;
6452    if (client.connect(owner.c_str()) != OK) {
6453        mCodec->signalError(OMX_ErrorUndefined, NO_INIT);
6454        return false;
6455    }
6456    omx = client.interface();
6457
6458    pid_t tid = gettid();
6459    int prevPriority = androidGetThreadPriority(tid);
6460    androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
6461    err = omx->allocateNode(componentName.c_str(), observer, &omxNode);
6462    androidSetThreadPriority(tid, prevPriority);
6463
6464    if (err != OK) {
6465        ALOGE("Unable to instantiate codec '%s' with err %#x.", componentName.c_str(), err);
6466
6467        mCodec->signalError((OMX_ERRORTYPE)err, makeNoSideEffectStatus(err));
6468        return false;
6469    }
6470
6471    mDeathNotifier = new DeathNotifier(notify);
6472    auto tOmxNode = omxNode->getHalInterface();
6473    if (!tOmxNode->linkToDeath(mDeathNotifier, 0)) {
6474        mDeathNotifier.clear();
6475    }
6476
6477    notify = new AMessage(kWhatOMXMessageList, mCodec);
6478    notify->setInt32("generation", ++mCodec->mNodeGeneration);
6479    observer->setNotificationMessage(notify);
6480
6481    mCodec->mComponentName = componentName;
6482    mCodec->mRenderTracker.setComponentName(componentName);
6483    mCodec->mFlags = 0;
6484
6485    if (componentName.endsWith(".secure")) {
6486        mCodec->mFlags |= kFlagIsSecure;
6487        mCodec->mFlags |= kFlagIsGrallocUsageProtected;
6488        mCodec->mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
6489    }
6490
6491    mCodec->mOMX = omx;
6492    mCodec->mOMXNode = omxNode;
6493    mCodec->mCallback->onComponentAllocated(mCodec->mComponentName.c_str());
6494    mCodec->changeState(mCodec->mLoadedState);
6495
6496    return true;
6497}
6498
6499////////////////////////////////////////////////////////////////////////////////
6500
6501ACodec::LoadedState::LoadedState(ACodec *codec)
6502    : BaseState(codec) {
6503}
6504
6505void ACodec::LoadedState::stateEntered() {
6506    ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
6507
6508    mCodec->mPortEOS[kPortIndexInput] =
6509        mCodec->mPortEOS[kPortIndexOutput] = false;
6510
6511    mCodec->mInputEOSResult = OK;
6512
6513    mCodec->mDequeueCounter = 0;
6514    mCodec->mMetadataBuffersToSubmit = 0;
6515    mCodec->mRepeatFrameDelayUs = -1ll;
6516    mCodec->mInputFormat.clear();
6517    mCodec->mOutputFormat.clear();
6518    mCodec->mBaseOutputFormat.clear();
6519    mCodec->mGraphicBufferSource.clear();
6520
6521    if (mCodec->mShutdownInProgress) {
6522        bool keepComponentAllocated = mCodec->mKeepComponentAllocated;
6523
6524        mCodec->mShutdownInProgress = false;
6525        mCodec->mKeepComponentAllocated = false;
6526
6527        onShutdown(keepComponentAllocated);
6528    }
6529    mCodec->mExplicitShutdown = false;
6530
6531    mCodec->processDeferredMessages();
6532}
6533
6534void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) {
6535    if (!keepComponentAllocated) {
6536        (void)mCodec->mOMXNode->freeNode();
6537
6538        mCodec->changeState(mCodec->mUninitializedState);
6539    }
6540
6541    if (mCodec->mExplicitShutdown) {
6542        if (keepComponentAllocated) {
6543            mCodec->mCallback->onStopCompleted();
6544        } else {
6545            mCodec->mCallback->onReleaseCompleted();
6546        }
6547        mCodec->mExplicitShutdown = false;
6548    }
6549}
6550
6551bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) {
6552    bool handled = false;
6553
6554    switch (msg->what()) {
6555        case ACodec::kWhatConfigureComponent:
6556        {
6557            onConfigureComponent(msg);
6558            handled = true;
6559            break;
6560        }
6561
6562        case ACodec::kWhatCreateInputSurface:
6563        {
6564            onCreateInputSurface(msg);
6565            handled = true;
6566            break;
6567        }
6568
6569        case ACodec::kWhatSetInputSurface:
6570        {
6571            onSetInputSurface(msg);
6572            handled = true;
6573            break;
6574        }
6575
6576        case ACodec::kWhatStart:
6577        {
6578            onStart();
6579            handled = true;
6580            break;
6581        }
6582
6583        case ACodec::kWhatShutdown:
6584        {
6585            int32_t keepComponentAllocated;
6586            CHECK(msg->findInt32(
6587                        "keepComponentAllocated", &keepComponentAllocated));
6588
6589            mCodec->mExplicitShutdown = true;
6590            onShutdown(keepComponentAllocated);
6591
6592            handled = true;
6593            break;
6594        }
6595
6596        case ACodec::kWhatFlush:
6597        {
6598            mCodec->mCallback->onFlushCompleted();
6599            handled = true;
6600            break;
6601        }
6602
6603        default:
6604            return BaseState::onMessageReceived(msg);
6605    }
6606
6607    return handled;
6608}
6609
6610bool ACodec::LoadedState::onConfigureComponent(
6611        const sp<AMessage> &msg) {
6612    ALOGV("onConfigureComponent");
6613
6614    CHECK(mCodec->mOMXNode != NULL);
6615
6616    status_t err = OK;
6617    AString mime;
6618    if (!msg->findString("mime", &mime)) {
6619        err = BAD_VALUE;
6620    } else {
6621        err = mCodec->configureCodec(mime.c_str(), msg);
6622    }
6623    if (err != OK) {
6624        ALOGE("[%s] configureCodec returning error %d",
6625              mCodec->mComponentName.c_str(), err);
6626
6627        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6628        return false;
6629    }
6630
6631    mCodec->mCallback->onComponentConfigured(mCodec->mInputFormat, mCodec->mOutputFormat);
6632
6633    return true;
6634}
6635
6636status_t ACodec::LoadedState::setupInputSurface() {
6637    if (mCodec->mGraphicBufferSource == NULL) {
6638        return BAD_VALUE;
6639    }
6640
6641    android_dataspace dataSpace;
6642    status_t err =
6643        mCodec->setInitialColorAspectsForVideoEncoderSurfaceAndGetDataSpace(&dataSpace);
6644    if (err != OK) {
6645        ALOGE("Failed to get default data space");
6646        return err;
6647    }
6648
6649    err = statusFromBinderStatus(
6650            mCodec->mGraphicBufferSource->configure(mCodec->mOMXNode, dataSpace));
6651    if (err != OK) {
6652        ALOGE("[%s] Unable to configure for node (err %d)",
6653              mCodec->mComponentName.c_str(), err);
6654        return err;
6655    }
6656
6657    if (mCodec->mRepeatFrameDelayUs > 0ll) {
6658        err = statusFromBinderStatus(
6659                mCodec->mGraphicBufferSource->setRepeatPreviousFrameDelayUs(
6660                        mCodec->mRepeatFrameDelayUs));
6661
6662        if (err != OK) {
6663            ALOGE("[%s] Unable to configure option to repeat previous "
6664                  "frames (err %d)",
6665                  mCodec->mComponentName.c_str(), err);
6666            return err;
6667        }
6668    }
6669
6670    if (mCodec->mMaxPtsGapUs > 0ll) {
6671        OMX_PARAM_U32TYPE maxPtsGapParams;
6672        InitOMXParams(&maxPtsGapParams);
6673        maxPtsGapParams.nPortIndex = kPortIndexInput;
6674        maxPtsGapParams.nU32 = (uint32_t) mCodec->mMaxPtsGapUs;
6675
6676        err = mCodec->mOMXNode->setParameter(
6677                (OMX_INDEXTYPE)OMX_IndexParamMaxFrameDurationForBitrateControl,
6678                &maxPtsGapParams, sizeof(maxPtsGapParams));
6679
6680        if (err != OK) {
6681            ALOGE("[%s] Unable to configure max timestamp gap (err %d)",
6682                    mCodec->mComponentName.c_str(), err);
6683            return err;
6684        }
6685    }
6686
6687    if (mCodec->mMaxFps > 0) {
6688        err = statusFromBinderStatus(
6689                mCodec->mGraphicBufferSource->setMaxFps(mCodec->mMaxFps));
6690
6691        if (err != OK) {
6692            ALOGE("[%s] Unable to configure max fps (err %d)",
6693                    mCodec->mComponentName.c_str(), err);
6694            return err;
6695        }
6696    }
6697
6698    if (mCodec->mCaptureFps > 0. && mCodec->mFps > 0.) {
6699        err = statusFromBinderStatus(
6700                mCodec->mGraphicBufferSource->setTimeLapseConfig(
6701                        mCodec->mFps, mCodec->mCaptureFps));
6702
6703        if (err != OK) {
6704            ALOGE("[%s] Unable to configure time lapse (err %d)",
6705                    mCodec->mComponentName.c_str(), err);
6706            return err;
6707        }
6708    }
6709
6710    if (mCodec->mCreateInputBuffersSuspended) {
6711        err = statusFromBinderStatus(
6712                mCodec->mGraphicBufferSource->setSuspend(true, -1));
6713
6714        if (err != OK) {
6715            ALOGE("[%s] Unable to configure option to suspend (err %d)",
6716                  mCodec->mComponentName.c_str(), err);
6717            return err;
6718        }
6719    }
6720
6721    uint32_t usageBits;
6722    if (mCodec->mOMXNode->getParameter(
6723            (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
6724            &usageBits, sizeof(usageBits)) == OK) {
6725        mCodec->mInputFormat->setInt32(
6726                "using-sw-read-often", !!(usageBits & GRALLOC_USAGE_SW_READ_OFTEN));
6727    }
6728
6729    sp<ABuffer> colorAspectsBuffer;
6730    if (mCodec->mInputFormat->findBuffer("android._color-aspects", &colorAspectsBuffer)) {
6731        if (colorAspectsBuffer->size() != sizeof(ColorAspects)) {
6732            return INVALID_OPERATION;
6733        }
6734
6735        err = statusFromBinderStatus(
6736                mCodec->mGraphicBufferSource->setColorAspects(ColorUtils::packToU32(
6737                        *(ColorAspects *)colorAspectsBuffer->base())));
6738
6739        if (err != OK) {
6740            ALOGE("[%s] Unable to configure color aspects (err %d)",
6741                  mCodec->mComponentName.c_str(), err);
6742            return err;
6743        }
6744    }
6745    return OK;
6746}
6747
6748void ACodec::LoadedState::onCreateInputSurface(
6749        const sp<AMessage> & /* msg */) {
6750    ALOGV("onCreateInputSurface");
6751
6752    sp<IGraphicBufferProducer> bufferProducer;
6753    status_t err = mCodec->mOMX->createInputSurface(
6754            &bufferProducer, &mCodec->mGraphicBufferSource);
6755
6756    if (err == OK) {
6757        err = setupInputSurface();
6758    }
6759
6760    if (err == OK) {
6761        mCodec->mCallback->onInputSurfaceCreated(
6762                mCodec->mInputFormat,
6763                mCodec->mOutputFormat,
6764                new BufferProducerWrapper(bufferProducer));
6765    } else {
6766        // Can't use mCodec->signalError() here -- MediaCodec won't forward
6767        // the error through because it's in the "configured" state.  We
6768        // send a kWhatInputSurfaceCreated with an error value instead.
6769        ALOGE("[%s] onCreateInputSurface returning error %d",
6770                mCodec->mComponentName.c_str(), err);
6771        mCodec->mCallback->onInputSurfaceCreationFailed(err);
6772    }
6773}
6774
6775void ACodec::LoadedState::onSetInputSurface(const sp<AMessage> &msg) {
6776    ALOGV("onSetInputSurface");
6777
6778    sp<RefBase> obj;
6779    CHECK(msg->findObject("input-surface", &obj));
6780    sp<PersistentSurface> surface = static_cast<PersistentSurface *>(obj.get());
6781    mCodec->mGraphicBufferSource = surface->getBufferSource();
6782
6783    status_t err = setupInputSurface();
6784
6785    if (err == OK) {
6786        mCodec->mCallback->onInputSurfaceAccepted(
6787                mCodec->mInputFormat, mCodec->mOutputFormat);
6788    } else {
6789        // Can't use mCodec->signalError() here -- MediaCodec won't forward
6790        // the error through because it's in the "configured" state.  We
6791        // send a kWhatInputSurfaceAccepted with an error value instead.
6792        ALOGE("[%s] onSetInputSurface returning error %d",
6793                mCodec->mComponentName.c_str(), err);
6794        mCodec->mCallback->onInputSurfaceDeclined(err);
6795    }
6796}
6797
6798void ACodec::LoadedState::onStart() {
6799    ALOGV("onStart");
6800
6801    status_t err = mCodec->mOMXNode->sendCommand(OMX_CommandStateSet, OMX_StateIdle);
6802    if (err != OK) {
6803        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6804    } else {
6805        mCodec->changeState(mCodec->mLoadedToIdleState);
6806    }
6807}
6808
6809////////////////////////////////////////////////////////////////////////////////
6810
6811ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec)
6812    : BaseState(codec) {
6813}
6814
6815void ACodec::LoadedToIdleState::stateEntered() {
6816    ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
6817
6818    status_t err;
6819    if ((err = allocateBuffers()) != OK) {
6820        ALOGE("Failed to allocate buffers after transitioning to IDLE state "
6821             "(error 0x%08x)",
6822             err);
6823
6824        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6825
6826        mCodec->mOMXNode->sendCommand(
6827                OMX_CommandStateSet, OMX_StateLoaded);
6828        if (mCodec->allYourBuffersAreBelongToUs(kPortIndexInput)) {
6829            mCodec->freeBuffersOnPort(kPortIndexInput);
6830        }
6831        if (mCodec->allYourBuffersAreBelongToUs(kPortIndexOutput)) {
6832            mCodec->freeBuffersOnPort(kPortIndexOutput);
6833        }
6834
6835        mCodec->changeState(mCodec->mLoadedState);
6836    }
6837}
6838
6839status_t ACodec::LoadedToIdleState::allocateBuffers() {
6840    status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput);
6841    if (err != OK) {
6842        return err;
6843    }
6844
6845    err = mCodec->allocateBuffersOnPort(kPortIndexOutput);
6846    if (err != OK) {
6847        return err;
6848    }
6849
6850    mCodec->mCallback->onStartCompleted();
6851
6852    return OK;
6853}
6854
6855bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
6856    switch (msg->what()) {
6857        case kWhatSetParameters:
6858        case kWhatShutdown:
6859        {
6860            mCodec->deferMessage(msg);
6861            return true;
6862        }
6863
6864        case kWhatSignalEndOfInputStream:
6865        {
6866            mCodec->onSignalEndOfInputStream();
6867            return true;
6868        }
6869
6870        case kWhatResume:
6871        {
6872            // We'll be active soon enough.
6873            return true;
6874        }
6875
6876        case kWhatFlush:
6877        {
6878            // We haven't even started yet, so we're flushed alright...
6879            mCodec->mCallback->onFlushCompleted();
6880            return true;
6881        }
6882
6883        default:
6884            return BaseState::onMessageReceived(msg);
6885    }
6886}
6887
6888bool ACodec::LoadedToIdleState::onOMXEvent(
6889        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
6890    switch (event) {
6891        case OMX_EventCmdComplete:
6892        {
6893            status_t err = OK;
6894            if (data1 != (OMX_U32)OMX_CommandStateSet
6895                    || data2 != (OMX_U32)OMX_StateIdle) {
6896                ALOGE("Unexpected command completion in LoadedToIdleState: %s(%u) %s(%u)",
6897                        asString((OMX_COMMANDTYPE)data1), data1,
6898                        asString((OMX_STATETYPE)data2), data2);
6899                err = FAILED_TRANSACTION;
6900            }
6901
6902            if (err == OK) {
6903                err = mCodec->mOMXNode->sendCommand(
6904                    OMX_CommandStateSet, OMX_StateExecuting);
6905            }
6906
6907            if (err != OK) {
6908                mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6909            } else {
6910                mCodec->changeState(mCodec->mIdleToExecutingState);
6911            }
6912
6913            return true;
6914        }
6915
6916        default:
6917            return BaseState::onOMXEvent(event, data1, data2);
6918    }
6919}
6920
6921////////////////////////////////////////////////////////////////////////////////
6922
6923ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec)
6924    : BaseState(codec) {
6925}
6926
6927void ACodec::IdleToExecutingState::stateEntered() {
6928    ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
6929}
6930
6931bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
6932    switch (msg->what()) {
6933        case kWhatSetParameters:
6934        case kWhatShutdown:
6935        {
6936            mCodec->deferMessage(msg);
6937            return true;
6938        }
6939
6940        case kWhatResume:
6941        {
6942            // We'll be active soon enough.
6943            return true;
6944        }
6945
6946        case kWhatFlush:
6947        {
6948            // We haven't even started yet, so we're flushed alright...
6949            mCodec->mCallback->onFlushCompleted();
6950            return true;
6951        }
6952
6953        case kWhatSignalEndOfInputStream:
6954        {
6955            mCodec->onSignalEndOfInputStream();
6956            return true;
6957        }
6958
6959        default:
6960            return BaseState::onMessageReceived(msg);
6961    }
6962}
6963
6964bool ACodec::IdleToExecutingState::onOMXEvent(
6965        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
6966    switch (event) {
6967        case OMX_EventCmdComplete:
6968        {
6969            if (data1 != (OMX_U32)OMX_CommandStateSet
6970                    || data2 != (OMX_U32)OMX_StateExecuting) {
6971                ALOGE("Unexpected command completion in IdleToExecutingState: %s(%u) %s(%u)",
6972                        asString((OMX_COMMANDTYPE)data1), data1,
6973                        asString((OMX_STATETYPE)data2), data2);
6974                mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
6975                return true;
6976            }
6977
6978            mCodec->mExecutingState->resume();
6979            mCodec->changeState(mCodec->mExecutingState);
6980
6981            return true;
6982        }
6983
6984        default:
6985            return BaseState::onOMXEvent(event, data1, data2);
6986    }
6987}
6988
6989////////////////////////////////////////////////////////////////////////////////
6990
6991ACodec::ExecutingState::ExecutingState(ACodec *codec)
6992    : BaseState(codec),
6993      mActive(false) {
6994}
6995
6996ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode(
6997        OMX_U32 /* portIndex */) {
6998    return RESUBMIT_BUFFERS;
6999}
7000
7001void ACodec::ExecutingState::submitOutputMetaBuffers() {
7002    // submit as many buffers as there are input buffers with the codec
7003    // in case we are in port reconfiguring
7004    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
7005        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
7006
7007        if (info->mStatus == BufferInfo::OWNED_BY_COMPONENT) {
7008            if (mCodec->submitOutputMetadataBuffer() != OK)
7009                break;
7010        }
7011    }
7012
7013    // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
7014    mCodec->signalSubmitOutputMetadataBufferIfEOS_workaround();
7015}
7016
7017void ACodec::ExecutingState::submitRegularOutputBuffers() {
7018    bool failed = false;
7019    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
7020        BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
7021
7022        if (mCodec->mNativeWindow != NULL) {
7023            if (info->mStatus != BufferInfo::OWNED_BY_US
7024                    && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
7025                ALOGE("buffers should be owned by us or the surface");
7026                failed = true;
7027                break;
7028            }
7029
7030            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
7031                continue;
7032            }
7033        } else {
7034            if (info->mStatus != BufferInfo::OWNED_BY_US) {
7035                ALOGE("buffers should be owned by us");
7036                failed = true;
7037                break;
7038            }
7039        }
7040
7041        ALOGV("[%s] calling fillBuffer %u", mCodec->mComponentName.c_str(), info->mBufferID);
7042
7043        info->checkWriteFence("submitRegularOutputBuffers");
7044        status_t err = mCodec->fillBuffer(info);
7045        if (err != OK) {
7046            failed = true;
7047            break;
7048        }
7049    }
7050
7051    if (failed) {
7052        mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
7053    }
7054}
7055
7056void ACodec::ExecutingState::submitOutputBuffers() {
7057    submitRegularOutputBuffers();
7058    if (mCodec->storingMetadataInDecodedBuffers()) {
7059        submitOutputMetaBuffers();
7060    }
7061}
7062
7063void ACodec::ExecutingState::resume() {
7064    if (mActive) {
7065        ALOGV("[%s] We're already active, no need to resume.", mCodec->mComponentName.c_str());
7066        return;
7067    }
7068
7069    submitOutputBuffers();
7070
7071    // Post all available input buffers
7072    if (mCodec->mBuffers[kPortIndexInput].size() == 0u) {
7073        ALOGW("[%s] we don't have any input buffers to resume", mCodec->mComponentName.c_str());
7074    }
7075
7076    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); i++) {
7077        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
7078        if (info->mStatus == BufferInfo::OWNED_BY_US) {
7079            postFillThisBuffer(info);
7080        }
7081    }
7082
7083    mActive = true;
7084}
7085
7086void ACodec::ExecutingState::stateEntered() {
7087    ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
7088    mCodec->mRenderTracker.clear(systemTime(CLOCK_MONOTONIC));
7089    mCodec->processDeferredMessages();
7090}
7091
7092bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) {
7093    bool handled = false;
7094
7095    switch (msg->what()) {
7096        case kWhatShutdown:
7097        {
7098            int32_t keepComponentAllocated;
7099            CHECK(msg->findInt32(
7100                        "keepComponentAllocated", &keepComponentAllocated));
7101
7102            mCodec->mShutdownInProgress = true;
7103            mCodec->mExplicitShutdown = true;
7104            mCodec->mKeepComponentAllocated = keepComponentAllocated;
7105
7106            mActive = false;
7107
7108            status_t err = mCodec->mOMXNode->sendCommand(
7109                    OMX_CommandStateSet, OMX_StateIdle);
7110            if (err != OK) {
7111                if (keepComponentAllocated) {
7112                    mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
7113                }
7114                // TODO: do some recovery here.
7115            } else {
7116                mCodec->changeState(mCodec->mExecutingToIdleState);
7117            }
7118
7119            handled = true;
7120            break;
7121        }
7122
7123        case kWhatFlush:
7124        {
7125            ALOGV("[%s] ExecutingState flushing now "
7126                 "(codec owns %zu/%zu input, %zu/%zu output).",
7127                    mCodec->mComponentName.c_str(),
7128                    mCodec->countBuffersOwnedByComponent(kPortIndexInput),
7129                    mCodec->mBuffers[kPortIndexInput].size(),
7130                    mCodec->countBuffersOwnedByComponent(kPortIndexOutput),
7131                    mCodec->mBuffers[kPortIndexOutput].size());
7132
7133            mActive = false;
7134
7135            status_t err = mCodec->mOMXNode->sendCommand(OMX_CommandFlush, OMX_ALL);
7136            if (err != OK) {
7137                mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
7138            } else {
7139                mCodec->changeState(mCodec->mFlushingState);
7140            }
7141
7142            handled = true;
7143            break;
7144        }
7145
7146        case kWhatResume:
7147        {
7148            resume();
7149
7150            handled = true;
7151            break;
7152        }
7153
7154        case kWhatRequestIDRFrame:
7155        {
7156            status_t err = mCodec->requestIDRFrame();
7157            if (err != OK) {
7158                ALOGW("Requesting an IDR frame failed.");
7159            }
7160
7161            handled = true;
7162            break;
7163        }
7164
7165        case kWhatSetParameters:
7166        {
7167            sp<AMessage> params;
7168            CHECK(msg->findMessage("params", &params));
7169
7170            status_t err = mCodec->setParameters(params);
7171
7172            sp<AMessage> reply;
7173            if (msg->findMessage("reply", &reply)) {
7174                reply->setInt32("err", err);
7175                reply->post();
7176            }
7177
7178            handled = true;
7179            break;
7180        }
7181
7182        case ACodec::kWhatSignalEndOfInputStream:
7183        {
7184            mCodec->onSignalEndOfInputStream();
7185            handled = true;
7186            break;
7187        }
7188
7189        // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
7190        case kWhatSubmitOutputMetadataBufferIfEOS:
7191        {
7192            if (mCodec->mPortEOS[kPortIndexInput] &&
7193                    !mCodec->mPortEOS[kPortIndexOutput]) {
7194                status_t err = mCodec->submitOutputMetadataBuffer();
7195                if (err == OK) {
7196                    mCodec->signalSubmitOutputMetadataBufferIfEOS_workaround();
7197                }
7198            }
7199            return true;
7200        }
7201
7202        default:
7203            handled = BaseState::onMessageReceived(msg);
7204            break;
7205    }
7206
7207    return handled;
7208}
7209
7210status_t ACodec::setParameters(const sp<AMessage> &params) {
7211    int32_t videoBitrate;
7212    if (params->findInt32("video-bitrate", &videoBitrate)) {
7213        OMX_VIDEO_CONFIG_BITRATETYPE configParams;
7214        InitOMXParams(&configParams);
7215        configParams.nPortIndex = kPortIndexOutput;
7216        configParams.nEncodeBitrate = videoBitrate;
7217
7218        status_t err = mOMXNode->setConfig(
7219                OMX_IndexConfigVideoBitrate,
7220                &configParams,
7221                sizeof(configParams));
7222
7223        if (err != OK) {
7224            ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d",
7225                   videoBitrate, err);
7226
7227            return err;
7228        }
7229    }
7230
7231    int64_t timeOffsetUs;
7232    if (params->findInt64("time-offset-us", &timeOffsetUs)) {
7233        if (mGraphicBufferSource == NULL) {
7234            ALOGE("[%s] Invalid to set input buffer time offset without surface",
7235                    mComponentName.c_str());
7236            return INVALID_OPERATION;
7237        }
7238
7239        status_t err = statusFromBinderStatus(
7240                mGraphicBufferSource->setTimeOffsetUs(timeOffsetUs));
7241
7242        if (err != OK) {
7243            ALOGE("[%s] Unable to set input buffer time offset (err %d)",
7244                mComponentName.c_str(),
7245                err);
7246            return err;
7247        }
7248    }
7249
7250    int64_t skipFramesBeforeUs;
7251    if (params->findInt64("skip-frames-before", &skipFramesBeforeUs)) {
7252        if (mGraphicBufferSource == NULL) {
7253            ALOGE("[%s] Invalid to set start time without surface",
7254                    mComponentName.c_str());
7255            return INVALID_OPERATION;
7256        }
7257
7258        status_t err = statusFromBinderStatus(
7259                mGraphicBufferSource->setStartTimeUs(skipFramesBeforeUs));
7260
7261        if (err != OK) {
7262            ALOGE("Failed to set parameter 'skip-frames-before' (err %d)", err);
7263            return err;
7264        }
7265    }
7266
7267    int32_t dropInputFrames;
7268    if (params->findInt32("drop-input-frames", &dropInputFrames)) {
7269        if (mGraphicBufferSource == NULL) {
7270            ALOGE("[%s] Invalid to set suspend without surface",
7271                    mComponentName.c_str());
7272            return INVALID_OPERATION;
7273        }
7274
7275        int64_t suspendStartTimeUs = -1;
7276        (void) params->findInt64("drop-start-time-us", &suspendStartTimeUs);
7277        status_t err = statusFromBinderStatus(
7278                mGraphicBufferSource->setSuspend(dropInputFrames != 0, suspendStartTimeUs));
7279
7280        if (err != OK) {
7281            ALOGE("Failed to set parameter 'drop-input-frames' (err %d)", err);
7282            return err;
7283        }
7284    }
7285
7286    int64_t stopTimeUs;
7287    if (params->findInt64("stop-time-us", &stopTimeUs)) {
7288        if (mGraphicBufferSource == NULL) {
7289            ALOGE("[%s] Invalid to set stop time without surface",
7290                    mComponentName.c_str());
7291            return INVALID_OPERATION;
7292        }
7293        status_t err = statusFromBinderStatus(
7294                mGraphicBufferSource->setStopTimeUs(stopTimeUs));
7295
7296        if (err != OK) {
7297            ALOGE("Failed to set parameter 'stop-time-us' (err %d)", err);
7298            return err;
7299        }
7300
7301        int64_t stopTimeOffsetUs;
7302        err = statusFromBinderStatus(
7303                mGraphicBufferSource->getStopTimeOffsetUs(&stopTimeOffsetUs));
7304
7305        if (err != OK) {
7306            ALOGE("Failed to get stop time offset (err %d)", err);
7307            return err;
7308        }
7309        mInputFormat->setInt64("android._stop-time-offset-us", stopTimeOffsetUs);
7310    }
7311
7312    int32_t dummy;
7313    if (params->findInt32("request-sync", &dummy)) {
7314        status_t err = requestIDRFrame();
7315
7316        if (err != OK) {
7317            ALOGE("Requesting a sync frame failed w/ err %d", err);
7318            return err;
7319        }
7320    }
7321
7322    int32_t rateInt = -1;
7323    float rateFloat = -1;
7324    if (!params->findFloat("operating-rate", &rateFloat)) {
7325        params->findInt32("operating-rate", &rateInt);
7326        rateFloat = (float) rateInt; // 16MHz (FLINTMAX) is OK for upper bound.
7327    }
7328    if (rateFloat > 0) {
7329        status_t err = setOperatingRate(rateFloat, mIsVideo);
7330        if (err != OK) {
7331            ALOGI("Failed to set parameter 'operating-rate' (err %d)", err);
7332        }
7333    }
7334
7335    int32_t intraRefreshPeriod = 0;
7336    if (params->findInt32("intra-refresh-period", &intraRefreshPeriod)
7337            && intraRefreshPeriod > 0) {
7338        status_t err = setIntraRefreshPeriod(intraRefreshPeriod, false);
7339        if (err != OK) {
7340            ALOGI("[%s] failed setIntraRefreshPeriod. Failure is fine since this key is optional",
7341                    mComponentName.c_str());
7342            err = OK;
7343        }
7344    }
7345
7346    int32_t latency = 0;
7347    if (params->findInt32("latency", &latency) && latency > 0) {
7348        status_t err = setLatency(latency);
7349        if (err != OK) {
7350            ALOGI("[%s] failed setLatency. Failure is fine since this key is optional",
7351                    mComponentName.c_str());
7352            err = OK;
7353        }
7354    }
7355
7356    // Ignore errors as failure is expected for codecs that aren't video encoders.
7357    (void)configureTemporalLayers(params, false /* inConfigure */, mOutputFormat);
7358
7359    return setVendorParameters(params);
7360}
7361
7362// Removes trailing tags matching |tag| from |key| (e.g. a settings name). |minLength| specifies
7363// the minimum number of characters to keep in |key| (even if it has trailing tags).
7364// (Used to remove trailing 'value' tags in settings names, e.g. to normalize
7365// 'vendor.settingsX.value' to 'vendor.settingsX')
7366static void removeTrailingTags(char *key, size_t minLength, const char *tag) {
7367    size_t length = strlen(key);
7368    size_t tagLength = strlen(tag);
7369    while (length > minLength + tagLength
7370            && !strcmp(key + length - tagLength, tag)
7371            && key[length - tagLength - 1] == '.') {
7372        length -= tagLength + 1;
7373        key[length] = '\0';
7374    }
7375}
7376
7377/**
7378 * Struct encompassing a vendor extension config structure and a potential error status (in case
7379 * the structure is null). Used to iterate through vendor extensions.
7380 */
7381struct VendorExtension {
7382    OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *config;  // structure does not own config
7383    status_t status;
7384
7385    // create based on an error status
7386    VendorExtension(status_t s_ = NO_INIT) : config(nullptr), status(s_) { }
7387
7388    // create based on a successfully retrieved config structure
7389    VendorExtension(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *c_) : config(c_), status(OK) { }
7390};
7391
7392// class VendorExtensions;
7393/**
7394 * Forward iterator to enumerate vendor extensions supported by an OMX component.
7395 */
7396class VendorExtensionIterator {
7397//private:
7398    static constexpr size_t kLastIndex = ~(size_t)0; // last index marker
7399
7400    sp<IOMXNode> mNode;                   // component
7401    size_t mIndex;                        // current android extension index
7402    std::unique_ptr<uint8_t[]> mBacking;  // current extension's backing
7403    VendorExtension mCurrent;             // current extension
7404
7405    VendorExtensionIterator(const sp<IOMXNode> &node, size_t index)
7406        : mNode(node),
7407          mIndex(index) {
7408        mCurrent = retrieve();
7409    }
7410
7411    friend class VendorExtensions;
7412
7413public:
7414    // copy constructor
7415    VendorExtensionIterator(const VendorExtensionIterator &it)
7416        : VendorExtensionIterator(it.mNode, it.mIndex) { }
7417
7418    // retrieves the current extension pointed to by this iterator
7419    VendorExtension retrieve() {
7420        if (mIndex == kLastIndex) {
7421            return NO_INIT;
7422        }
7423
7424        // try with one param first, then retry if extension needs more than 1 param
7425        for (size_t paramSizeUsed = 1;; ) {
7426            if (paramSizeUsed > OMX_MAX_ANDROID_VENDOR_PARAMCOUNT) {
7427                return BAD_VALUE; // this prevents overflow in the following formula
7428            }
7429
7430            size_t size = sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE) +
7431                (paramSizeUsed - 1) * sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE::param);
7432            mBacking.reset(new uint8_t[size]);
7433            if (!mBacking) {
7434                return NO_MEMORY;
7435            }
7436
7437            OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *config =
7438                reinterpret_cast<OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *>(mBacking.get());
7439
7440            InitOMXParams(config);
7441            config->nSize = size;
7442            config->nIndex = mIndex;
7443            config->nParamSizeUsed = paramSizeUsed;
7444            status_t err = mNode->getConfig(
7445                    (OMX_INDEXTYPE)OMX_IndexConfigAndroidVendorExtension, config, size);
7446            if (err == OK && config->nParamCount > paramSizeUsed && paramSizeUsed == 1) {
7447                // reallocate if we need a bigger config
7448                paramSizeUsed = config->nParamCount;
7449                continue;
7450            } else if (err == NOT_ENOUGH_DATA
7451                   || (err != OK && mIndex == 0)) {
7452                // stop iterator on no-more signal, or if index is not at all supported
7453                mIndex = kLastIndex;
7454                return NO_INIT;
7455            } else if (err != OK) {
7456                return err;
7457            } else if (paramSizeUsed != config->nParamSizeUsed) {
7458                return BAD_VALUE; // component shall not modify size of nParam
7459            }
7460
7461            return config;
7462        }
7463    }
7464
7465    // returns extension pointed to by this iterator
7466    VendorExtension operator*() {
7467        return mCurrent;
7468    }
7469
7470    // prefix increment: move to next extension
7471    VendorExtensionIterator &operator++() { // prefix
7472        if (mIndex != kLastIndex) {
7473            ++mIndex;
7474            mCurrent = retrieve();
7475        }
7476        return *this;
7477    }
7478
7479    // iterator equality operators
7480    bool operator==(const VendorExtensionIterator &o) {
7481        return mNode == o.mNode && mIndex == o.mIndex;
7482    }
7483
7484    bool operator!=(const VendorExtensionIterator &o) {
7485        return !(*this == o);
7486    }
7487};
7488
7489/**
7490 * Iterable container for vendor extensions provided by a component
7491 */
7492class VendorExtensions {
7493//private:
7494    sp<IOMXNode> mNode;
7495
7496public:
7497    VendorExtensions(const sp<IOMXNode> &node)
7498        : mNode(node) {
7499    }
7500
7501    VendorExtensionIterator begin() {
7502        return VendorExtensionIterator(mNode, 0);
7503    }
7504
7505    VendorExtensionIterator end() {
7506        return VendorExtensionIterator(mNode, VendorExtensionIterator::kLastIndex);
7507    }
7508};
7509
7510status_t ACodec::setVendorParameters(const sp<AMessage> &params) {
7511    std::map<std::string, std::string> vendorKeys; // maps reduced name to actual name
7512    constexpr char prefix[] = "vendor.";
7513    constexpr size_t prefixLength = sizeof(prefix) - 1;
7514    // longest possible vendor param name
7515    char reducedKey[OMX_MAX_STRINGNAME_SIZE + OMX_MAX_STRINGVALUE_SIZE];
7516
7517    // identify all vendor keys to speed up search later and to detect vendor keys
7518    for (size_t i = params->countEntries(); i; --i) {
7519        AMessage::Type keyType;
7520        const char* key = params->getEntryNameAt(i - 1, &keyType);
7521        if (key != nullptr && !strncmp(key, prefix, prefixLength)
7522                // it is safe to limit format keys to the max vendor param size as we only
7523                // shorten parameter names by removing any trailing 'value' tags, and we
7524                // already remove the vendor prefix.
7525                && strlen(key + prefixLength) < sizeof(reducedKey)
7526                && (keyType == AMessage::kTypeInt32
7527                        || keyType == AMessage::kTypeInt64
7528                        || keyType == AMessage::kTypeString)) {
7529            strcpy(reducedKey, key + prefixLength);
7530            removeTrailingTags(reducedKey, 0, "value");
7531            auto existingKey = vendorKeys.find(reducedKey);
7532            if (existingKey != vendorKeys.end()) {
7533                ALOGW("[%s] vendor parameter '%s' aliases parameter '%s'",
7534                        mComponentName.c_str(), key, existingKey->second.c_str());
7535                // ignore for now
7536            }
7537            vendorKeys.emplace(reducedKey, key);
7538        }
7539    }
7540
7541    // don't bother component if we don't have vendor extensions as they may not have implemented
7542    // the android vendor extension support, which will lead to unnecessary OMX failure logs.
7543    if (vendorKeys.empty()) {
7544        return OK;
7545    }
7546
7547    char key[sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE::cName) +
7548            sizeof(OMX_CONFIG_ANDROID_VENDOR_PARAMTYPE::cKey)];
7549
7550    status_t finalError = OK;
7551
7552    // don't try again if component does not have vendor extensions
7553    if (mVendorExtensionsStatus == kExtensionsNone) {
7554        return OK;
7555    }
7556
7557    for (VendorExtension ext : VendorExtensions(mOMXNode)) {
7558        OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *config = ext.config;
7559        if (config == nullptr) {
7560            return ext.status;
7561        }
7562
7563        mVendorExtensionsStatus = kExtensionsExist;
7564
7565        config->cName[sizeof(config->cName) - 1] = '\0'; // null-terminate name
7566        strcpy(key, (const char *)config->cName);
7567        size_t nameLength = strlen(key);
7568        key[nameLength] = '.';
7569
7570        // don't set vendor extension if client has not provided any of its parameters
7571        // or if client simply unsets parameters that are already unset
7572        bool needToSet = false;
7573        for (size_t paramIndex = 0; paramIndex < config->nParamCount; ++paramIndex) {
7574            // null-terminate param key
7575            config->param[paramIndex].cKey[sizeof(config->param[0].cKey) - 1] = '\0';
7576            strcpy(key + nameLength + 1, (const char *)config->param[paramIndex].cKey);
7577            removeTrailingTags(key, nameLength, "value");
7578            auto existingKey = vendorKeys.find(key);
7579
7580            // don't touch (e.g. change) parameters that are not specified by client
7581            if (existingKey == vendorKeys.end()) {
7582                continue;
7583            }
7584
7585            bool wasSet = config->param[paramIndex].bSet;
7586            switch (config->param[paramIndex].eValueType) {
7587            case OMX_AndroidVendorValueInt32:
7588            {
7589                int32_t value;
7590                config->param[paramIndex].bSet =
7591                    (OMX_BOOL)params->findInt32(existingKey->second.c_str(), &value);
7592                if (config->param[paramIndex].bSet) {
7593                    config->param[paramIndex].nInt32 = value;
7594                }
7595                break;
7596            }
7597            case OMX_AndroidVendorValueInt64:
7598            {
7599                int64_t value;
7600                config->param[paramIndex].bSet =
7601                    (OMX_BOOL)params->findAsInt64(existingKey->second.c_str(), &value);
7602                if (config->param[paramIndex].bSet) {
7603                    config->param[paramIndex].nInt64 = value;
7604                }
7605                break;
7606            }
7607            case OMX_AndroidVendorValueString:
7608            {
7609                AString value;
7610                config->param[paramIndex].bSet =
7611                    (OMX_BOOL)params->findString(existingKey->second.c_str(), &value);
7612                if (config->param[paramIndex].bSet) {
7613                    strncpy((char *)config->param[paramIndex].cString, value.c_str(),
7614                            sizeof(OMX_CONFIG_ANDROID_VENDOR_PARAMTYPE::cString));
7615                }
7616                break;
7617            }
7618            default:
7619                ALOGW("[%s] vendor parameter '%s' is not a supported value",
7620                        mComponentName.c_str(), key);
7621                continue;
7622            }
7623            if (config->param[paramIndex].bSet || wasSet) {
7624                needToSet = true;
7625            }
7626        }
7627
7628        if (needToSet) {
7629            status_t err = mOMXNode->setConfig(
7630                    (OMX_INDEXTYPE)OMX_IndexConfigAndroidVendorExtension,
7631                    config, config->nSize);
7632            if (err != OK) {
7633                key[nameLength] = '\0';
7634                ALOGW("[%s] failed to set vendor extension '%s'", mComponentName.c_str(), key);
7635                // try to set each extension, and return first failure
7636                if (finalError == OK) {
7637                    finalError = err;
7638                }
7639            }
7640        }
7641    }
7642
7643    if (mVendorExtensionsStatus == kExtensionsUnchecked) {
7644        mVendorExtensionsStatus = kExtensionsNone;
7645    }
7646
7647    return finalError;
7648}
7649
7650status_t ACodec::getVendorParameters(OMX_U32 portIndex, sp<AMessage> &format) {
7651    constexpr char prefix[] = "vendor.";
7652    constexpr size_t prefixLength = sizeof(prefix) - 1;
7653    char key[sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE::cName) +
7654            sizeof(OMX_CONFIG_ANDROID_VENDOR_PARAMTYPE::cKey) + prefixLength];
7655    strcpy(key, prefix);
7656
7657    // don't try again if component does not have vendor extensions
7658    if (mVendorExtensionsStatus == kExtensionsNone) {
7659        return OK;
7660    }
7661
7662    for (VendorExtension ext : VendorExtensions(mOMXNode)) {
7663        OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *config = ext.config;
7664        if (config == nullptr) {
7665            return ext.status;
7666        }
7667
7668        mVendorExtensionsStatus = kExtensionsExist;
7669
7670        if (config->eDir != (portIndex == kPortIndexInput ? OMX_DirInput : OMX_DirOutput)) {
7671            continue;
7672        }
7673
7674        config->cName[sizeof(config->cName) - 1] = '\0'; // null-terminate name
7675        strcpy(key + prefixLength, (const char *)config->cName);
7676        size_t nameLength = strlen(key);
7677        key[nameLength] = '.';
7678
7679        for (size_t paramIndex = 0; paramIndex < config->nParamCount; ++paramIndex) {
7680            // null-terminate param key
7681            config->param[paramIndex].cKey[sizeof(config->param[0].cKey) - 1] = '\0';
7682            strcpy(key + nameLength + 1, (const char *)config->param[paramIndex].cKey);
7683            removeTrailingTags(key, nameLength, "value");
7684            if (config->param[paramIndex].bSet) {
7685                switch (config->param[paramIndex].eValueType) {
7686                case OMX_AndroidVendorValueInt32:
7687                {
7688                    format->setInt32(key, config->param[paramIndex].nInt32);
7689                    break;
7690                }
7691                case OMX_AndroidVendorValueInt64:
7692                {
7693                    format->setInt64(key, config->param[paramIndex].nInt64);
7694                    break;
7695                }
7696                case OMX_AndroidVendorValueString:
7697                {
7698                    config->param[paramIndex].cString[OMX_MAX_STRINGVALUE_SIZE - 1] = '\0';
7699                    format->setString(key, (const char *)config->param[paramIndex].cString);
7700                    break;
7701                }
7702                default:
7703                    ALOGW("vendor parameter %s is not a supported value", key);
7704                    continue;
7705                }
7706            }
7707        }
7708    }
7709
7710    if (mVendorExtensionsStatus == kExtensionsUnchecked) {
7711        mVendorExtensionsStatus = kExtensionsNone;
7712    }
7713
7714    return OK;
7715}
7716
7717void ACodec::onSignalEndOfInputStream() {
7718    status_t err = INVALID_OPERATION;
7719    if (mGraphicBufferSource != NULL) {
7720        err = statusFromBinderStatus(mGraphicBufferSource->signalEndOfInputStream());
7721    }
7722    mCallback->onSignaledInputEOS(err);
7723}
7724
7725void ACodec::forceStateTransition(int generation) {
7726    if (generation != mStateGeneration) {
7727        ALOGV("Ignoring stale force state transition message: #%d (now #%d)",
7728                generation, mStateGeneration);
7729        return;
7730    }
7731    ALOGE("State machine stuck");
7732    // Error must have already been signalled to the client.
7733
7734    // Deferred messages will be handled at LoadedState at the end of the
7735    // transition.
7736    mShutdownInProgress = true;
7737    // No shutdown complete callback at the end of the transition.
7738    mExplicitShutdown = false;
7739    mKeepComponentAllocated = true;
7740
7741    status_t err = mOMXNode->sendCommand(OMX_CommandStateSet, OMX_StateIdle);
7742    if (err != OK) {
7743        // TODO: do some recovery here.
7744    } else {
7745        changeState(mExecutingToIdleState);
7746    }
7747}
7748
7749bool ACodec::ExecutingState::onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano) {
7750    mCodec->onFrameRendered(mediaTimeUs, systemNano);
7751    return true;
7752}
7753
7754bool ACodec::ExecutingState::onOMXEvent(
7755        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
7756    switch (event) {
7757        case OMX_EventPortSettingsChanged:
7758        {
7759            CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
7760
7761            mCodec->onOutputFormatChanged();
7762
7763            if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
7764                mCodec->mMetadataBuffersToSubmit = 0;
7765                CHECK_EQ(mCodec->mOMXNode->sendCommand(
7766                            OMX_CommandPortDisable, kPortIndexOutput),
7767                         (status_t)OK);
7768
7769                mCodec->freeOutputBuffersNotOwnedByComponent();
7770
7771                mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
7772            } else if (data2 != OMX_IndexConfigCommonOutputCrop
7773                    && data2 != OMX_IndexConfigAndroidIntraRefresh) {
7774                ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08x",
7775                     mCodec->mComponentName.c_str(), data2);
7776            }
7777
7778            return true;
7779        }
7780
7781        case OMX_EventBufferFlag:
7782        {
7783            return true;
7784        }
7785
7786        default:
7787            return BaseState::onOMXEvent(event, data1, data2);
7788    }
7789}
7790
7791////////////////////////////////////////////////////////////////////////////////
7792
7793ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState(
7794        ACodec *codec)
7795    : BaseState(codec) {
7796}
7797
7798ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode(
7799        OMX_U32 portIndex) {
7800    if (portIndex == kPortIndexOutput) {
7801        return FREE_BUFFERS;
7802    }
7803
7804    CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput);
7805
7806    return RESUBMIT_BUFFERS;
7807}
7808
7809bool ACodec::OutputPortSettingsChangedState::onMessageReceived(
7810        const sp<AMessage> &msg) {
7811    bool handled = false;
7812
7813    switch (msg->what()) {
7814        case kWhatFlush:
7815        case kWhatShutdown: {
7816            if (mCodec->mFatalError) {
7817                sp<AMessage> msg = new AMessage(ACodec::kWhatForceStateTransition, mCodec);
7818                msg->setInt32("generation", mCodec->mStateGeneration);
7819                msg->post(3000000);
7820            }
7821            // fall-through
7822        }
7823        case kWhatResume:
7824        case kWhatSetParameters:
7825        {
7826            if (msg->what() == kWhatResume) {
7827                ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
7828            }
7829
7830            mCodec->deferMessage(msg);
7831            handled = true;
7832            break;
7833        }
7834
7835        case kWhatForceStateTransition:
7836        {
7837            int32_t generation = 0;
7838            CHECK(msg->findInt32("generation", &generation));
7839            mCodec->forceStateTransition(generation);
7840
7841            handled = true;
7842            break;
7843        }
7844
7845        default:
7846            handled = BaseState::onMessageReceived(msg);
7847            break;
7848    }
7849
7850    return handled;
7851}
7852
7853void ACodec::OutputPortSettingsChangedState::stateEntered() {
7854    ALOGV("[%s] Now handling output port settings change",
7855         mCodec->mComponentName.c_str());
7856}
7857
7858bool ACodec::OutputPortSettingsChangedState::onOMXFrameRendered(
7859        int64_t mediaTimeUs, nsecs_t systemNano) {
7860    mCodec->onFrameRendered(mediaTimeUs, systemNano);
7861    return true;
7862}
7863
7864bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
7865        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
7866    switch (event) {
7867        case OMX_EventCmdComplete:
7868        {
7869            if (data1 == (OMX_U32)OMX_CommandPortDisable) {
7870                if (data2 != (OMX_U32)kPortIndexOutput) {
7871                    ALOGW("ignoring EventCmdComplete CommandPortDisable for port %u", data2);
7872                    return false;
7873                }
7874
7875                ALOGV("[%s] Output port now disabled.", mCodec->mComponentName.c_str());
7876
7877                status_t err = OK;
7878                if (!mCodec->mBuffers[kPortIndexOutput].isEmpty()) {
7879                    ALOGE("disabled port should be empty, but has %zu buffers",
7880                            mCodec->mBuffers[kPortIndexOutput].size());
7881                    err = FAILED_TRANSACTION;
7882                } else {
7883                    mCodec->mAllocator[kPortIndexOutput].clear();
7884                }
7885
7886                if (err == OK) {
7887                    err = mCodec->mOMXNode->sendCommand(
7888                            OMX_CommandPortEnable, kPortIndexOutput);
7889                }
7890
7891                if (err == OK) {
7892                    err = mCodec->allocateBuffersOnPort(kPortIndexOutput);
7893                    ALOGE_IF(err != OK, "Failed to allocate output port buffers after port "
7894                            "reconfiguration: (%d)", err);
7895                    mCodec->mCallback->onOutputBuffersChanged();
7896                }
7897
7898                if (err != OK) {
7899                    mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
7900                    ALOGE("Error occurred while disabling the output port");
7901                }
7902
7903                return true;
7904            } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
7905                if (data2 != (OMX_U32)kPortIndexOutput) {
7906                    ALOGW("ignoring EventCmdComplete OMX_CommandPortEnable for port %u", data2);
7907                    return false;
7908                }
7909
7910                ALOGV("[%s] Output port now reenabled.", mCodec->mComponentName.c_str());
7911
7912                if (mCodec->mExecutingState->active()) {
7913                    mCodec->mExecutingState->submitOutputBuffers();
7914                }
7915
7916                mCodec->changeState(mCodec->mExecutingState);
7917
7918                return true;
7919            }
7920
7921            return false;
7922        }
7923
7924        default:
7925            return BaseState::onOMXEvent(event, data1, data2);
7926    }
7927}
7928
7929////////////////////////////////////////////////////////////////////////////////
7930
7931ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec)
7932    : BaseState(codec),
7933      mComponentNowIdle(false) {
7934}
7935
7936bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) {
7937    bool handled = false;
7938
7939    switch (msg->what()) {
7940        case kWhatFlush:
7941        {
7942            // Don't send me a flush request if you previously wanted me
7943            // to shutdown.
7944            ALOGW("Ignoring flush request in ExecutingToIdleState");
7945            break;
7946        }
7947
7948        case kWhatShutdown:
7949        {
7950            mCodec->deferMessage(msg);
7951            handled = true;
7952            break;
7953        }
7954
7955        default:
7956            handled = BaseState::onMessageReceived(msg);
7957            break;
7958    }
7959
7960    return handled;
7961}
7962
7963void ACodec::ExecutingToIdleState::stateEntered() {
7964    ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
7965
7966    mComponentNowIdle = false;
7967    mCodec->mLastOutputFormat.clear();
7968}
7969
7970bool ACodec::ExecutingToIdleState::onOMXEvent(
7971        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
7972    switch (event) {
7973        case OMX_EventCmdComplete:
7974        {
7975            if (data1 != (OMX_U32)OMX_CommandStateSet
7976                    || data2 != (OMX_U32)OMX_StateIdle) {
7977                ALOGE("Unexpected command completion in ExecutingToIdleState: %s(%u) %s(%u)",
7978                        asString((OMX_COMMANDTYPE)data1), data1,
7979                        asString((OMX_STATETYPE)data2), data2);
7980                mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
7981                return true;
7982            }
7983
7984            mComponentNowIdle = true;
7985
7986            changeStateIfWeOwnAllBuffers();
7987
7988            return true;
7989        }
7990
7991        case OMX_EventPortSettingsChanged:
7992        case OMX_EventBufferFlag:
7993        {
7994            // We're shutting down and don't care about this anymore.
7995            return true;
7996        }
7997
7998        default:
7999            return BaseState::onOMXEvent(event, data1, data2);
8000    }
8001}
8002
8003void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
8004    if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) {
8005        status_t err = mCodec->mOMXNode->sendCommand(
8006                OMX_CommandStateSet, OMX_StateLoaded);
8007        if (err == OK) {
8008            err = mCodec->freeBuffersOnPort(kPortIndexInput);
8009            status_t err2 = mCodec->freeBuffersOnPort(kPortIndexOutput);
8010            if (err == OK) {
8011                err = err2;
8012            }
8013        }
8014
8015        if ((mCodec->mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown)
8016                && mCodec->mNativeWindow != NULL) {
8017            // We push enough 1x1 blank buffers to ensure that one of
8018            // them has made it to the display.  This allows the OMX
8019            // component teardown to zero out any protected buffers
8020            // without the risk of scanning out one of those buffers.
8021            pushBlankBuffersToNativeWindow(mCodec->mNativeWindow.get());
8022        }
8023
8024        if (err != OK) {
8025            mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
8026            return;
8027        }
8028
8029        mCodec->changeState(mCodec->mIdleToLoadedState);
8030    }
8031}
8032
8033void ACodec::ExecutingToIdleState::onInputBufferFilled(
8034        const sp<AMessage> &msg) {
8035    BaseState::onInputBufferFilled(msg);
8036
8037    changeStateIfWeOwnAllBuffers();
8038}
8039
8040void ACodec::ExecutingToIdleState::onOutputBufferDrained(
8041        const sp<AMessage> &msg) {
8042    BaseState::onOutputBufferDrained(msg);
8043
8044    changeStateIfWeOwnAllBuffers();
8045}
8046
8047////////////////////////////////////////////////////////////////////////////////
8048
8049ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec)
8050    : BaseState(codec) {
8051}
8052
8053bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) {
8054    bool handled = false;
8055
8056    switch (msg->what()) {
8057        case kWhatShutdown:
8058        {
8059            mCodec->deferMessage(msg);
8060            handled = true;
8061            break;
8062        }
8063
8064        case kWhatFlush:
8065        {
8066            // Don't send me a flush request if you previously wanted me
8067            // to shutdown.
8068            ALOGE("Got flush request in IdleToLoadedState");
8069            break;
8070        }
8071
8072        default:
8073            handled = BaseState::onMessageReceived(msg);
8074            break;
8075    }
8076
8077    return handled;
8078}
8079
8080void ACodec::IdleToLoadedState::stateEntered() {
8081    ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
8082}
8083
8084bool ACodec::IdleToLoadedState::onOMXEvent(
8085        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
8086    switch (event) {
8087        case OMX_EventCmdComplete:
8088        {
8089            if (data1 != (OMX_U32)OMX_CommandStateSet
8090                    || data2 != (OMX_U32)OMX_StateLoaded) {
8091                ALOGE("Unexpected command completion in IdleToLoadedState: %s(%u) %s(%u)",
8092                        asString((OMX_COMMANDTYPE)data1), data1,
8093                        asString((OMX_STATETYPE)data2), data2);
8094                mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
8095                return true;
8096            }
8097
8098            mCodec->changeState(mCodec->mLoadedState);
8099
8100            return true;
8101        }
8102
8103        default:
8104            return BaseState::onOMXEvent(event, data1, data2);
8105    }
8106}
8107
8108////////////////////////////////////////////////////////////////////////////////
8109
8110ACodec::FlushingState::FlushingState(ACodec *codec)
8111    : BaseState(codec) {
8112}
8113
8114void ACodec::FlushingState::stateEntered() {
8115    ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());
8116
8117    mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
8118}
8119
8120bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) {
8121    bool handled = false;
8122
8123    switch (msg->what()) {
8124        case kWhatShutdown:
8125        {
8126            mCodec->deferMessage(msg);
8127            if (mCodec->mFatalError) {
8128                sp<AMessage> msg = new AMessage(ACodec::kWhatForceStateTransition, mCodec);
8129                msg->setInt32("generation", mCodec->mStateGeneration);
8130                msg->post(3000000);
8131            }
8132            break;
8133        }
8134
8135        case kWhatFlush:
8136        {
8137            // We're already doing this right now.
8138            handled = true;
8139            break;
8140        }
8141
8142        case kWhatForceStateTransition:
8143        {
8144            int32_t generation = 0;
8145            CHECK(msg->findInt32("generation", &generation));
8146            mCodec->forceStateTransition(generation);
8147
8148            handled = true;
8149            break;
8150        }
8151
8152        default:
8153            handled = BaseState::onMessageReceived(msg);
8154            break;
8155    }
8156
8157    return handled;
8158}
8159
8160bool ACodec::FlushingState::onOMXEvent(
8161        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
8162    ALOGV("[%s] FlushingState onOMXEvent(%u,%d)",
8163            mCodec->mComponentName.c_str(), event, (OMX_S32)data1);
8164
8165    switch (event) {
8166        case OMX_EventCmdComplete:
8167        {
8168            if (data1 != (OMX_U32)OMX_CommandFlush) {
8169                ALOGE("unexpected EventCmdComplete %s(%d) data2:%d in FlushingState",
8170                        asString((OMX_COMMANDTYPE)data1), data1, data2);
8171                mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
8172                return true;
8173            }
8174
8175            if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
8176                if (mFlushComplete[data2]) {
8177                    ALOGW("Flush already completed for %s port",
8178                            data2 == kPortIndexInput ? "input" : "output");
8179                    return true;
8180                }
8181                mFlushComplete[data2] = true;
8182
8183                if (mFlushComplete[kPortIndexInput] && mFlushComplete[kPortIndexOutput]) {
8184                    changeStateIfWeOwnAllBuffers();
8185                }
8186            } else if (data2 == OMX_ALL) {
8187                if (!mFlushComplete[kPortIndexInput] || !mFlushComplete[kPortIndexOutput]) {
8188                    ALOGW("received flush complete event for OMX_ALL before ports have been"
8189                            "flushed (%d/%d)",
8190                            mFlushComplete[kPortIndexInput], mFlushComplete[kPortIndexOutput]);
8191                    return false;
8192                }
8193
8194                changeStateIfWeOwnAllBuffers();
8195            } else {
8196                ALOGW("data2 not OMX_ALL but %u in EventCmdComplete CommandFlush", data2);
8197            }
8198
8199            return true;
8200        }
8201
8202        case OMX_EventPortSettingsChanged:
8203        {
8204            sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec);
8205            msg->setInt32("type", omx_message::EVENT);
8206            msg->setInt32("generation", mCodec->mNodeGeneration);
8207            msg->setInt32("event", event);
8208            msg->setInt32("data1", data1);
8209            msg->setInt32("data2", data2);
8210
8211            ALOGV("[%s] Deferring OMX_EventPortSettingsChanged",
8212                 mCodec->mComponentName.c_str());
8213
8214            mCodec->deferMessage(msg);
8215
8216            return true;
8217        }
8218
8219        default:
8220            return BaseState::onOMXEvent(event, data1, data2);
8221    }
8222
8223    return true;
8224}
8225
8226void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) {
8227    BaseState::onOutputBufferDrained(msg);
8228
8229    changeStateIfWeOwnAllBuffers();
8230}
8231
8232void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) {
8233    BaseState::onInputBufferFilled(msg);
8234
8235    changeStateIfWeOwnAllBuffers();
8236}
8237
8238void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() {
8239    if (mFlushComplete[kPortIndexInput]
8240            && mFlushComplete[kPortIndexOutput]
8241            && mCodec->allYourBuffersAreBelongToUs()) {
8242        // We now own all buffers except possibly those still queued with
8243        // the native window for rendering. Let's get those back as well.
8244        mCodec->waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs();
8245
8246        mCodec->mRenderTracker.clear(systemTime(CLOCK_MONOTONIC));
8247
8248        mCodec->mCallback->onFlushCompleted();
8249
8250        mCodec->mPortEOS[kPortIndexInput] =
8251            mCodec->mPortEOS[kPortIndexOutput] = false;
8252
8253        mCodec->mInputEOSResult = OK;
8254
8255        if (mCodec->mSkipCutBuffer != NULL) {
8256            mCodec->mSkipCutBuffer->clear();
8257        }
8258
8259        mCodec->changeState(mCodec->mExecutingState);
8260    }
8261}
8262
8263status_t ACodec::queryCapabilities(
8264        const char* owner, const char* name, const char* mime, bool isEncoder,
8265        MediaCodecInfo::CapabilitiesWriter* caps) {
8266    const char *role = GetComponentRole(isEncoder, mime);
8267    if (role == NULL) {
8268        return BAD_VALUE;
8269    }
8270
8271    OMXClient client;
8272    status_t err = client.connect(owner);
8273    if (err != OK) {
8274        return err;
8275    }
8276
8277    sp<IOMX> omx = client.interface();
8278    sp<CodecObserver> observer = new CodecObserver;
8279    sp<IOMXNode> omxNode;
8280
8281    err = omx->allocateNode(name, observer, &omxNode);
8282    if (err != OK) {
8283        client.disconnect();
8284        return err;
8285    }
8286
8287    err = SetComponentRole(omxNode, role);
8288    if (err != OK) {
8289        omxNode->freeNode();
8290        client.disconnect();
8291        return err;
8292    }
8293
8294    bool isVideo = strncasecmp(mime, "video/", 6) == 0;
8295    bool isImage = strncasecmp(mime, "image/", 6) == 0;
8296
8297    if (isVideo || isImage) {
8298        OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
8299        InitOMXParams(&param);
8300        param.nPortIndex = isEncoder ? kPortIndexOutput : kPortIndexInput;
8301
8302        for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
8303            param.nProfileIndex = index;
8304            status_t err = omxNode->getParameter(
8305                    OMX_IndexParamVideoProfileLevelQuerySupported,
8306                    &param, sizeof(param));
8307            if (err != OK) {
8308                break;
8309            }
8310            caps->addProfileLevel(param.eProfile, param.eLevel);
8311
8312            // AVC components may not list the constrained profiles explicitly, but
8313            // decoders that support a profile also support its constrained version.
8314            // Encoders must explicitly support constrained profiles.
8315            if (!isEncoder && strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC) == 0) {
8316                if (param.eProfile == OMX_VIDEO_AVCProfileHigh) {
8317                    caps->addProfileLevel(OMX_VIDEO_AVCProfileConstrainedHigh, param.eLevel);
8318                } else if (param.eProfile == OMX_VIDEO_AVCProfileBaseline) {
8319                    caps->addProfileLevel(OMX_VIDEO_AVCProfileConstrainedBaseline, param.eLevel);
8320                }
8321            }
8322
8323            if (index == kMaxIndicesToCheck) {
8324                ALOGW("[%s] stopping checking profiles after %u: %x/%x",
8325                        name, index,
8326                        param.eProfile, param.eLevel);
8327            }
8328        }
8329
8330        // Color format query
8331        // return colors in the order reported by the OMX component
8332        // prefix "flexible" standard ones with the flexible equivalent
8333        OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat;
8334        InitOMXParams(&portFormat);
8335        portFormat.nPortIndex = isEncoder ? kPortIndexInput : kPortIndexOutput;
8336        for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
8337            portFormat.nIndex = index;
8338            status_t err = omxNode->getParameter(
8339                    OMX_IndexParamVideoPortFormat,
8340                    &portFormat, sizeof(portFormat));
8341            if (err != OK) {
8342                break;
8343            }
8344
8345            OMX_U32 flexibleEquivalent;
8346            if (IsFlexibleColorFormat(
8347                    omxNode, portFormat.eColorFormat, false /* usingNativeWindow */,
8348                    &flexibleEquivalent)) {
8349                caps->addColorFormat(flexibleEquivalent);
8350            }
8351            caps->addColorFormat(portFormat.eColorFormat);
8352
8353            if (index == kMaxIndicesToCheck) {
8354                ALOGW("[%s] stopping checking formats after %u: %s(%x)",
8355                        name, index,
8356                        asString(portFormat.eColorFormat), portFormat.eColorFormat);
8357            }
8358        }
8359    } else if (strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC) == 0) {
8360        // More audio codecs if they have profiles.
8361        OMX_AUDIO_PARAM_ANDROID_PROFILETYPE param;
8362        InitOMXParams(&param);
8363        param.nPortIndex = isEncoder ? kPortIndexOutput : kPortIndexInput;
8364        for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
8365            param.nProfileIndex = index;
8366            status_t err = omxNode->getParameter(
8367                    (OMX_INDEXTYPE)OMX_IndexParamAudioProfileQuerySupported,
8368                    &param, sizeof(param));
8369            if (err != OK) {
8370                break;
8371            }
8372            // For audio, level is ignored.
8373            caps->addProfileLevel(param.eProfile, 0 /* level */);
8374
8375            if (index == kMaxIndicesToCheck) {
8376                ALOGW("[%s] stopping checking profiles after %u: %x",
8377                        name, index,
8378                        param.eProfile);
8379            }
8380        }
8381
8382        // NOTE: Without Android extensions, OMX does not provide a way to query
8383        // AAC profile support
8384        if (param.nProfileIndex == 0) {
8385            ALOGW("component %s doesn't support profile query.", name);
8386        }
8387    }
8388
8389    if (isVideo && !isEncoder) {
8390        native_handle_t *sidebandHandle = NULL;
8391        if (omxNode->configureVideoTunnelMode(
8392                kPortIndexOutput, OMX_TRUE, 0, &sidebandHandle) == OK) {
8393            // tunneled playback includes adaptive playback
8394            caps->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback
8395                    | MediaCodecInfo::Capabilities::kFlagSupportsTunneledPlayback);
8396        } else if (omxNode->setPortMode(
8397                kPortIndexOutput, IOMX::kPortModeDynamicANWBuffer) == OK ||
8398                omxNode->prepareForAdaptivePlayback(
8399                kPortIndexOutput, OMX_TRUE,
8400                1280 /* width */, 720 /* height */) == OK) {
8401            caps->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback);
8402        }
8403    }
8404
8405    if (isVideo && isEncoder) {
8406        OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE params;
8407        InitOMXParams(&params);
8408        params.nPortIndex = kPortIndexOutput;
8409        // TODO: should we verify if fallback is supported?
8410        if (omxNode->getConfig(
8411                (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh,
8412                &params, sizeof(params)) == OK) {
8413            caps->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsIntraRefresh);
8414        }
8415    }
8416
8417    omxNode->freeNode();
8418    client.disconnect();
8419    return OK;
8420}
8421
8422// These are supposed be equivalent to the logic in
8423// "audio_channel_out_mask_from_count".
8424//static
8425status_t ACodec::getOMXChannelMapping(size_t numChannels, OMX_AUDIO_CHANNELTYPE map[]) {
8426    switch (numChannels) {
8427        case 1:
8428            map[0] = OMX_AUDIO_ChannelCF;
8429            break;
8430        case 2:
8431            map[0] = OMX_AUDIO_ChannelLF;
8432            map[1] = OMX_AUDIO_ChannelRF;
8433            break;
8434        case 3:
8435            map[0] = OMX_AUDIO_ChannelLF;
8436            map[1] = OMX_AUDIO_ChannelRF;
8437            map[2] = OMX_AUDIO_ChannelCF;
8438            break;
8439        case 4:
8440            map[0] = OMX_AUDIO_ChannelLF;
8441            map[1] = OMX_AUDIO_ChannelRF;
8442            map[2] = OMX_AUDIO_ChannelLR;
8443            map[3] = OMX_AUDIO_ChannelRR;
8444            break;
8445        case 5:
8446            map[0] = OMX_AUDIO_ChannelLF;
8447            map[1] = OMX_AUDIO_ChannelRF;
8448            map[2] = OMX_AUDIO_ChannelCF;
8449            map[3] = OMX_AUDIO_ChannelLR;
8450            map[4] = OMX_AUDIO_ChannelRR;
8451            break;
8452        case 6:
8453            map[0] = OMX_AUDIO_ChannelLF;
8454            map[1] = OMX_AUDIO_ChannelRF;
8455            map[2] = OMX_AUDIO_ChannelCF;
8456            map[3] = OMX_AUDIO_ChannelLFE;
8457            map[4] = OMX_AUDIO_ChannelLR;
8458            map[5] = OMX_AUDIO_ChannelRR;
8459            break;
8460        case 7:
8461            map[0] = OMX_AUDIO_ChannelLF;
8462            map[1] = OMX_AUDIO_ChannelRF;
8463            map[2] = OMX_AUDIO_ChannelCF;
8464            map[3] = OMX_AUDIO_ChannelLFE;
8465            map[4] = OMX_AUDIO_ChannelLR;
8466            map[5] = OMX_AUDIO_ChannelRR;
8467            map[6] = OMX_AUDIO_ChannelCS;
8468            break;
8469        case 8:
8470            map[0] = OMX_AUDIO_ChannelLF;
8471            map[1] = OMX_AUDIO_ChannelRF;
8472            map[2] = OMX_AUDIO_ChannelCF;
8473            map[3] = OMX_AUDIO_ChannelLFE;
8474            map[4] = OMX_AUDIO_ChannelLR;
8475            map[5] = OMX_AUDIO_ChannelRR;
8476            map[6] = OMX_AUDIO_ChannelLS;
8477            map[7] = OMX_AUDIO_ChannelRS;
8478            break;
8479        default:
8480            return -EINVAL;
8481    }
8482
8483    return OK;
8484}
8485
8486}  // namespace android
8487