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