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