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