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/hexdump.h>
34#include <media/stagefright/foundation/ABuffer.h>
35#include <media/stagefright/foundation/ADebug.h>
36#include <media/stagefright/foundation/AMessage.h>
37#include <media/stagefright/foundation/AUtils.h>
38
39#include <media/stagefright/BufferProducerWrapper.h>
40#include <media/stagefright/MediaCodec.h>
41#include <media/stagefright/MediaCodecList.h>
42#include <media/stagefright/MediaDefs.h>
43#include <media/stagefright/OMXClient.h>
44#include <media/stagefright/PersistentSurface.h>
45#include <media/stagefright/SurfaceUtils.h>
46#include <media/hardware/HardwareAPI.h>
47#include <media/OMXBuffer.h>
48#include <media/omx/1.0/WOmxNode.h>
49
50#include <hidlmemory/mapping.h>
51
52#include <OMX_AudioExt.h>
53#include <OMX_VideoExt.h>
54#include <OMX_Component.h>
55#include <OMX_IndexExt.h>
56#include <OMX_AsString.h>
57
58#include "include/avc_utils.h"
59#include "include/ACodecBufferChannel.h"
60#include "include/DataConverter.h"
61#include "include/SecureBuffer.h"
62#include "include/SharedMemoryBuffer.h"
63#include "omx/OMXUtils.h"
64
65#include <android/hidl/allocator/1.0/IAllocator.h>
66#include <android/hidl/memory/1.0/IMemory.h>
67
68namespace android {
69
70using binder::Status;
71
72enum {
73    kMaxIndicesToCheck = 32, // used when enumerating supported formats and profiles
74};
75
76// OMX errors are directly mapped into status_t range if
77// there is no corresponding MediaError status code.
78// Use the statusFromOMXError(int32_t omxError) function.
79//
80// Currently this is a direct map.
81// See frameworks/native/include/media/openmax/OMX_Core.h
82//
83// Vendor OMX errors     from 0x90000000 - 0x9000FFFF
84// Extension OMX errors  from 0x8F000000 - 0x90000000
85// Standard OMX errors   from 0x80001000 - 0x80001024 (0x80001024 current)
86//
87
88// returns true if err is a recognized OMX error code.
89// as OMX error is OMX_S32, this is an int32_t type
90static inline bool isOMXError(int32_t err) {
91    return (ERROR_CODEC_MIN <= err && err <= ERROR_CODEC_MAX);
92}
93
94// converts an OMX error to a status_t
95static inline status_t statusFromOMXError(int32_t omxError) {
96    switch (omxError) {
97    case OMX_ErrorInvalidComponentName:
98    case OMX_ErrorComponentNotFound:
99        return NAME_NOT_FOUND; // can trigger illegal argument error for provided names.
100    default:
101        return isOMXError(omxError) ? omxError : 0; // no translation required
102    }
103}
104
105static inline status_t statusFromBinderStatus(const Status &status) {
106    if (status.isOk()) {
107        return OK;
108    }
109    status_t err;
110    if ((err = status.serviceSpecificErrorCode()) != OK) {
111        return err;
112    }
113    if ((err = status.transactionError()) != OK) {
114        return err;
115    }
116    // Other exception
117    return UNKNOWN_ERROR;
118}
119
120// checks and converts status_t to a non-side-effect status_t
121static inline status_t makeNoSideEffectStatus(status_t err) {
122    switch (err) {
123    // the following errors have side effects and may come
124    // from other code modules. Remap for safety reasons.
125    case INVALID_OPERATION:
126    case DEAD_OBJECT:
127        return UNKNOWN_ERROR;
128    default:
129        return err;
130    }
131}
132
133struct MessageList : public RefBase {
134    MessageList() {
135    }
136    virtual ~MessageList() {
137    }
138    std::list<sp<AMessage> > &getList() { return mList; }
139private:
140    std::list<sp<AMessage> > mList;
141
142    DISALLOW_EVIL_CONSTRUCTORS(MessageList);
143};
144
145static sp<DataConverter> getCopyConverter() {
146    static pthread_once_t once = PTHREAD_ONCE_INIT; // const-inited
147    static sp<DataConverter> sCopyConverter;        // zero-inited
148    pthread_once(&once, [](){ sCopyConverter = new DataConverter(); });
149    return sCopyConverter;
150}
151
152struct CodecObserver : public BnOMXObserver {
153    CodecObserver() {}
154
155    void setNotificationMessage(const sp<AMessage> &msg) {
156        mNotify = msg;
157    }
158
159    // from IOMXObserver
160    virtual void onMessages(const std::list<omx_message> &messages) {
161        if (messages.empty()) {
162            return;
163        }
164
165        sp<AMessage> notify = mNotify->dup();
166        sp<MessageList> msgList = new MessageList();
167        for (std::list<omx_message>::const_iterator it = messages.cbegin();
168              it != messages.cend(); ++it) {
169            const omx_message &omx_msg = *it;
170
171            sp<AMessage> msg = new AMessage;
172            msg->setInt32("type", omx_msg.type);
173            switch (omx_msg.type) {
174                case omx_message::EVENT:
175                {
176                    msg->setInt32("event", omx_msg.u.event_data.event);
177                    msg->setInt32("data1", omx_msg.u.event_data.data1);
178                    msg->setInt32("data2", omx_msg.u.event_data.data2);
179                    break;
180                }
181
182                case omx_message::EMPTY_BUFFER_DONE:
183                {
184                    msg->setInt32("buffer", omx_msg.u.buffer_data.buffer);
185                    msg->setInt32("fence_fd", omx_msg.fenceFd);
186                    break;
187                }
188
189                case omx_message::FILL_BUFFER_DONE:
190                {
191                    msg->setInt32(
192                            "buffer", omx_msg.u.extended_buffer_data.buffer);
193                    msg->setInt32(
194                            "range_offset",
195                            omx_msg.u.extended_buffer_data.range_offset);
196                    msg->setInt32(
197                            "range_length",
198                            omx_msg.u.extended_buffer_data.range_length);
199                    msg->setInt32(
200                            "flags",
201                            omx_msg.u.extended_buffer_data.flags);
202                    msg->setInt64(
203                            "timestamp",
204                            omx_msg.u.extended_buffer_data.timestamp);
205                    msg->setInt32(
206                            "fence_fd", omx_msg.fenceFd);
207                    break;
208                }
209
210                case omx_message::FRAME_RENDERED:
211                {
212                    msg->setInt64(
213                            "media_time_us", omx_msg.u.render_data.timestamp);
214                    msg->setInt64(
215                            "system_nano", omx_msg.u.render_data.nanoTime);
216                    break;
217                }
218
219                default:
220                    ALOGE("Unrecognized message type: %d", omx_msg.type);
221                    break;
222            }
223            msgList->getList().push_back(msg);
224        }
225        notify->setObject("messages", msgList);
226        notify->post();
227    }
228
229protected:
230    virtual ~CodecObserver() {}
231
232private:
233    sp<AMessage> mNotify;
234
235    DISALLOW_EVIL_CONSTRUCTORS(CodecObserver);
236};
237
238////////////////////////////////////////////////////////////////////////////////
239
240struct ACodec::BaseState : public AState {
241    explicit BaseState(ACodec *codec, const sp<AState> &parentState = NULL);
242
243protected:
244    enum PortMode {
245        KEEP_BUFFERS,
246        RESUBMIT_BUFFERS,
247        FREE_BUFFERS,
248    };
249
250    ACodec *mCodec;
251
252    virtual PortMode getPortMode(OMX_U32 portIndex);
253
254    virtual void stateExited();
255    virtual bool onMessageReceived(const sp<AMessage> &msg);
256
257    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
258
259    virtual void onOutputBufferDrained(const sp<AMessage> &msg);
260    virtual void onInputBufferFilled(const sp<AMessage> &msg);
261
262    void postFillThisBuffer(BufferInfo *info);
263
264private:
265    // Handles an OMX message. Returns true iff message was handled.
266    bool onOMXMessage(const sp<AMessage> &msg);
267
268    // Handles a list of messages. Returns true iff messages were handled.
269    bool onOMXMessageList(const sp<AMessage> &msg);
270
271    // returns true iff this message is for this component and the component is alive
272    bool checkOMXMessage(const sp<AMessage> &msg);
273
274    bool onOMXEmptyBufferDone(IOMX::buffer_id bufferID, int fenceFd);
275
276    bool onOMXFillBufferDone(
277            IOMX::buffer_id bufferID,
278            size_t rangeOffset, size_t rangeLength,
279            OMX_U32 flags,
280            int64_t timeUs,
281            int fenceFd);
282
283    virtual bool onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano);
284
285    void getMoreInputDataIfPossible();
286
287    DISALLOW_EVIL_CONSTRUCTORS(BaseState);
288};
289
290////////////////////////////////////////////////////////////////////////////////
291
292struct ACodec::DeathNotifier :
293        public IBinder::DeathRecipient,
294        public ::android::hardware::hidl_death_recipient {
295    explicit DeathNotifier(const sp<AMessage> &notify)
296        : mNotify(notify) {
297    }
298
299    virtual void binderDied(const wp<IBinder> &) {
300        mNotify->post();
301    }
302
303    virtual void serviceDied(
304            uint64_t /* cookie */,
305            const wp<::android::hidl::base::V1_0::IBase>& /* who */) {
306        mNotify->post();
307    }
308
309protected:
310    virtual ~DeathNotifier() {}
311
312private:
313    sp<AMessage> mNotify;
314
315    DISALLOW_EVIL_CONSTRUCTORS(DeathNotifier);
316};
317
318struct ACodec::UninitializedState : public ACodec::BaseState {
319    explicit UninitializedState(ACodec *codec);
320
321protected:
322    virtual bool onMessageReceived(const sp<AMessage> &msg);
323    virtual void stateEntered();
324
325private:
326    void onSetup(const sp<AMessage> &msg);
327    bool onAllocateComponent(const sp<AMessage> &msg);
328
329    sp<DeathNotifier> mDeathNotifier;
330
331    DISALLOW_EVIL_CONSTRUCTORS(UninitializedState);
332};
333
334////////////////////////////////////////////////////////////////////////////////
335
336struct ACodec::LoadedState : public ACodec::BaseState {
337    explicit LoadedState(ACodec *codec);
338
339protected:
340    virtual bool onMessageReceived(const sp<AMessage> &msg);
341    virtual void stateEntered();
342
343private:
344    friend struct ACodec::UninitializedState;
345
346    bool onConfigureComponent(const sp<AMessage> &msg);
347    void onCreateInputSurface(const sp<AMessage> &msg);
348    void onSetInputSurface(const sp<AMessage> &msg);
349    void onStart();
350    void onShutdown(bool keepComponentAllocated);
351
352    status_t setupInputSurface();
353
354    DISALLOW_EVIL_CONSTRUCTORS(LoadedState);
355};
356
357////////////////////////////////////////////////////////////////////////////////
358
359struct ACodec::LoadedToIdleState : public ACodec::BaseState {
360    explicit LoadedToIdleState(ACodec *codec);
361
362protected:
363    virtual bool onMessageReceived(const sp<AMessage> &msg);
364    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
365    virtual void stateEntered();
366
367private:
368    status_t allocateBuffers();
369
370    DISALLOW_EVIL_CONSTRUCTORS(LoadedToIdleState);
371};
372
373////////////////////////////////////////////////////////////////////////////////
374
375struct ACodec::IdleToExecutingState : public ACodec::BaseState {
376    explicit IdleToExecutingState(ACodec *codec);
377
378protected:
379    virtual bool onMessageReceived(const sp<AMessage> &msg);
380    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
381    virtual void stateEntered();
382
383private:
384    DISALLOW_EVIL_CONSTRUCTORS(IdleToExecutingState);
385};
386
387////////////////////////////////////////////////////////////////////////////////
388
389struct ACodec::ExecutingState : public ACodec::BaseState {
390    explicit ExecutingState(ACodec *codec);
391
392    void submitRegularOutputBuffers();
393    void submitOutputMetaBuffers();
394    void submitOutputBuffers();
395
396    // Submit output buffers to the decoder, submit input buffers to client
397    // to fill with data.
398    void resume();
399
400    // Returns true iff input and output buffers are in play.
401    bool active() const { return mActive; }
402
403protected:
404    virtual PortMode getPortMode(OMX_U32 portIndex);
405    virtual bool onMessageReceived(const sp<AMessage> &msg);
406    virtual void stateEntered();
407
408    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
409    virtual bool onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano);
410
411private:
412    bool mActive;
413
414    DISALLOW_EVIL_CONSTRUCTORS(ExecutingState);
415};
416
417////////////////////////////////////////////////////////////////////////////////
418
419struct ACodec::OutputPortSettingsChangedState : public ACodec::BaseState {
420    explicit OutputPortSettingsChangedState(ACodec *codec);
421
422protected:
423    virtual PortMode getPortMode(OMX_U32 portIndex);
424    virtual bool onMessageReceived(const sp<AMessage> &msg);
425    virtual void stateEntered();
426
427    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
428    virtual bool onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano);
429
430private:
431    DISALLOW_EVIL_CONSTRUCTORS(OutputPortSettingsChangedState);
432};
433
434////////////////////////////////////////////////////////////////////////////////
435
436struct ACodec::ExecutingToIdleState : public ACodec::BaseState {
437    explicit ExecutingToIdleState(ACodec *codec);
438
439protected:
440    virtual bool onMessageReceived(const sp<AMessage> &msg);
441    virtual void stateEntered();
442
443    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
444
445    virtual void onOutputBufferDrained(const sp<AMessage> &msg);
446    virtual void onInputBufferFilled(const sp<AMessage> &msg);
447
448private:
449    void changeStateIfWeOwnAllBuffers();
450
451    bool mComponentNowIdle;
452
453    DISALLOW_EVIL_CONSTRUCTORS(ExecutingToIdleState);
454};
455
456////////////////////////////////////////////////////////////////////////////////
457
458struct ACodec::IdleToLoadedState : public ACodec::BaseState {
459    explicit IdleToLoadedState(ACodec *codec);
460
461protected:
462    virtual bool onMessageReceived(const sp<AMessage> &msg);
463    virtual void stateEntered();
464
465    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
466
467private:
468    DISALLOW_EVIL_CONSTRUCTORS(IdleToLoadedState);
469};
470
471////////////////////////////////////////////////////////////////////////////////
472
473struct ACodec::FlushingState : public ACodec::BaseState {
474    explicit FlushingState(ACodec *codec);
475
476protected:
477    virtual bool onMessageReceived(const sp<AMessage> &msg);
478    virtual void stateEntered();
479
480    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
481
482    virtual void onOutputBufferDrained(const sp<AMessage> &msg);
483    virtual void onInputBufferFilled(const sp<AMessage> &msg);
484
485private:
486    bool mFlushComplete[2];
487
488    void changeStateIfWeOwnAllBuffers();
489
490    DISALLOW_EVIL_CONSTRUCTORS(FlushingState);
491};
492
493////////////////////////////////////////////////////////////////////////////////
494
495void ACodec::BufferInfo::setWriteFence(int fenceFd, const char *dbg) {
496    if (mFenceFd >= 0) {
497        ALOGW("OVERWRITE OF %s fence %d by write fence %d in %s",
498                mIsReadFence ? "read" : "write", mFenceFd, fenceFd, dbg);
499    }
500    mFenceFd = fenceFd;
501    mIsReadFence = false;
502}
503
504void ACodec::BufferInfo::setReadFence(int fenceFd, const char *dbg) {
505    if (mFenceFd >= 0) {
506        ALOGW("OVERWRITE OF %s fence %d by read fence %d in %s",
507                mIsReadFence ? "read" : "write", mFenceFd, fenceFd, dbg);
508    }
509    mFenceFd = fenceFd;
510    mIsReadFence = true;
511}
512
513void ACodec::BufferInfo::checkWriteFence(const char *dbg) {
514    if (mFenceFd >= 0 && mIsReadFence) {
515        ALOGD("REUSING read fence %d as write fence in %s", mFenceFd, dbg);
516    }
517}
518
519void ACodec::BufferInfo::checkReadFence(const char *dbg) {
520    if (mFenceFd >= 0 && !mIsReadFence) {
521        ALOGD("REUSING write fence %d as read fence in %s", mFenceFd, dbg);
522    }
523}
524
525////////////////////////////////////////////////////////////////////////////////
526
527ACodec::ACodec()
528    : mSampleRate(0),
529      mNodeGeneration(0),
530      mUsingNativeWindow(false),
531      mNativeWindowUsageBits(0),
532      mLastNativeWindowDataSpace(HAL_DATASPACE_UNKNOWN),
533      mIsVideo(false),
534      mIsEncoder(false),
535      mFatalError(false),
536      mShutdownInProgress(false),
537      mExplicitShutdown(false),
538      mIsLegacyVP9Decoder(false),
539      mEncoderDelay(0),
540      mEncoderPadding(0),
541      mRotationDegrees(0),
542      mChannelMaskPresent(false),
543      mChannelMask(0),
544      mDequeueCounter(0),
545      mMetadataBuffersToSubmit(0),
546      mNumUndequeuedBuffers(0),
547      mRepeatFrameDelayUs(-1ll),
548      mMaxPtsGapUs(-1ll),
549      mMaxFps(-1),
550      mFps(-1.0),
551      mCaptureFps(-1.0),
552      mCreateInputBuffersSuspended(false),
553      mLatency(0),
554      mTunneled(false),
555      mDescribeColorAspectsIndex((OMX_INDEXTYPE)0),
556      mDescribeHDRStaticInfoIndex((OMX_INDEXTYPE)0),
557      mStateGeneration(0),
558      mVendorExtensionsStatus(kExtensionsUnchecked) {
559    mUninitializedState = new UninitializedState(this);
560    mLoadedState = new LoadedState(this);
561    mLoadedToIdleState = new LoadedToIdleState(this);
562    mIdleToExecutingState = new IdleToExecutingState(this);
563    mExecutingState = new ExecutingState(this);
564
565    mOutputPortSettingsChangedState =
566        new OutputPortSettingsChangedState(this);
567
568    mExecutingToIdleState = new ExecutingToIdleState(this);
569    mIdleToLoadedState = new IdleToLoadedState(this);
570    mFlushingState = new FlushingState(this);
571
572    mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false;
573    mInputEOSResult = OK;
574
575    mPortMode[kPortIndexInput] = IOMX::kPortModePresetByteBuffer;
576    mPortMode[kPortIndexOutput] = IOMX::kPortModePresetByteBuffer;
577
578    memset(&mLastNativeWindowCrop, 0, sizeof(mLastNativeWindowCrop));
579
580    changeState(mUninitializedState);
581
582    mTrebleFlag = false;
583}
584
585ACodec::~ACodec() {
586}
587
588void ACodec::initiateSetup(const sp<AMessage> &msg) {
589    msg->setWhat(kWhatSetup);
590    msg->setTarget(this);
591    msg->post();
592}
593
594std::shared_ptr<BufferChannelBase> ACodec::getBufferChannel() {
595    if (!mBufferChannel) {
596        mBufferChannel = std::make_shared<ACodecBufferChannel>(
597                new AMessage(kWhatInputBufferFilled, this),
598                new AMessage(kWhatOutputBufferDrained, this));
599    }
600    return mBufferChannel;
601}
602
603void ACodec::signalSetParameters(const sp<AMessage> &params) {
604    sp<AMessage> msg = new AMessage(kWhatSetParameters, this);
605    msg->setMessage("params", params);
606    msg->post();
607}
608
609void ACodec::initiateAllocateComponent(const sp<AMessage> &msg) {
610    msg->setWhat(kWhatAllocateComponent);
611    msg->setTarget(this);
612    msg->post();
613}
614
615void ACodec::initiateConfigureComponent(const sp<AMessage> &msg) {
616    msg->setWhat(kWhatConfigureComponent);
617    msg->setTarget(this);
618    msg->post();
619}
620
621status_t ACodec::setSurface(const sp<Surface> &surface) {
622    sp<AMessage> msg = new AMessage(kWhatSetSurface, this);
623    msg->setObject("surface", surface);
624
625    sp<AMessage> response;
626    status_t err = msg->postAndAwaitResponse(&response);
627
628    if (err == OK) {
629        (void)response->findInt32("err", &err);
630    }
631    return err;
632}
633
634void ACodec::initiateCreateInputSurface() {
635    (new AMessage(kWhatCreateInputSurface, this))->post();
636}
637
638void ACodec::initiateSetInputSurface(
639        const sp<PersistentSurface> &surface) {
640    sp<AMessage> msg = new AMessage(kWhatSetInputSurface, this);
641    msg->setObject("input-surface", surface);
642    msg->post();
643}
644
645void ACodec::signalEndOfInputStream() {
646    (new AMessage(kWhatSignalEndOfInputStream, this))->post();
647}
648
649void ACodec::initiateStart() {
650    (new AMessage(kWhatStart, this))->post();
651}
652
653void ACodec::signalFlush() {
654    ALOGV("[%s] signalFlush", mComponentName.c_str());
655    (new AMessage(kWhatFlush, this))->post();
656}
657
658void ACodec::signalResume() {
659    (new AMessage(kWhatResume, this))->post();
660}
661
662void ACodec::initiateShutdown(bool keepComponentAllocated) {
663    sp<AMessage> msg = new AMessage(kWhatShutdown, this);
664    msg->setInt32("keepComponentAllocated", keepComponentAllocated);
665    msg->post();
666    if (!keepComponentAllocated) {
667        // ensure shutdown completes in 3 seconds
668        (new AMessage(kWhatReleaseCodecInstance, this))->post(3000000);
669    }
670}
671
672void ACodec::signalRequestIDRFrame() {
673    (new AMessage(kWhatRequestIDRFrame, this))->post();
674}
675
676// *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
677// Some codecs may return input buffers before having them processed.
678// This causes a halt if we already signaled an EOS on the input
679// port.  For now keep submitting an output buffer if there was an
680// EOS on the input port, but not yet on the output port.
681void ACodec::signalSubmitOutputMetadataBufferIfEOS_workaround() {
682    if (mPortEOS[kPortIndexInput] && !mPortEOS[kPortIndexOutput] &&
683            mMetadataBuffersToSubmit > 0) {
684        (new AMessage(kWhatSubmitOutputMetadataBufferIfEOS, this))->post();
685    }
686}
687
688status_t ACodec::handleSetSurface(const sp<Surface> &surface) {
689    // allow keeping unset surface
690    if (surface == NULL) {
691        if (mNativeWindow != NULL) {
692            ALOGW("cannot unset a surface");
693            return INVALID_OPERATION;
694        }
695        return OK;
696    }
697
698    // cannot switch from bytebuffers to surface
699    if (mNativeWindow == NULL) {
700        ALOGW("component was not configured with a surface");
701        return INVALID_OPERATION;
702    }
703
704    ANativeWindow *nativeWindow = surface.get();
705    // if we have not yet started the codec, we can simply set the native window
706    if (mBuffers[kPortIndexInput].size() == 0) {
707        mNativeWindow = surface;
708        return OK;
709    }
710
711    // we do not support changing a tunneled surface after start
712    if (mTunneled) {
713        ALOGW("cannot change tunneled surface");
714        return INVALID_OPERATION;
715    }
716
717    int usageBits = 0;
718    // no need to reconnect as we will not dequeue all buffers
719    status_t err = setupNativeWindowSizeFormatAndUsage(
720            nativeWindow, &usageBits, !storingMetadataInDecodedBuffers());
721    if (err != OK) {
722        return err;
723    }
724
725    int ignoredFlags = kVideoGrallocUsage;
726    // New output surface is not allowed to add new usage flag except ignored ones.
727    if ((usageBits & ~(mNativeWindowUsageBits | ignoredFlags)) != 0) {
728        ALOGW("cannot change usage from %#x to %#x", mNativeWindowUsageBits, usageBits);
729        return BAD_VALUE;
730    }
731
732    // get min undequeued count. We cannot switch to a surface that has a higher
733    // undequeued count than we allocated.
734    int minUndequeuedBuffers = 0;
735    err = nativeWindow->query(
736            nativeWindow, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
737            &minUndequeuedBuffers);
738    if (err != 0) {
739        ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)",
740                strerror(-err), -err);
741        return err;
742    }
743    if (minUndequeuedBuffers > (int)mNumUndequeuedBuffers) {
744        ALOGE("new surface holds onto more buffers (%d) than planned for (%zu)",
745                minUndequeuedBuffers, mNumUndequeuedBuffers);
746        return BAD_VALUE;
747    }
748
749    // we cannot change the number of output buffers while OMX is running
750    // set up surface to the same count
751    Vector<BufferInfo> &buffers = mBuffers[kPortIndexOutput];
752    ALOGV("setting up surface for %zu buffers", buffers.size());
753
754    err = native_window_set_buffer_count(nativeWindow, buffers.size());
755    if (err != 0) {
756        ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err),
757                -err);
758        return err;
759    }
760
761    // need to enable allocation when attaching
762    surface->getIGraphicBufferProducer()->allowAllocation(true);
763
764    // for meta data mode, we move dequeud buffers to the new surface.
765    // for non-meta mode, we must move all registered buffers
766    for (size_t i = 0; i < buffers.size(); ++i) {
767        const BufferInfo &info = buffers[i];
768        // skip undequeued buffers for meta data mode
769        if (storingMetadataInDecodedBuffers()
770                && info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
771            ALOGV("skipping buffer");
772            continue;
773        }
774        ALOGV("attaching buffer %p", info.mGraphicBuffer->getNativeBuffer());
775
776        err = surface->attachBuffer(info.mGraphicBuffer->getNativeBuffer());
777        if (err != OK) {
778            ALOGE("failed to attach buffer %p to the new surface: %s (%d)",
779                    info.mGraphicBuffer->getNativeBuffer(),
780                    strerror(-err), -err);
781            return err;
782        }
783    }
784
785    // cancel undequeued buffers to new surface
786    if (!storingMetadataInDecodedBuffers()) {
787        for (size_t i = 0; i < buffers.size(); ++i) {
788            BufferInfo &info = buffers.editItemAt(i);
789            if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
790                ALOGV("canceling buffer %p", info.mGraphicBuffer->getNativeBuffer());
791                err = nativeWindow->cancelBuffer(
792                        nativeWindow, info.mGraphicBuffer->getNativeBuffer(), info.mFenceFd);
793                info.mFenceFd = -1;
794                if (err != OK) {
795                    ALOGE("failed to cancel buffer %p to the new surface: %s (%d)",
796                            info.mGraphicBuffer->getNativeBuffer(),
797                            strerror(-err), -err);
798                    return err;
799                }
800            }
801        }
802        // disallow further allocation
803        (void)surface->getIGraphicBufferProducer()->allowAllocation(false);
804    }
805
806    // push blank buffers to previous window if requested
807    if (mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown) {
808        pushBlankBuffersToNativeWindow(mNativeWindow.get());
809    }
810
811    mNativeWindow = nativeWindow;
812    mNativeWindowUsageBits = usageBits;
813    return OK;
814}
815
816status_t ACodec::setPortMode(int32_t portIndex, IOMX::PortMode mode) {
817    status_t err = mOMXNode->setPortMode(portIndex, mode);
818    if (err != OK) {
819        ALOGE("[%s] setPortMode on %s to %s failed w/ err %d",
820                mComponentName.c_str(),
821                portIndex == kPortIndexInput ? "input" : "output",
822                asString(mode),
823                err);
824        return err;
825    }
826
827    mPortMode[portIndex] = mode;
828    return OK;
829}
830
831status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) {
832    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
833
834    if (getTrebleFlag()) {
835        CHECK(mAllocator[portIndex] == NULL);
836    } else {
837        CHECK(mDealer[portIndex] == NULL);
838    }
839    CHECK(mBuffers[portIndex].isEmpty());
840
841    status_t err;
842    if (mNativeWindow != NULL && portIndex == kPortIndexOutput) {
843        if (storingMetadataInDecodedBuffers()) {
844            err = allocateOutputMetadataBuffers();
845        } else {
846            err = allocateOutputBuffersFromNativeWindow();
847        }
848    } else {
849        OMX_PARAM_PORTDEFINITIONTYPE def;
850        InitOMXParams(&def);
851        def.nPortIndex = portIndex;
852
853        err = mOMXNode->getParameter(
854                OMX_IndexParamPortDefinition, &def, sizeof(def));
855
856        if (err == OK) {
857            const IOMX::PortMode &mode = mPortMode[portIndex];
858            size_t bufSize = def.nBufferSize;
859            // Always allocate VideoNativeMetadata if using ANWBuffer.
860            // OMX might use gralloc source internally, but we don't share
861            // metadata buffer with OMX, OMX has its own headers.
862            if (mode == IOMX::kPortModeDynamicANWBuffer) {
863                bufSize = sizeof(VideoNativeMetadata);
864            } else if (mode == IOMX::kPortModeDynamicNativeHandle) {
865                bufSize = sizeof(VideoNativeHandleMetadata);
866            }
867
868            size_t conversionBufferSize = 0;
869
870            sp<DataConverter> converter = mConverter[portIndex];
871            if (converter != NULL) {
872                // here we assume sane conversions of max 4:1, so result fits in int32
873                if (portIndex == kPortIndexInput) {
874                    conversionBufferSize = converter->sourceSize(bufSize);
875                } else {
876                    conversionBufferSize = converter->targetSize(bufSize);
877                }
878            }
879
880            size_t alignment = MemoryDealer::getAllocationAlignment();
881
882            ALOGV("[%s] Allocating %u buffers of size %zu (from %u using %s) on %s port",
883                    mComponentName.c_str(),
884                    def.nBufferCountActual, bufSize, def.nBufferSize, asString(mode),
885                    portIndex == kPortIndexInput ? "input" : "output");
886
887            // verify buffer sizes to avoid overflow in align()
888            if (bufSize == 0 || max(bufSize, conversionBufferSize) > kMaxCodecBufferSize) {
889                ALOGE("b/22885421");
890                return NO_MEMORY;
891            }
892
893            // don't modify bufSize as OMX may not expect it to increase after negotiation
894            size_t alignedSize = align(bufSize, alignment);
895            size_t alignedConvSize = align(conversionBufferSize, alignment);
896            if (def.nBufferCountActual > SIZE_MAX / (alignedSize + alignedConvSize)) {
897                ALOGE("b/22885421");
898                return NO_MEMORY;
899            }
900
901            if (mode != IOMX::kPortModePresetSecureBuffer) {
902                if (getTrebleFlag()) {
903                    mAllocator[portIndex] = TAllocator::getService("ashmem");
904                    if (mAllocator[portIndex] == nullptr) {
905                        ALOGE("hidl allocator on port %d is null",
906                                (int)portIndex);
907                        return NO_MEMORY;
908                    }
909                } else {
910                    size_t totalSize = def.nBufferCountActual *
911                            (alignedSize + alignedConvSize);
912                    mDealer[portIndex] = new MemoryDealer(totalSize, "ACodec");
913                }
914            }
915
916            const sp<AMessage> &format =
917                    portIndex == kPortIndexInput ? mInputFormat : mOutputFormat;
918            for (OMX_U32 i = 0; i < def.nBufferCountActual && err == OK; ++i) {
919                hidl_memory hidlMemToken;
920                sp<TMemory> hidlMem;
921                sp<IMemory> mem;
922
923                BufferInfo info;
924                info.mStatus = BufferInfo::OWNED_BY_US;
925                info.mFenceFd = -1;
926                info.mRenderInfo = NULL;
927                info.mGraphicBuffer = NULL;
928                info.mNewGraphicBuffer = false;
929
930                if (mode == IOMX::kPortModePresetSecureBuffer) {
931                    void *ptr = NULL;
932                    sp<NativeHandle> native_handle;
933                    err = mOMXNode->allocateSecureBuffer(
934                            portIndex, bufSize, &info.mBufferID,
935                            &ptr, &native_handle);
936
937                    info.mData = (native_handle == NULL)
938                            ? new SecureBuffer(format, ptr, bufSize)
939                            : new SecureBuffer(format, native_handle, bufSize);
940                    info.mCodecData = info.mData;
941                } else {
942                    if (getTrebleFlag()) {
943                        bool success;
944                        auto transStatus = mAllocator[portIndex]->allocate(
945                                bufSize,
946                                [&success, &hidlMemToken](
947                                        bool s,
948                                        hidl_memory const& m) {
949                                    success = s;
950                                    hidlMemToken = m;
951                                });
952
953                        if (!transStatus.isOk()) {
954                            ALOGE("hidl's AshmemAllocator failed at the "
955                                    "transport: %s",
956                                    transStatus.description().c_str());
957                            return NO_MEMORY;
958                        }
959                        if (!success) {
960                            return NO_MEMORY;
961                        }
962                        hidlMem = mapMemory(hidlMemToken);
963
964                        err = mOMXNode->useBuffer(
965                                portIndex, hidlMemToken, &info.mBufferID);
966                    } else {
967                        mem = mDealer[portIndex]->allocate(bufSize);
968                        if (mem == NULL || mem->pointer() == NULL) {
969                            return NO_MEMORY;
970                        }
971
972                        err = mOMXNode->useBuffer(
973                                portIndex, mem, &info.mBufferID);
974                    }
975
976                    if (mode == IOMX::kPortModeDynamicANWBuffer) {
977                        VideoNativeMetadata* metaData = (VideoNativeMetadata*)(
978                                getTrebleFlag() ?
979                                (void*)hidlMem->getPointer() : mem->pointer());
980                        metaData->nFenceFd = -1;
981                    }
982
983                    if (getTrebleFlag()) {
984                        info.mCodecData = new SharedMemoryBuffer(
985                                format, hidlMem);
986                        info.mCodecRef = hidlMem;
987                    } else {
988                        info.mCodecData = new SharedMemoryBuffer(
989                                format, mem);
990                        info.mCodecRef = mem;
991                    }
992
993                    // if we require conversion, allocate conversion buffer for client use;
994                    // otherwise, reuse codec buffer
995                    if (mConverter[portIndex] != NULL) {
996                        CHECK_GT(conversionBufferSize, (size_t)0);
997                        if (getTrebleFlag()) {
998                            bool success;
999                            mAllocator[portIndex]->allocate(
1000                                    conversionBufferSize,
1001                                    [&success, &hidlMemToken](
1002                                            bool s,
1003                                            hidl_memory const& m) {
1004                                        success = s;
1005                                        hidlMemToken = m;
1006                                    });
1007                            if (!success) {
1008                                return NO_MEMORY;
1009                            }
1010                            hidlMem = mapMemory(hidlMemToken);
1011                            info.mData = new SharedMemoryBuffer(format, hidlMem);
1012                            info.mMemRef = hidlMem;
1013                        } else {
1014                            mem = mDealer[portIndex]->allocate(
1015                                    conversionBufferSize);
1016                            if (mem == NULL|| mem->pointer() == NULL) {
1017                                return NO_MEMORY;
1018                            }
1019                            info.mData = new SharedMemoryBuffer(format, mem);
1020                            info.mMemRef = mem;
1021                        }
1022                    } else {
1023                        info.mData = info.mCodecData;
1024                        info.mMemRef = info.mCodecRef;
1025                    }
1026                }
1027
1028                mBuffers[portIndex].push(info);
1029            }
1030        }
1031    }
1032
1033    if (err != OK) {
1034        return err;
1035    }
1036
1037    std::vector<ACodecBufferChannel::BufferAndId> array(mBuffers[portIndex].size());
1038    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
1039        array[i] = {mBuffers[portIndex][i].mData, mBuffers[portIndex][i].mBufferID};
1040    }
1041    if (portIndex == kPortIndexInput) {
1042        mBufferChannel->setInputBufferArray(array);
1043    } else if (portIndex == kPortIndexOutput) {
1044        mBufferChannel->setOutputBufferArray(array);
1045    } else {
1046        TRESPASS();
1047    }
1048
1049    return OK;
1050}
1051
1052status_t ACodec::setupNativeWindowSizeFormatAndUsage(
1053        ANativeWindow *nativeWindow /* nonnull */, int *finalUsage /* nonnull */,
1054        bool reconnect) {
1055    OMX_PARAM_PORTDEFINITIONTYPE def;
1056    InitOMXParams(&def);
1057    def.nPortIndex = kPortIndexOutput;
1058
1059    status_t err = mOMXNode->getParameter(
1060            OMX_IndexParamPortDefinition, &def, sizeof(def));
1061
1062    if (err != OK) {
1063        return err;
1064    }
1065
1066    OMX_INDEXTYPE index;
1067    err = mOMXNode->getExtensionIndex(
1068            "OMX.google.android.index.AndroidNativeBufferConsumerUsage",
1069            &index);
1070
1071    if (err != OK) {
1072        // allow failure
1073        err = OK;
1074    } else {
1075        int usageBits = 0;
1076        if (nativeWindow->query(
1077                nativeWindow,
1078                NATIVE_WINDOW_CONSUMER_USAGE_BITS,
1079                &usageBits) == OK) {
1080            OMX_PARAM_U32TYPE params;
1081            InitOMXParams(&params);
1082            params.nPortIndex = kPortIndexOutput;
1083            params.nU32 = (OMX_U32)usageBits;
1084
1085            err = mOMXNode->setParameter(index, &params, sizeof(params));
1086
1087            if (err != OK) {
1088                ALOGE("Fail to set AndroidNativeBufferConsumerUsage: %d", err);
1089                return err;
1090            }
1091        }
1092    }
1093
1094    OMX_U32 usage = 0;
1095    err = mOMXNode->getGraphicBufferUsage(kPortIndexOutput, &usage);
1096    if (err != 0) {
1097        ALOGW("querying usage flags from OMX IL component failed: %d", err);
1098        // XXX: Currently this error is logged, but not fatal.
1099        usage = 0;
1100    }
1101    int omxUsage = usage;
1102
1103    if (mFlags & kFlagIsGrallocUsageProtected) {
1104        usage |= GRALLOC_USAGE_PROTECTED;
1105    }
1106
1107    usage |= kVideoGrallocUsage;
1108    *finalUsage = usage;
1109
1110    memset(&mLastNativeWindowCrop, 0, sizeof(mLastNativeWindowCrop));
1111    mLastNativeWindowDataSpace = HAL_DATASPACE_UNKNOWN;
1112
1113    ALOGV("gralloc usage: %#x(OMX) => %#x(ACodec)", omxUsage, usage);
1114    return setNativeWindowSizeFormatAndUsage(
1115            nativeWindow,
1116            def.format.video.nFrameWidth,
1117            def.format.video.nFrameHeight,
1118            def.format.video.eColorFormat,
1119            mRotationDegrees,
1120            usage,
1121            reconnect);
1122}
1123
1124status_t ACodec::configureOutputBuffersFromNativeWindow(
1125        OMX_U32 *bufferCount, OMX_U32 *bufferSize,
1126        OMX_U32 *minUndequeuedBuffers, bool preregister) {
1127
1128    OMX_PARAM_PORTDEFINITIONTYPE def;
1129    InitOMXParams(&def);
1130    def.nPortIndex = kPortIndexOutput;
1131
1132    status_t err = mOMXNode->getParameter(
1133            OMX_IndexParamPortDefinition, &def, sizeof(def));
1134
1135    if (err == OK) {
1136        err = setupNativeWindowSizeFormatAndUsage(
1137                mNativeWindow.get(), &mNativeWindowUsageBits,
1138                preregister && !mTunneled /* reconnect */);
1139    }
1140    if (err != OK) {
1141        mNativeWindowUsageBits = 0;
1142        return err;
1143    }
1144
1145    // Exits here for tunneled video playback codecs -- i.e. skips native window
1146    // buffer allocation step as this is managed by the tunneled OMX omponent
1147    // itself and explicitly sets def.nBufferCountActual to 0.
1148    if (mTunneled) {
1149        ALOGV("Tunneled Playback: skipping native window buffer allocation.");
1150        def.nBufferCountActual = 0;
1151        err = mOMXNode->setParameter(
1152                OMX_IndexParamPortDefinition, &def, sizeof(def));
1153
1154        *minUndequeuedBuffers = 0;
1155        *bufferCount = 0;
1156        *bufferSize = 0;
1157        return err;
1158    }
1159
1160    *minUndequeuedBuffers = 0;
1161    err = mNativeWindow->query(
1162            mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
1163            (int *)minUndequeuedBuffers);
1164
1165    if (err != 0) {
1166        ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)",
1167                strerror(-err), -err);
1168        return err;
1169    }
1170
1171    // FIXME: assume that surface is controlled by app (native window
1172    // returns the number for the case when surface is not controlled by app)
1173    // FIXME2: This means that minUndeqeueudBufs can be 1 larger than reported
1174    // For now, try to allocate 1 more buffer, but don't fail if unsuccessful
1175
1176    // Use conservative allocation while also trying to reduce starvation
1177    //
1178    // 1. allocate at least nBufferCountMin + minUndequeuedBuffers - that is the
1179    //    minimum needed for the consumer to be able to work
1180    // 2. try to allocate two (2) additional buffers to reduce starvation from
1181    //    the consumer
1182    //    plus an extra buffer to account for incorrect minUndequeuedBufs
1183    for (OMX_U32 extraBuffers = 2 + 1; /* condition inside loop */; extraBuffers--) {
1184        OMX_U32 newBufferCount =
1185            def.nBufferCountMin + *minUndequeuedBuffers + extraBuffers;
1186        def.nBufferCountActual = newBufferCount;
1187        err = mOMXNode->setParameter(
1188                OMX_IndexParamPortDefinition, &def, sizeof(def));
1189
1190        if (err == OK) {
1191            *minUndequeuedBuffers += extraBuffers;
1192            break;
1193        }
1194
1195        ALOGW("[%s] setting nBufferCountActual to %u failed: %d",
1196                mComponentName.c_str(), newBufferCount, err);
1197        /* exit condition */
1198        if (extraBuffers == 0) {
1199            return err;
1200        }
1201    }
1202
1203    err = native_window_set_buffer_count(
1204            mNativeWindow.get(), def.nBufferCountActual);
1205
1206    if (err != 0) {
1207        ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err),
1208                -err);
1209        return err;
1210    }
1211
1212    *bufferCount = def.nBufferCountActual;
1213    *bufferSize =  def.nBufferSize;
1214    return err;
1215}
1216
1217status_t ACodec::allocateOutputBuffersFromNativeWindow() {
1218    // This method only handles the non-metadata mode (or simulating legacy
1219    // mode with metadata, which is transparent to ACodec).
1220    CHECK(!storingMetadataInDecodedBuffers());
1221
1222    OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers;
1223    status_t err = configureOutputBuffersFromNativeWindow(
1224            &bufferCount, &bufferSize, &minUndequeuedBuffers, true /* preregister */);
1225    if (err != 0)
1226        return err;
1227    mNumUndequeuedBuffers = minUndequeuedBuffers;
1228
1229    static_cast<Surface*>(mNativeWindow.get())
1230            ->getIGraphicBufferProducer()->allowAllocation(true);
1231
1232    ALOGV("[%s] Allocating %u buffers from a native window of size %u on "
1233         "output port",
1234         mComponentName.c_str(), bufferCount, bufferSize);
1235
1236    // Dequeue buffers and send them to OMX
1237    for (OMX_U32 i = 0; i < bufferCount; i++) {
1238        ANativeWindowBuffer *buf;
1239        int fenceFd;
1240        err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf, &fenceFd);
1241        if (err != 0) {
1242            ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
1243            break;
1244        }
1245
1246        sp<GraphicBuffer> graphicBuffer(GraphicBuffer::from(buf));
1247        BufferInfo info;
1248        info.mStatus = BufferInfo::OWNED_BY_US;
1249        info.mFenceFd = fenceFd;
1250        info.mIsReadFence = false;
1251        info.mRenderInfo = NULL;
1252        info.mGraphicBuffer = graphicBuffer;
1253        info.mNewGraphicBuffer = false;
1254
1255        // TODO: We shouln't need to create MediaCodecBuffer. In metadata mode
1256        //       OMX doesn't use the shared memory buffer, but some code still
1257        //       access info.mData. Create an ABuffer as a placeholder.
1258        info.mData = new MediaCodecBuffer(mOutputFormat, new ABuffer(bufferSize));
1259        info.mCodecData = info.mData;
1260
1261        mBuffers[kPortIndexOutput].push(info);
1262
1263        IOMX::buffer_id bufferId;
1264        err = mOMXNode->useBuffer(kPortIndexOutput, graphicBuffer, &bufferId);
1265        if (err != 0) {
1266            ALOGE("registering GraphicBuffer %u with OMX IL component failed: "
1267                 "%d", i, err);
1268            break;
1269        }
1270
1271        mBuffers[kPortIndexOutput].editItemAt(i).mBufferID = bufferId;
1272
1273        ALOGV("[%s] Registered graphic buffer with ID %u (pointer = %p)",
1274             mComponentName.c_str(),
1275             bufferId, graphicBuffer.get());
1276    }
1277
1278    OMX_U32 cancelStart;
1279    OMX_U32 cancelEnd;
1280
1281    if (err != OK) {
1282        // If an error occurred while dequeuing we need to cancel any buffers
1283        // that were dequeued. Also cancel all if we're in legacy metadata mode.
1284        cancelStart = 0;
1285        cancelEnd = mBuffers[kPortIndexOutput].size();
1286    } else {
1287        // Return the required minimum undequeued buffers to the native window.
1288        cancelStart = bufferCount - minUndequeuedBuffers;
1289        cancelEnd = bufferCount;
1290    }
1291
1292    for (OMX_U32 i = cancelStart; i < cancelEnd; i++) {
1293        BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
1294        if (info->mStatus == BufferInfo::OWNED_BY_US) {
1295            status_t error = cancelBufferToNativeWindow(info);
1296            if (err == 0) {
1297                err = error;
1298            }
1299        }
1300    }
1301
1302    static_cast<Surface*>(mNativeWindow.get())
1303            ->getIGraphicBufferProducer()->allowAllocation(false);
1304
1305    return err;
1306}
1307
1308status_t ACodec::allocateOutputMetadataBuffers() {
1309    CHECK(storingMetadataInDecodedBuffers());
1310
1311    OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers;
1312    status_t err = configureOutputBuffersFromNativeWindow(
1313            &bufferCount, &bufferSize, &minUndequeuedBuffers,
1314            false /* preregister */);
1315    if (err != OK)
1316        return err;
1317    mNumUndequeuedBuffers = minUndequeuedBuffers;
1318
1319    ALOGV("[%s] Allocating %u meta buffers on output port",
1320         mComponentName.c_str(), bufferCount);
1321
1322    for (OMX_U32 i = 0; i < bufferCount; i++) {
1323        BufferInfo info;
1324        info.mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
1325        info.mFenceFd = -1;
1326        info.mRenderInfo = NULL;
1327        info.mGraphicBuffer = NULL;
1328        info.mNewGraphicBuffer = false;
1329        info.mDequeuedAt = mDequeueCounter;
1330
1331        info.mData = new MediaCodecBuffer(mOutputFormat, new ABuffer(bufferSize));
1332
1333        // Initialize fence fd to -1 to avoid warning in freeBuffer().
1334        ((VideoNativeMetadata *)info.mData->base())->nFenceFd = -1;
1335
1336        info.mCodecData = info.mData;
1337
1338        err = mOMXNode->useBuffer(kPortIndexOutput, OMXBuffer::sPreset, &info.mBufferID);
1339        mBuffers[kPortIndexOutput].push(info);
1340
1341        ALOGV("[%s] allocated meta buffer with ID %u",
1342                mComponentName.c_str(), info.mBufferID);
1343    }
1344
1345    mMetadataBuffersToSubmit = bufferCount - minUndequeuedBuffers;
1346    return err;
1347}
1348
1349status_t ACodec::submitOutputMetadataBuffer() {
1350    CHECK(storingMetadataInDecodedBuffers());
1351    if (mMetadataBuffersToSubmit == 0)
1352        return OK;
1353
1354    BufferInfo *info = dequeueBufferFromNativeWindow();
1355    if (info == NULL) {
1356        return ERROR_IO;
1357    }
1358
1359    ALOGV("[%s] submitting output meta buffer ID %u for graphic buffer %p",
1360          mComponentName.c_str(), info->mBufferID, info->mGraphicBuffer->handle);
1361
1362    --mMetadataBuffersToSubmit;
1363    info->checkWriteFence("submitOutputMetadataBuffer");
1364    return fillBuffer(info);
1365}
1366
1367status_t ACodec::waitForFence(int fd, const char *dbg ) {
1368    status_t res = OK;
1369    if (fd >= 0) {
1370        sp<Fence> fence = new Fence(fd);
1371        res = fence->wait(IOMX::kFenceTimeoutMs);
1372        ALOGW_IF(res != OK, "FENCE TIMEOUT for %d in %s", fd, dbg);
1373    }
1374    return res;
1375}
1376
1377// static
1378const char *ACodec::_asString(BufferInfo::Status s) {
1379    switch (s) {
1380        case BufferInfo::OWNED_BY_US:            return "OUR";
1381        case BufferInfo::OWNED_BY_COMPONENT:     return "COMPONENT";
1382        case BufferInfo::OWNED_BY_UPSTREAM:      return "UPSTREAM";
1383        case BufferInfo::OWNED_BY_DOWNSTREAM:    return "DOWNSTREAM";
1384        case BufferInfo::OWNED_BY_NATIVE_WINDOW: return "SURFACE";
1385        case BufferInfo::UNRECOGNIZED:           return "UNRECOGNIZED";
1386        default:                                 return "?";
1387    }
1388}
1389
1390void ACodec::dumpBuffers(OMX_U32 portIndex) {
1391    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
1392    ALOGI("[%s] %s port has %zu buffers:", mComponentName.c_str(),
1393            portIndex == kPortIndexInput ? "input" : "output", mBuffers[portIndex].size());
1394    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
1395        const BufferInfo &info = mBuffers[portIndex][i];
1396        ALOGI("  slot %2zu: #%8u %p/%p %s(%d) dequeued:%u",
1397                i, info.mBufferID, info.mGraphicBuffer.get(),
1398                info.mGraphicBuffer == NULL ? NULL : info.mGraphicBuffer->getNativeBuffer(),
1399                _asString(info.mStatus), info.mStatus, info.mDequeuedAt);
1400    }
1401}
1402
1403status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) {
1404    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
1405
1406    ALOGV("[%s] Calling cancelBuffer on buffer %u",
1407         mComponentName.c_str(), info->mBufferID);
1408
1409    info->checkWriteFence("cancelBufferToNativeWindow");
1410    int err = mNativeWindow->cancelBuffer(
1411        mNativeWindow.get(), info->mGraphicBuffer.get(), info->mFenceFd);
1412    info->mFenceFd = -1;
1413
1414    ALOGW_IF(err != 0, "[%s] can not return buffer %u to native window",
1415            mComponentName.c_str(), info->mBufferID);
1416    // change ownership even if cancelBuffer fails
1417    info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
1418
1419    return err;
1420}
1421
1422void ACodec::updateRenderInfoForDequeuedBuffer(
1423        ANativeWindowBuffer *buf, int fenceFd, BufferInfo *info) {
1424
1425    info->mRenderInfo =
1426        mRenderTracker.updateInfoForDequeuedBuffer(
1427                buf, fenceFd, info - &mBuffers[kPortIndexOutput][0]);
1428
1429    // check for any fences already signaled
1430    notifyOfRenderedFrames(false /* dropIncomplete */, info->mRenderInfo);
1431}
1432
1433void ACodec::onFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano) {
1434    if (mRenderTracker.onFrameRendered(mediaTimeUs, systemNano) != OK) {
1435        mRenderTracker.dumpRenderQueue();
1436    }
1437}
1438
1439void ACodec::notifyOfRenderedFrames(bool dropIncomplete, FrameRenderTracker::Info *until) {
1440    std::list<FrameRenderTracker::Info> done =
1441        mRenderTracker.checkFencesAndGetRenderedFrames(until, dropIncomplete);
1442
1443    // unlink untracked frames
1444    for (std::list<FrameRenderTracker::Info>::const_iterator it = done.cbegin();
1445            it != done.cend(); ++it) {
1446        ssize_t index = it->getIndex();
1447        if (index >= 0 && (size_t)index < mBuffers[kPortIndexOutput].size()) {
1448            mBuffers[kPortIndexOutput].editItemAt(index).mRenderInfo = NULL;
1449        } else if (index >= 0) {
1450            // THIS SHOULD NEVER HAPPEN
1451            ALOGE("invalid index %zd in %zu", index, mBuffers[kPortIndexOutput].size());
1452        }
1453    }
1454
1455    mCallback->onOutputFramesRendered(done);
1456}
1457
1458ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() {
1459    ANativeWindowBuffer *buf;
1460    CHECK(mNativeWindow.get() != NULL);
1461
1462    if (mTunneled) {
1463        ALOGW("dequeueBufferFromNativeWindow() should not be called in tunnel"
1464              " video playback mode mode!");
1465        return NULL;
1466    }
1467
1468    if (mFatalError) {
1469        ALOGW("not dequeuing from native window due to fatal error");
1470        return NULL;
1471    }
1472
1473    int fenceFd = -1;
1474    do {
1475        status_t err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf, &fenceFd);
1476        if (err != 0) {
1477            ALOGE("dequeueBuffer failed: %s(%d).", asString(err), err);
1478            return NULL;
1479        }
1480
1481        bool stale = false;
1482        for (size_t i = mBuffers[kPortIndexOutput].size(); i > 0;) {
1483            i--;
1484            BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
1485
1486            if (info->mGraphicBuffer != NULL &&
1487                    info->mGraphicBuffer->handle == buf->handle) {
1488                // Since consumers can attach buffers to BufferQueues, it is possible
1489                // that a known yet stale buffer can return from a surface that we
1490                // once used.  We can simply ignore this as we have already dequeued
1491                // this buffer properly.  NOTE: this does not eliminate all cases,
1492                // e.g. it is possible that we have queued the valid buffer to the
1493                // NW, and a stale copy of the same buffer gets dequeued - which will
1494                // be treated as the valid buffer by ACodec.
1495                if (info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
1496                    ALOGI("dequeued stale buffer %p. discarding", buf);
1497                    stale = true;
1498                    break;
1499                }
1500
1501                ALOGV("dequeued buffer #%u with age %u, graphicBuffer %p",
1502                        (unsigned)(info - &mBuffers[kPortIndexOutput][0]),
1503                        mDequeueCounter - info->mDequeuedAt,
1504                        info->mGraphicBuffer->handle);
1505
1506                info->mStatus = BufferInfo::OWNED_BY_US;
1507                info->setWriteFence(fenceFd, "dequeueBufferFromNativeWindow");
1508                updateRenderInfoForDequeuedBuffer(buf, fenceFd, info);
1509                return info;
1510            }
1511        }
1512
1513        // It is also possible to receive a previously unregistered buffer
1514        // in non-meta mode. These should be treated as stale buffers. The
1515        // same is possible in meta mode, in which case, it will be treated
1516        // as a normal buffer, which is not desirable.
1517        // TODO: fix this.
1518        if (!stale && !storingMetadataInDecodedBuffers()) {
1519            ALOGI("dequeued unrecognized (stale) buffer %p. discarding", buf);
1520            stale = true;
1521        }
1522        if (stale) {
1523            // TODO: detach stale buffer, but there is no API yet to do it.
1524            buf = NULL;
1525        }
1526    } while (buf == NULL);
1527
1528    // get oldest undequeued buffer
1529    BufferInfo *oldest = NULL;
1530    for (size_t i = mBuffers[kPortIndexOutput].size(); i > 0;) {
1531        i--;
1532        BufferInfo *info =
1533            &mBuffers[kPortIndexOutput].editItemAt(i);
1534        if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW &&
1535            (oldest == NULL ||
1536             // avoid potential issues from counter rolling over
1537             mDequeueCounter - info->mDequeuedAt >
1538                    mDequeueCounter - oldest->mDequeuedAt)) {
1539            oldest = info;
1540        }
1541    }
1542
1543    // it is impossible dequeue a buffer when there are no buffers with ANW
1544    CHECK(oldest != NULL);
1545    // it is impossible to dequeue an unknown buffer in non-meta mode, as the
1546    // while loop above does not complete
1547    CHECK(storingMetadataInDecodedBuffers());
1548
1549    // discard buffer in LRU info and replace with new buffer
1550    oldest->mGraphicBuffer = GraphicBuffer::from(buf);
1551    oldest->mNewGraphicBuffer = true;
1552    oldest->mStatus = BufferInfo::OWNED_BY_US;
1553    oldest->setWriteFence(fenceFd, "dequeueBufferFromNativeWindow for oldest");
1554    mRenderTracker.untrackFrame(oldest->mRenderInfo);
1555    oldest->mRenderInfo = NULL;
1556
1557    ALOGV("replaced oldest buffer #%u with age %u, graphicBuffer %p",
1558            (unsigned)(oldest - &mBuffers[kPortIndexOutput][0]),
1559            mDequeueCounter - oldest->mDequeuedAt,
1560            oldest->mGraphicBuffer->handle);
1561
1562    updateRenderInfoForDequeuedBuffer(buf, fenceFd, oldest);
1563    return oldest;
1564}
1565
1566status_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) {
1567    if (portIndex == kPortIndexInput) {
1568        mBufferChannel->setInputBufferArray({});
1569    } else {
1570        mBufferChannel->setOutputBufferArray({});
1571    }
1572
1573    status_t err = OK;
1574    for (size_t i = mBuffers[portIndex].size(); i > 0;) {
1575        i--;
1576        status_t err2 = freeBuffer(portIndex, i);
1577        if (err == OK) {
1578            err = err2;
1579        }
1580    }
1581
1582    if (getTrebleFlag()) {
1583        mAllocator[portIndex].clear();
1584    } else {
1585        mDealer[portIndex].clear();
1586    }
1587    return err;
1588}
1589
1590status_t ACodec::freeOutputBuffersNotOwnedByComponent() {
1591    status_t err = OK;
1592    for (size_t i = mBuffers[kPortIndexOutput].size(); i > 0;) {
1593        i--;
1594        BufferInfo *info =
1595            &mBuffers[kPortIndexOutput].editItemAt(i);
1596
1597        // At this time some buffers may still be with the component
1598        // or being drained.
1599        if (info->mStatus != BufferInfo::OWNED_BY_COMPONENT &&
1600            info->mStatus != BufferInfo::OWNED_BY_DOWNSTREAM) {
1601            status_t err2 = freeBuffer(kPortIndexOutput, i);
1602            if (err == OK) {
1603                err = err2;
1604            }
1605        }
1606    }
1607
1608    return err;
1609}
1610
1611status_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) {
1612    BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
1613    status_t err = OK;
1614
1615    // there should not be any fences in the metadata
1616    if (mPortMode[portIndex] == IOMX::kPortModeDynamicANWBuffer && info->mCodecData != NULL
1617            && info->mCodecData->size() >= sizeof(VideoNativeMetadata)) {
1618        int fenceFd = ((VideoNativeMetadata *)info->mCodecData->base())->nFenceFd;
1619        if (fenceFd >= 0) {
1620            ALOGW("unreleased fence (%d) in %s metadata buffer %zu",
1621                    fenceFd, portIndex == kPortIndexInput ? "input" : "output", i);
1622        }
1623    }
1624
1625    switch (info->mStatus) {
1626        case BufferInfo::OWNED_BY_US:
1627            if (portIndex == kPortIndexOutput && mNativeWindow != NULL) {
1628                (void)cancelBufferToNativeWindow(info);
1629            }
1630            // fall through
1631
1632        case BufferInfo::OWNED_BY_NATIVE_WINDOW:
1633            err = mOMXNode->freeBuffer(portIndex, info->mBufferID);
1634            break;
1635
1636        default:
1637            ALOGE("trying to free buffer not owned by us or ANW (%d)", info->mStatus);
1638            err = FAILED_TRANSACTION;
1639            break;
1640    }
1641
1642    if (info->mFenceFd >= 0) {
1643        ::close(info->mFenceFd);
1644    }
1645
1646    if (portIndex == kPortIndexOutput) {
1647        mRenderTracker.untrackFrame(info->mRenderInfo, i);
1648        info->mRenderInfo = NULL;
1649    }
1650
1651    // remove buffer even if mOMXNode->freeBuffer fails
1652    mBuffers[portIndex].removeAt(i);
1653    return err;
1654}
1655
1656ACodec::BufferInfo *ACodec::findBufferByID(
1657        uint32_t portIndex, IOMX::buffer_id bufferID, ssize_t *index) {
1658    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
1659        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
1660
1661        if (info->mBufferID == bufferID) {
1662            if (index != NULL) {
1663                *index = i;
1664            }
1665            return info;
1666        }
1667    }
1668
1669    ALOGE("Could not find buffer with ID %u", bufferID);
1670    return NULL;
1671}
1672
1673status_t ACodec::fillBuffer(BufferInfo *info) {
1674    status_t err;
1675    // Even in dynamic ANW buffer mode, if the graphic buffer is not changing,
1676    // send sPreset instead of the same graphic buffer, so that OMX server
1677    // side doesn't update the meta. In theory it should make no difference,
1678    // however when the same buffer is parcelled again, a new handle could be
1679    // created on server side, and some decoder doesn't recognize the handle
1680    // even if it's the same buffer.
1681    if (!storingMetadataInDecodedBuffers() || !info->mNewGraphicBuffer) {
1682        err = mOMXNode->fillBuffer(
1683            info->mBufferID, OMXBuffer::sPreset, info->mFenceFd);
1684    } else {
1685        err = mOMXNode->fillBuffer(
1686            info->mBufferID, info->mGraphicBuffer, info->mFenceFd);
1687    }
1688
1689    info->mNewGraphicBuffer = false;
1690    info->mFenceFd = -1;
1691    if (err == OK) {
1692        info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1693    }
1694    return err;
1695}
1696
1697status_t ACodec::setComponentRole(
1698        bool isEncoder, const char *mime) {
1699    const char *role = GetComponentRole(isEncoder, mime);
1700    if (role == NULL) {
1701        return BAD_VALUE;
1702    }
1703    status_t err = SetComponentRole(mOMXNode, role);
1704    if (err != OK) {
1705        ALOGW("[%s] Failed to set standard component role '%s'.",
1706             mComponentName.c_str(), role);
1707    }
1708    return err;
1709}
1710
1711status_t ACodec::configureCodec(
1712        const char *mime, const sp<AMessage> &msg) {
1713    int32_t encoder;
1714    if (!msg->findInt32("encoder", &encoder)) {
1715        encoder = false;
1716    }
1717
1718    sp<AMessage> inputFormat = new AMessage;
1719    sp<AMessage> outputFormat = new AMessage;
1720    mConfigFormat = msg;
1721
1722    mIsEncoder = encoder;
1723
1724    mPortMode[kPortIndexInput] = IOMX::kPortModePresetByteBuffer;
1725    mPortMode[kPortIndexOutput] = IOMX::kPortModePresetByteBuffer;
1726
1727    status_t err = setComponentRole(encoder /* isEncoder */, mime);
1728
1729    if (err != OK) {
1730        return err;
1731    }
1732
1733    int32_t bitRate = 0;
1734    // FLAC encoder doesn't need a bitrate, other encoders do
1735    if (encoder && strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)
1736            && !msg->findInt32("bitrate", &bitRate)) {
1737        return INVALID_OPERATION;
1738    }
1739
1740    // propagate bitrate to the output so that the muxer has it
1741    if (encoder && msg->findInt32("bitrate", &bitRate)) {
1742        // Technically ISO spec says that 'bitrate' should be 0 for VBR even though it is the
1743        // average bitrate. We've been setting both bitrate and max-bitrate to this same value.
1744        outputFormat->setInt32("bitrate", bitRate);
1745        outputFormat->setInt32("max-bitrate", bitRate);
1746    }
1747
1748    int32_t storeMeta;
1749    if (encoder
1750            && msg->findInt32("android._input-metadata-buffer-type", &storeMeta)
1751            && storeMeta != kMetadataBufferTypeInvalid) {
1752        IOMX::PortMode mode;
1753        if (storeMeta == kMetadataBufferTypeNativeHandleSource) {
1754            mode = IOMX::kPortModeDynamicNativeHandle;
1755        } else if (storeMeta == kMetadataBufferTypeANWBuffer ||
1756                storeMeta == kMetadataBufferTypeGrallocSource) {
1757            mode = IOMX::kPortModeDynamicANWBuffer;
1758        } else {
1759            return BAD_VALUE;
1760        }
1761        err = setPortMode(kPortIndexInput, mode);
1762        if (err != OK) {
1763            return err;
1764        }
1765
1766        uint32_t usageBits;
1767        if (mOMXNode->getParameter(
1768                (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
1769                &usageBits, sizeof(usageBits)) == OK) {
1770            inputFormat->setInt32(
1771                    "using-sw-read-often", !!(usageBits & GRALLOC_USAGE_SW_READ_OFTEN));
1772        }
1773    }
1774
1775    int32_t prependSPSPPS = 0;
1776    if (encoder
1777            && msg->findInt32("prepend-sps-pps-to-idr-frames", &prependSPSPPS)
1778            && prependSPSPPS != 0) {
1779        OMX_INDEXTYPE index;
1780        err = mOMXNode->getExtensionIndex(
1781                "OMX.google.android.index.prependSPSPPSToIDRFrames", &index);
1782
1783        if (err == OK) {
1784            PrependSPSPPSToIDRFramesParams params;
1785            InitOMXParams(&params);
1786            params.bEnable = OMX_TRUE;
1787
1788            err = mOMXNode->setParameter(index, &params, sizeof(params));
1789        }
1790
1791        if (err != OK) {
1792            ALOGE("Encoder could not be configured to emit SPS/PPS before "
1793                  "IDR frames. (err %d)", err);
1794
1795            return err;
1796        }
1797    }
1798
1799    // Only enable metadata mode on encoder output if encoder can prepend
1800    // sps/pps to idr frames, since in metadata mode the bitstream is in an
1801    // opaque handle, to which we don't have access.
1802    int32_t video = !strncasecmp(mime, "video/", 6);
1803    mIsVideo = video;
1804    if (encoder && video) {
1805        OMX_BOOL enable = (OMX_BOOL) (prependSPSPPS
1806            && msg->findInt32("android._store-metadata-in-buffers-output", &storeMeta)
1807            && storeMeta != 0);
1808        if (mFlags & kFlagIsSecure) {
1809            enable = OMX_TRUE;
1810        }
1811
1812        err = setPortMode(kPortIndexOutput, enable ?
1813                IOMX::kPortModePresetSecureBuffer : IOMX::kPortModePresetByteBuffer);
1814        if (err != OK) {
1815            return err;
1816        }
1817
1818        if (!msg->findInt64(
1819                    "repeat-previous-frame-after",
1820                    &mRepeatFrameDelayUs)) {
1821            mRepeatFrameDelayUs = -1ll;
1822        }
1823
1824        // only allow 32-bit value, since we pass it as U32 to OMX.
1825        if (!msg->findInt64("max-pts-gap-to-encoder", &mMaxPtsGapUs)) {
1826            mMaxPtsGapUs = -1ll;
1827        } else if (mMaxPtsGapUs > INT32_MAX || mMaxPtsGapUs < 0) {
1828            ALOGW("Unsupported value for max pts gap %lld", (long long) mMaxPtsGapUs);
1829            mMaxPtsGapUs = -1ll;
1830        }
1831
1832        if (!msg->findFloat("max-fps-to-encoder", &mMaxFps)) {
1833            mMaxFps = -1;
1834        }
1835
1836        if (!msg->findDouble("time-lapse-fps", &mCaptureFps)) {
1837            mCaptureFps = -1.0;
1838        }
1839
1840        if (!msg->findInt32(
1841                    "create-input-buffers-suspended",
1842                    (int32_t*)&mCreateInputBuffersSuspended)) {
1843            mCreateInputBuffersSuspended = false;
1844        }
1845    }
1846
1847    // NOTE: we only use native window for video decoders
1848    sp<RefBase> obj;
1849    bool haveNativeWindow = msg->findObject("native-window", &obj)
1850            && obj != NULL && video && !encoder;
1851    mUsingNativeWindow = haveNativeWindow;
1852    if (video && !encoder) {
1853        inputFormat->setInt32("adaptive-playback", false);
1854
1855        int32_t usageProtected;
1856        if (msg->findInt32("protected", &usageProtected) && usageProtected) {
1857            if (!haveNativeWindow) {
1858                ALOGE("protected output buffers must be sent to an ANativeWindow");
1859                return PERMISSION_DENIED;
1860            }
1861            mFlags |= kFlagIsGrallocUsageProtected;
1862            mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
1863        }
1864
1865        if (mFlags & kFlagIsSecure) {
1866            // use native_handles for secure input buffers
1867            err = setPortMode(kPortIndexInput, IOMX::kPortModePresetSecureBuffer);
1868
1869            if (err != OK) {
1870                ALOGI("falling back to non-native_handles");
1871                setPortMode(kPortIndexInput, IOMX::kPortModePresetByteBuffer);
1872                err = OK; // ignore error for now
1873            }
1874        }
1875    }
1876    if (haveNativeWindow) {
1877        sp<ANativeWindow> nativeWindow =
1878            static_cast<ANativeWindow *>(static_cast<Surface *>(obj.get()));
1879
1880        // START of temporary support for automatic FRC - THIS WILL BE REMOVED
1881        int32_t autoFrc;
1882        if (msg->findInt32("auto-frc", &autoFrc)) {
1883            bool enabled = autoFrc;
1884            OMX_CONFIG_BOOLEANTYPE config;
1885            InitOMXParams(&config);
1886            config.bEnabled = (OMX_BOOL)enabled;
1887            status_t temp = mOMXNode->setConfig(
1888                    (OMX_INDEXTYPE)OMX_IndexConfigAutoFramerateConversion,
1889                    &config, sizeof(config));
1890            if (temp == OK) {
1891                outputFormat->setInt32("auto-frc", enabled);
1892            } else if (enabled) {
1893                ALOGI("codec does not support requested auto-frc (err %d)", temp);
1894            }
1895        }
1896        // END of temporary support for automatic FRC
1897
1898        int32_t tunneled;
1899        if (msg->findInt32("feature-tunneled-playback", &tunneled) &&
1900            tunneled != 0) {
1901            ALOGI("Configuring TUNNELED video playback.");
1902            mTunneled = true;
1903
1904            int32_t audioHwSync = 0;
1905            if (!msg->findInt32("audio-hw-sync", &audioHwSync)) {
1906                ALOGW("No Audio HW Sync provided for video tunnel");
1907            }
1908            err = configureTunneledVideoPlayback(audioHwSync, nativeWindow);
1909            if (err != OK) {
1910                ALOGE("configureTunneledVideoPlayback(%d,%p) failed!",
1911                        audioHwSync, nativeWindow.get());
1912                return err;
1913            }
1914
1915            int32_t maxWidth = 0, maxHeight = 0;
1916            if (msg->findInt32("max-width", &maxWidth) &&
1917                    msg->findInt32("max-height", &maxHeight)) {
1918
1919                err = mOMXNode->prepareForAdaptivePlayback(
1920                        kPortIndexOutput, OMX_TRUE, maxWidth, maxHeight);
1921                if (err != OK) {
1922                    ALOGW("[%s] prepareForAdaptivePlayback failed w/ err %d",
1923                            mComponentName.c_str(), err);
1924                    // allow failure
1925                    err = OK;
1926                } else {
1927                    inputFormat->setInt32("max-width", maxWidth);
1928                    inputFormat->setInt32("max-height", maxHeight);
1929                    inputFormat->setInt32("adaptive-playback", true);
1930                }
1931            }
1932        } else {
1933            ALOGV("Configuring CPU controlled video playback.");
1934            mTunneled = false;
1935
1936            // Explicity reset the sideband handle of the window for
1937            // non-tunneled video in case the window was previously used
1938            // for a tunneled video playback.
1939            err = native_window_set_sideband_stream(nativeWindow.get(), NULL);
1940            if (err != OK) {
1941                ALOGE("set_sideband_stream(NULL) failed! (err %d).", err);
1942                return err;
1943            }
1944
1945            err = setPortMode(kPortIndexOutput, IOMX::kPortModeDynamicANWBuffer);
1946            if (err != OK) {
1947                // if adaptive playback has been requested, try JB fallback
1948                // NOTE: THIS FALLBACK MECHANISM WILL BE REMOVED DUE TO ITS
1949                // LARGE MEMORY REQUIREMENT
1950
1951                // we will not do adaptive playback on software accessed
1952                // surfaces as they never had to respond to changes in the
1953                // crop window, and we don't trust that they will be able to.
1954                int usageBits = 0;
1955                bool canDoAdaptivePlayback;
1956
1957                if (nativeWindow->query(
1958                        nativeWindow.get(),
1959                        NATIVE_WINDOW_CONSUMER_USAGE_BITS,
1960                        &usageBits) != OK) {
1961                    canDoAdaptivePlayback = false;
1962                } else {
1963                    canDoAdaptivePlayback =
1964                        (usageBits &
1965                                (GRALLOC_USAGE_SW_READ_MASK |
1966                                 GRALLOC_USAGE_SW_WRITE_MASK)) == 0;
1967                }
1968
1969                int32_t maxWidth = 0, maxHeight = 0;
1970                if (canDoAdaptivePlayback &&
1971                        msg->findInt32("max-width", &maxWidth) &&
1972                        msg->findInt32("max-height", &maxHeight)) {
1973                    ALOGV("[%s] prepareForAdaptivePlayback(%dx%d)",
1974                            mComponentName.c_str(), maxWidth, maxHeight);
1975
1976                    err = mOMXNode->prepareForAdaptivePlayback(
1977                            kPortIndexOutput, OMX_TRUE, maxWidth, maxHeight);
1978                    ALOGW_IF(err != OK,
1979                            "[%s] prepareForAdaptivePlayback failed w/ err %d",
1980                            mComponentName.c_str(), err);
1981
1982                    if (err == OK) {
1983                        inputFormat->setInt32("max-width", maxWidth);
1984                        inputFormat->setInt32("max-height", maxHeight);
1985                        inputFormat->setInt32("adaptive-playback", true);
1986                    }
1987                }
1988                // allow failure
1989                err = OK;
1990            } else {
1991                ALOGV("[%s] setPortMode on output to %s succeeded",
1992                        mComponentName.c_str(), asString(IOMX::kPortModeDynamicANWBuffer));
1993                CHECK(storingMetadataInDecodedBuffers());
1994                inputFormat->setInt32("adaptive-playback", true);
1995            }
1996
1997            int32_t push;
1998            if (msg->findInt32("push-blank-buffers-on-shutdown", &push)
1999                    && push != 0) {
2000                mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
2001            }
2002        }
2003
2004        int32_t rotationDegrees;
2005        if (msg->findInt32("rotation-degrees", &rotationDegrees)) {
2006            mRotationDegrees = rotationDegrees;
2007        } else {
2008            mRotationDegrees = 0;
2009        }
2010    }
2011
2012    AudioEncoding pcmEncoding = kAudioEncodingPcm16bit;
2013    (void)msg->findInt32("pcm-encoding", (int32_t*)&pcmEncoding);
2014    // invalid encodings will default to PCM-16bit in setupRawAudioFormat.
2015
2016    if (video) {
2017        // determine need for software renderer
2018        bool usingSwRenderer = false;
2019        if (haveNativeWindow && mComponentName.startsWith("OMX.google.")) {
2020            usingSwRenderer = true;
2021            haveNativeWindow = false;
2022            (void)setPortMode(kPortIndexOutput, IOMX::kPortModePresetByteBuffer);
2023        } else if (haveNativeWindow && !storingMetadataInDecodedBuffers()) {
2024            err = setPortMode(kPortIndexOutput, IOMX::kPortModePresetANWBuffer);
2025            if (err != OK) {
2026                return err;
2027            }
2028        }
2029
2030        if (encoder) {
2031            err = setupVideoEncoder(mime, msg, outputFormat, inputFormat);
2032        } else {
2033            err = setupVideoDecoder(mime, msg, haveNativeWindow, usingSwRenderer, outputFormat);
2034        }
2035
2036        if (err != OK) {
2037            return err;
2038        }
2039
2040        if (haveNativeWindow) {
2041            mNativeWindow = static_cast<Surface *>(obj.get());
2042
2043            // fallback for devices that do not handle flex-YUV for native buffers
2044            int32_t requestedColorFormat = OMX_COLOR_FormatUnused;
2045            if (msg->findInt32("color-format", &requestedColorFormat) &&
2046                    requestedColorFormat == OMX_COLOR_FormatYUV420Flexible) {
2047                status_t err = getPortFormat(kPortIndexOutput, outputFormat);
2048                if (err != OK) {
2049                    return err;
2050                }
2051                int32_t colorFormat = OMX_COLOR_FormatUnused;
2052                OMX_U32 flexibleEquivalent = OMX_COLOR_FormatUnused;
2053                if (!outputFormat->findInt32("color-format", &colorFormat)) {
2054                    ALOGE("ouptut port did not have a color format (wrong domain?)");
2055                    return BAD_VALUE;
2056                }
2057                ALOGD("[%s] Requested output format %#x and got %#x.",
2058                        mComponentName.c_str(), requestedColorFormat, colorFormat);
2059                if (!IsFlexibleColorFormat(
2060                        mOMXNode, colorFormat, haveNativeWindow, &flexibleEquivalent)
2061                        || flexibleEquivalent != (OMX_U32)requestedColorFormat) {
2062                    // device did not handle flex-YUV request for native window, fall back
2063                    // to SW renderer
2064                    ALOGI("[%s] Falling back to software renderer", mComponentName.c_str());
2065                    mNativeWindow.clear();
2066                    mNativeWindowUsageBits = 0;
2067                    haveNativeWindow = false;
2068                    usingSwRenderer = true;
2069                    // TODO: implement adaptive-playback support for bytebuffer mode.
2070                    // This is done by SW codecs, but most HW codecs don't support it.
2071                    err = setPortMode(kPortIndexOutput, IOMX::kPortModePresetByteBuffer);
2072                    inputFormat->setInt32("adaptive-playback", false);
2073                    if (mFlags & kFlagIsGrallocUsageProtected) {
2074                        // fallback is not supported for protected playback
2075                        err = PERMISSION_DENIED;
2076                    } else if (err == OK) {
2077                        err = setupVideoDecoder(
2078                                mime, msg, haveNativeWindow, usingSwRenderer, outputFormat);
2079                    }
2080                }
2081            }
2082        }
2083
2084        if (usingSwRenderer) {
2085            outputFormat->setInt32("using-sw-renderer", 1);
2086        }
2087    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
2088        int32_t numChannels, sampleRate;
2089        if (!msg->findInt32("channel-count", &numChannels)
2090                || !msg->findInt32("sample-rate", &sampleRate)) {
2091            // Since we did not always check for these, leave them optional
2092            // and have the decoder figure it all out.
2093            err = OK;
2094        } else {
2095            err = setupRawAudioFormat(
2096                    encoder ? kPortIndexInput : kPortIndexOutput,
2097                    sampleRate,
2098                    numChannels);
2099        }
2100    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
2101        int32_t numChannels, sampleRate;
2102        if (!msg->findInt32("channel-count", &numChannels)
2103                || !msg->findInt32("sample-rate", &sampleRate)) {
2104            err = INVALID_OPERATION;
2105        } else {
2106            int32_t isADTS, aacProfile;
2107            int32_t sbrMode;
2108            int32_t maxOutputChannelCount;
2109            int32_t pcmLimiterEnable;
2110            drcParams_t drc;
2111            if (!msg->findInt32("is-adts", &isADTS)) {
2112                isADTS = 0;
2113            }
2114            if (!msg->findInt32("aac-profile", &aacProfile)) {
2115                aacProfile = OMX_AUDIO_AACObjectNull;
2116            }
2117            if (!msg->findInt32("aac-sbr-mode", &sbrMode)) {
2118                sbrMode = -1;
2119            }
2120
2121            if (!msg->findInt32("aac-max-output-channel_count", &maxOutputChannelCount)) {
2122                maxOutputChannelCount = -1;
2123            }
2124            if (!msg->findInt32("aac-pcm-limiter-enable", &pcmLimiterEnable)) {
2125                // value is unknown
2126                pcmLimiterEnable = -1;
2127            }
2128            if (!msg->findInt32("aac-encoded-target-level", &drc.encodedTargetLevel)) {
2129                // value is unknown
2130                drc.encodedTargetLevel = -1;
2131            }
2132            if (!msg->findInt32("aac-drc-cut-level", &drc.drcCut)) {
2133                // value is unknown
2134                drc.drcCut = -1;
2135            }
2136            if (!msg->findInt32("aac-drc-boost-level", &drc.drcBoost)) {
2137                // value is unknown
2138                drc.drcBoost = -1;
2139            }
2140            if (!msg->findInt32("aac-drc-heavy-compression", &drc.heavyCompression)) {
2141                // value is unknown
2142                drc.heavyCompression = -1;
2143            }
2144            if (!msg->findInt32("aac-target-ref-level", &drc.targetRefLevel)) {
2145                // value is unknown
2146                drc.targetRefLevel = -1;
2147            }
2148
2149            err = setupAACCodec(
2150                    encoder, numChannels, sampleRate, bitRate, aacProfile,
2151                    isADTS != 0, sbrMode, maxOutputChannelCount, drc,
2152                    pcmLimiterEnable);
2153        }
2154    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) {
2155        err = setupAMRCodec(encoder, false /* isWAMR */, bitRate);
2156    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
2157        err = setupAMRCodec(encoder, true /* isWAMR */, bitRate);
2158    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW)
2159            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) {
2160        // These are PCM-like formats with a fixed sample rate but
2161        // a variable number of channels.
2162
2163        int32_t numChannels;
2164        if (!msg->findInt32("channel-count", &numChannels)) {
2165            err = INVALID_OPERATION;
2166        } else {
2167            int32_t sampleRate;
2168            if (!msg->findInt32("sample-rate", &sampleRate)) {
2169                sampleRate = 8000;
2170            }
2171            err = setupG711Codec(encoder, sampleRate, numChannels);
2172        }
2173    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)) {
2174        int32_t numChannels = 0, sampleRate = 0, compressionLevel = -1;
2175        if (encoder &&
2176                (!msg->findInt32("channel-count", &numChannels)
2177                        || !msg->findInt32("sample-rate", &sampleRate))) {
2178            ALOGE("missing channel count or sample rate for FLAC encoder");
2179            err = INVALID_OPERATION;
2180        } else {
2181            if (encoder) {
2182                if (!msg->findInt32(
2183                            "complexity", &compressionLevel) &&
2184                    !msg->findInt32(
2185                            "flac-compression-level", &compressionLevel)) {
2186                    compressionLevel = 5; // default FLAC compression level
2187                } else if (compressionLevel < 0) {
2188                    ALOGW("compression level %d outside [0..8] range, "
2189                          "using 0",
2190                          compressionLevel);
2191                    compressionLevel = 0;
2192                } else if (compressionLevel > 8) {
2193                    ALOGW("compression level %d outside [0..8] range, "
2194                          "using 8",
2195                          compressionLevel);
2196                    compressionLevel = 8;
2197                }
2198            }
2199            err = setupFlacCodec(
2200                    encoder, numChannels, sampleRate, compressionLevel);
2201        }
2202    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
2203        int32_t numChannels, sampleRate;
2204        if (encoder
2205                || !msg->findInt32("channel-count", &numChannels)
2206                || !msg->findInt32("sample-rate", &sampleRate)) {
2207            err = INVALID_OPERATION;
2208        } else {
2209            err = setupRawAudioFormat(kPortIndexInput, sampleRate, numChannels, pcmEncoding);
2210        }
2211    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AC3)) {
2212        int32_t numChannels;
2213        int32_t sampleRate;
2214        if (!msg->findInt32("channel-count", &numChannels)
2215                || !msg->findInt32("sample-rate", &sampleRate)) {
2216            err = INVALID_OPERATION;
2217        } else {
2218            err = setupAC3Codec(encoder, numChannels, sampleRate);
2219        }
2220    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_EAC3)) {
2221        int32_t numChannels;
2222        int32_t sampleRate;
2223        if (!msg->findInt32("channel-count", &numChannels)
2224                || !msg->findInt32("sample-rate", &sampleRate)) {
2225            err = INVALID_OPERATION;
2226        } else {
2227            err = setupEAC3Codec(encoder, numChannels, sampleRate);
2228        }
2229    }
2230
2231    if (err != OK) {
2232        return err;
2233    }
2234
2235    if (!msg->findInt32("encoder-delay", &mEncoderDelay)) {
2236        mEncoderDelay = 0;
2237    }
2238
2239    if (!msg->findInt32("encoder-padding", &mEncoderPadding)) {
2240        mEncoderPadding = 0;
2241    }
2242
2243    if (msg->findInt32("channel-mask", &mChannelMask)) {
2244        mChannelMaskPresent = true;
2245    } else {
2246        mChannelMaskPresent = false;
2247    }
2248
2249    int32_t maxInputSize;
2250    if (msg->findInt32("max-input-size", &maxInputSize)) {
2251        err = setMinBufferSize(kPortIndexInput, (size_t)maxInputSize);
2252        err = OK; // ignore error
2253    } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) {
2254        err = setMinBufferSize(kPortIndexInput, 8192);  // XXX
2255        err = OK; // ignore error
2256    }
2257
2258    int32_t priority;
2259    if (msg->findInt32("priority", &priority)) {
2260        err = setPriority(priority);
2261        err = OK; // ignore error
2262    }
2263
2264    int32_t rateInt = -1;
2265    float rateFloat = -1;
2266    if (!msg->findFloat("operating-rate", &rateFloat)) {
2267        msg->findInt32("operating-rate", &rateInt);
2268        rateFloat = (float)rateInt;  // 16MHz (FLINTMAX) is OK for upper bound.
2269    }
2270    if (rateFloat > 0) {
2271        err = setOperatingRate(rateFloat, video);
2272        err = OK; // ignore errors
2273    }
2274
2275    if (err == OK) {
2276        err = setVendorParameters(msg);
2277        if (err != OK) {
2278            return err;
2279        }
2280    }
2281
2282    // NOTE: both mBaseOutputFormat and mOutputFormat are outputFormat to signal first frame.
2283    mBaseOutputFormat = outputFormat;
2284    mLastOutputFormat.clear();
2285
2286    err = getPortFormat(kPortIndexInput, inputFormat);
2287    if (err == OK) {
2288        err = getPortFormat(kPortIndexOutput, outputFormat);
2289        if (err == OK) {
2290            mInputFormat = inputFormat;
2291            mOutputFormat = outputFormat;
2292        }
2293    }
2294
2295    // create data converters if needed
2296    if (!video && err == OK) {
2297        AudioEncoding codecPcmEncoding = kAudioEncodingPcm16bit;
2298        if (encoder) {
2299            (void)mInputFormat->findInt32("pcm-encoding", (int32_t*)&codecPcmEncoding);
2300            mConverter[kPortIndexInput] = AudioConverter::Create(pcmEncoding, codecPcmEncoding);
2301            if (mConverter[kPortIndexInput] != NULL) {
2302                mInputFormat->setInt32("pcm-encoding", pcmEncoding);
2303            }
2304        } else {
2305            (void)mOutputFormat->findInt32("pcm-encoding", (int32_t*)&codecPcmEncoding);
2306            mConverter[kPortIndexOutput] = AudioConverter::Create(codecPcmEncoding, pcmEncoding);
2307            if (mConverter[kPortIndexOutput] != NULL) {
2308                mOutputFormat->setInt32("pcm-encoding", pcmEncoding);
2309            }
2310        }
2311    }
2312
2313    return err;
2314}
2315
2316status_t ACodec::setLatency(uint32_t latency) {
2317    OMX_PARAM_U32TYPE config;
2318    InitOMXParams(&config);
2319    config.nPortIndex = kPortIndexInput;
2320    config.nU32 = (OMX_U32)latency;
2321    status_t err = mOMXNode->setConfig(
2322            (OMX_INDEXTYPE)OMX_IndexConfigLatency,
2323            &config, sizeof(config));
2324    return err;
2325}
2326
2327status_t ACodec::getLatency(uint32_t *latency) {
2328    OMX_PARAM_U32TYPE config;
2329    InitOMXParams(&config);
2330    config.nPortIndex = kPortIndexInput;
2331    status_t err = mOMXNode->getConfig(
2332            (OMX_INDEXTYPE)OMX_IndexConfigLatency,
2333            &config, sizeof(config));
2334    if (err == OK) {
2335        *latency = config.nU32;
2336    }
2337    return err;
2338}
2339
2340status_t ACodec::setPriority(int32_t priority) {
2341    if (priority < 0) {
2342        return BAD_VALUE;
2343    }
2344    OMX_PARAM_U32TYPE config;
2345    InitOMXParams(&config);
2346    config.nU32 = (OMX_U32)priority;
2347    status_t temp = mOMXNode->setConfig(
2348            (OMX_INDEXTYPE)OMX_IndexConfigPriority,
2349            &config, sizeof(config));
2350    if (temp != OK) {
2351        ALOGI("codec does not support config priority (err %d)", temp);
2352    }
2353    return OK;
2354}
2355
2356status_t ACodec::setOperatingRate(float rateFloat, bool isVideo) {
2357    if (rateFloat < 0) {
2358        return BAD_VALUE;
2359    }
2360    OMX_U32 rate;
2361    if (isVideo) {
2362        if (rateFloat > 65535) {
2363            return BAD_VALUE;
2364        }
2365        rate = (OMX_U32)(rateFloat * 65536.0f + 0.5f);
2366    } else {
2367        if (rateFloat > UINT_MAX) {
2368            return BAD_VALUE;
2369        }
2370        rate = (OMX_U32)(rateFloat);
2371    }
2372    OMX_PARAM_U32TYPE config;
2373    InitOMXParams(&config);
2374    config.nU32 = rate;
2375    status_t err = mOMXNode->setConfig(
2376            (OMX_INDEXTYPE)OMX_IndexConfigOperatingRate,
2377            &config, sizeof(config));
2378    if (err != OK) {
2379        ALOGI("codec does not support config operating rate (err %d)", err);
2380    }
2381    return OK;
2382}
2383
2384status_t ACodec::getIntraRefreshPeriod(uint32_t *intraRefreshPeriod) {
2385    OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE params;
2386    InitOMXParams(&params);
2387    params.nPortIndex = kPortIndexOutput;
2388    status_t err = mOMXNode->getConfig(
2389            (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh, &params, sizeof(params));
2390    if (err == OK) {
2391        *intraRefreshPeriod = params.nRefreshPeriod;
2392        return OK;
2393    }
2394
2395    // Fallback to query through standard OMX index.
2396    OMX_VIDEO_PARAM_INTRAREFRESHTYPE refreshParams;
2397    InitOMXParams(&refreshParams);
2398    refreshParams.nPortIndex = kPortIndexOutput;
2399    refreshParams.eRefreshMode = OMX_VIDEO_IntraRefreshCyclic;
2400    err = mOMXNode->getParameter(
2401            OMX_IndexParamVideoIntraRefresh, &refreshParams, sizeof(refreshParams));
2402    if (err != OK || refreshParams.nCirMBs == 0) {
2403        *intraRefreshPeriod = 0;
2404        return OK;
2405    }
2406
2407    // Calculate period based on width and height
2408    uint32_t width, height;
2409    OMX_PARAM_PORTDEFINITIONTYPE def;
2410    InitOMXParams(&def);
2411    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
2412    def.nPortIndex = kPortIndexOutput;
2413    err = mOMXNode->getParameter(
2414            OMX_IndexParamPortDefinition, &def, sizeof(def));
2415    if (err != OK) {
2416        *intraRefreshPeriod = 0;
2417        return err;
2418    }
2419    width = video_def->nFrameWidth;
2420    height = video_def->nFrameHeight;
2421    // Use H.264/AVC MacroBlock size 16x16
2422    *intraRefreshPeriod = divUp((divUp(width, 16u) * divUp(height, 16u)), refreshParams.nCirMBs);
2423
2424    return OK;
2425}
2426
2427status_t ACodec::setIntraRefreshPeriod(uint32_t intraRefreshPeriod, bool inConfigure) {
2428    OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE params;
2429    InitOMXParams(&params);
2430    params.nPortIndex = kPortIndexOutput;
2431    params.nRefreshPeriod = intraRefreshPeriod;
2432    status_t err = mOMXNode->setConfig(
2433            (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh, &params, sizeof(params));
2434    if (err == OK) {
2435        return OK;
2436    }
2437
2438    // Only in configure state, a component could invoke setParameter.
2439    if (!inConfigure) {
2440        return INVALID_OPERATION;
2441    } else {
2442        ALOGI("[%s] try falling back to Cyclic", mComponentName.c_str());
2443    }
2444
2445    OMX_VIDEO_PARAM_INTRAREFRESHTYPE refreshParams;
2446    InitOMXParams(&refreshParams);
2447    refreshParams.nPortIndex = kPortIndexOutput;
2448    refreshParams.eRefreshMode = OMX_VIDEO_IntraRefreshCyclic;
2449
2450    if (intraRefreshPeriod == 0) {
2451        // 0 means disable intra refresh.
2452        refreshParams.nCirMBs = 0;
2453    } else {
2454        // Calculate macroblocks that need to be intra coded base on width and height
2455        uint32_t width, height;
2456        OMX_PARAM_PORTDEFINITIONTYPE def;
2457        InitOMXParams(&def);
2458        OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
2459        def.nPortIndex = kPortIndexOutput;
2460        err = mOMXNode->getParameter(
2461                OMX_IndexParamPortDefinition, &def, sizeof(def));
2462        if (err != OK) {
2463            return err;
2464        }
2465        width = video_def->nFrameWidth;
2466        height = video_def->nFrameHeight;
2467        // Use H.264/AVC MacroBlock size 16x16
2468        refreshParams.nCirMBs = divUp((divUp(width, 16u) * divUp(height, 16u)), intraRefreshPeriod);
2469    }
2470
2471    err = mOMXNode->setParameter(
2472            OMX_IndexParamVideoIntraRefresh,
2473            &refreshParams, sizeof(refreshParams));
2474    if (err != OK) {
2475        return err;
2476    }
2477
2478    return OK;
2479}
2480
2481status_t ACodec::configureTemporalLayers(
2482        const sp<AMessage> &msg, bool inConfigure, sp<AMessage> &outputFormat) {
2483    if (!mIsVideo || !mIsEncoder) {
2484        return INVALID_OPERATION;
2485    }
2486
2487    AString tsSchema;
2488    if (!msg->findString("ts-schema", &tsSchema)) {
2489        return OK;
2490    }
2491
2492    unsigned int numLayers = 0;
2493    unsigned int numBLayers = 0;
2494    int tags;
2495    char dummy;
2496    OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE pattern =
2497        OMX_VIDEO_AndroidTemporalLayeringPatternNone;
2498    if (sscanf(tsSchema.c_str(), "webrtc.vp8.%u-layer%c", &numLayers, &dummy) == 1
2499            && numLayers > 0) {
2500        pattern = OMX_VIDEO_AndroidTemporalLayeringPatternWebRTC;
2501    } else if ((tags = sscanf(tsSchema.c_str(), "android.generic.%u%c%u%c",
2502                    &numLayers, &dummy, &numBLayers, &dummy))
2503            && (tags == 1 || (tags == 3 && dummy == '+'))
2504            && numLayers > 0 && numLayers < UINT32_MAX - numBLayers) {
2505        numLayers += numBLayers;
2506        pattern = OMX_VIDEO_AndroidTemporalLayeringPatternAndroid;
2507    } else {
2508        ALOGI("Ignoring unsupported ts-schema [%s]", tsSchema.c_str());
2509        return BAD_VALUE;
2510    }
2511
2512    OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE layerParams;
2513    InitOMXParams(&layerParams);
2514    layerParams.nPortIndex = kPortIndexOutput;
2515
2516    status_t err = mOMXNode->getParameter(
2517            (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering,
2518            &layerParams, sizeof(layerParams));
2519
2520    if (err != OK) {
2521        return err;
2522    } else if (!(layerParams.eSupportedPatterns & pattern)) {
2523        return BAD_VALUE;
2524    }
2525
2526    numLayers = min(numLayers, layerParams.nLayerCountMax);
2527    numBLayers = min(numBLayers, layerParams.nBLayerCountMax);
2528
2529    if (!inConfigure) {
2530        OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE layerConfig;
2531        InitOMXParams(&layerConfig);
2532        layerConfig.nPortIndex = kPortIndexOutput;
2533        layerConfig.ePattern = pattern;
2534        layerConfig.nPLayerCountActual = numLayers - numBLayers;
2535        layerConfig.nBLayerCountActual = numBLayers;
2536        layerConfig.bBitrateRatiosSpecified = OMX_FALSE;
2537
2538        err = mOMXNode->setConfig(
2539                (OMX_INDEXTYPE)OMX_IndexConfigAndroidVideoTemporalLayering,
2540                &layerConfig, sizeof(layerConfig));
2541    } else {
2542        layerParams.ePattern = pattern;
2543        layerParams.nPLayerCountActual = numLayers - numBLayers;
2544        layerParams.nBLayerCountActual = numBLayers;
2545        layerParams.bBitrateRatiosSpecified = OMX_FALSE;
2546
2547        err = mOMXNode->setParameter(
2548                (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering,
2549                &layerParams, sizeof(layerParams));
2550    }
2551
2552    AString configSchema;
2553    if (pattern == OMX_VIDEO_AndroidTemporalLayeringPatternAndroid) {
2554        configSchema = AStringPrintf("android.generic.%u+%u", numLayers - numBLayers, numBLayers);
2555    } else if (pattern == OMX_VIDEO_AndroidTemporalLayeringPatternWebRTC) {
2556        configSchema = AStringPrintf("webrtc.vp8.%u", numLayers);
2557    }
2558
2559    if (err != OK) {
2560        ALOGW("Failed to set temporal layers to %s (requested %s)",
2561                configSchema.c_str(), tsSchema.c_str());
2562        return err;
2563    }
2564
2565    err = mOMXNode->getParameter(
2566            (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering,
2567            &layerParams, sizeof(layerParams));
2568
2569    if (err == OK) {
2570        ALOGD("Temporal layers requested:%s configured:%s got:%s(%u: P=%u, B=%u)",
2571                tsSchema.c_str(), configSchema.c_str(),
2572                asString(layerParams.ePattern), layerParams.ePattern,
2573                layerParams.nPLayerCountActual, layerParams.nBLayerCountActual);
2574
2575        if (outputFormat.get() == mOutputFormat.get()) {
2576            mOutputFormat = mOutputFormat->dup(); // trigger an output format change event
2577        }
2578        // assume we got what we configured
2579        outputFormat->setString("ts-schema", configSchema);
2580    }
2581    return err;
2582}
2583
2584status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) {
2585    OMX_PARAM_PORTDEFINITIONTYPE def;
2586    InitOMXParams(&def);
2587    def.nPortIndex = portIndex;
2588
2589    status_t err = mOMXNode->getParameter(
2590            OMX_IndexParamPortDefinition, &def, sizeof(def));
2591
2592    if (err != OK) {
2593        return err;
2594    }
2595
2596    if (def.nBufferSize >= size) {
2597        return OK;
2598    }
2599
2600    def.nBufferSize = size;
2601
2602    err = mOMXNode->setParameter(
2603            OMX_IndexParamPortDefinition, &def, sizeof(def));
2604
2605    if (err != OK) {
2606        return err;
2607    }
2608
2609    err = mOMXNode->getParameter(
2610            OMX_IndexParamPortDefinition, &def, sizeof(def));
2611
2612    if (err != OK) {
2613        return err;
2614    }
2615
2616    if (def.nBufferSize < size) {
2617        ALOGE("failed to set min buffer size to %zu (is still %u)", size, def.nBufferSize);
2618        return FAILED_TRANSACTION;
2619    }
2620
2621    return OK;
2622}
2623
2624status_t ACodec::selectAudioPortFormat(
2625        OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat) {
2626    OMX_AUDIO_PARAM_PORTFORMATTYPE format;
2627    InitOMXParams(&format);
2628
2629    format.nPortIndex = portIndex;
2630    for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
2631        format.nIndex = index;
2632        status_t err = mOMXNode->getParameter(
2633                OMX_IndexParamAudioPortFormat, &format, sizeof(format));
2634
2635        if (err != OK) {
2636            return err;
2637        }
2638
2639        if (format.eEncoding == desiredFormat) {
2640            break;
2641        }
2642
2643        if (index == kMaxIndicesToCheck) {
2644            ALOGW("[%s] stopping checking formats after %u: %s(%x)",
2645                    mComponentName.c_str(), index,
2646                    asString(format.eEncoding), format.eEncoding);
2647            return ERROR_UNSUPPORTED;
2648        }
2649    }
2650
2651    return mOMXNode->setParameter(
2652            OMX_IndexParamAudioPortFormat, &format, sizeof(format));
2653}
2654
2655status_t ACodec::setupAACCodec(
2656        bool encoder, int32_t numChannels, int32_t sampleRate,
2657        int32_t bitRate, int32_t aacProfile, bool isADTS, int32_t sbrMode,
2658        int32_t maxOutputChannelCount, const drcParams_t& drc,
2659        int32_t pcmLimiterEnable) {
2660    if (encoder && isADTS) {
2661        return -EINVAL;
2662    }
2663
2664    status_t err = setupRawAudioFormat(
2665            encoder ? kPortIndexInput : kPortIndexOutput,
2666            sampleRate,
2667            numChannels);
2668
2669    if (err != OK) {
2670        return err;
2671    }
2672
2673    if (encoder) {
2674        err = selectAudioPortFormat(kPortIndexOutput, OMX_AUDIO_CodingAAC);
2675
2676        if (err != OK) {
2677            return err;
2678        }
2679
2680        OMX_PARAM_PORTDEFINITIONTYPE def;
2681        InitOMXParams(&def);
2682        def.nPortIndex = kPortIndexOutput;
2683
2684        err = mOMXNode->getParameter(
2685                OMX_IndexParamPortDefinition, &def, sizeof(def));
2686
2687        if (err != OK) {
2688            return err;
2689        }
2690
2691        def.format.audio.bFlagErrorConcealment = OMX_TRUE;
2692        def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
2693
2694        err = mOMXNode->setParameter(
2695                OMX_IndexParamPortDefinition, &def, sizeof(def));
2696
2697        if (err != OK) {
2698            return err;
2699        }
2700
2701        OMX_AUDIO_PARAM_AACPROFILETYPE profile;
2702        InitOMXParams(&profile);
2703        profile.nPortIndex = kPortIndexOutput;
2704
2705        err = mOMXNode->getParameter(
2706                OMX_IndexParamAudioAac, &profile, sizeof(profile));
2707
2708        if (err != OK) {
2709            return err;
2710        }
2711
2712        profile.nChannels = numChannels;
2713
2714        profile.eChannelMode =
2715            (numChannels == 1)
2716                ? OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo;
2717
2718        profile.nSampleRate = sampleRate;
2719        profile.nBitRate = bitRate;
2720        profile.nAudioBandWidth = 0;
2721        profile.nFrameLength = 0;
2722        profile.nAACtools = OMX_AUDIO_AACToolAll;
2723        profile.nAACERtools = OMX_AUDIO_AACERNone;
2724        profile.eAACProfile = (OMX_AUDIO_AACPROFILETYPE) aacProfile;
2725        profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
2726        switch (sbrMode) {
2727        case 0:
2728            // disable sbr
2729            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR;
2730            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR;
2731            break;
2732        case 1:
2733            // enable single-rate sbr
2734            profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR;
2735            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR;
2736            break;
2737        case 2:
2738            // enable dual-rate sbr
2739            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR;
2740            profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR;
2741            break;
2742        case -1:
2743            // enable both modes -> the codec will decide which mode should be used
2744            profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR;
2745            profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR;
2746            break;
2747        default:
2748            // unsupported sbr mode
2749            return BAD_VALUE;
2750        }
2751
2752
2753        err = mOMXNode->setParameter(
2754                OMX_IndexParamAudioAac, &profile, sizeof(profile));
2755
2756        if (err != OK) {
2757            return err;
2758        }
2759
2760        return err;
2761    }
2762
2763    OMX_AUDIO_PARAM_AACPROFILETYPE profile;
2764    InitOMXParams(&profile);
2765    profile.nPortIndex = kPortIndexInput;
2766
2767    err = mOMXNode->getParameter(
2768            OMX_IndexParamAudioAac, &profile, sizeof(profile));
2769
2770    if (err != OK) {
2771        return err;
2772    }
2773
2774    profile.nChannels = numChannels;
2775    profile.nSampleRate = sampleRate;
2776
2777    profile.eAACStreamFormat =
2778        isADTS
2779            ? OMX_AUDIO_AACStreamFormatMP4ADTS
2780            : OMX_AUDIO_AACStreamFormatMP4FF;
2781
2782    OMX_AUDIO_PARAM_ANDROID_AACPRESENTATIONTYPE presentation;
2783    InitOMXParams(&presentation);
2784    presentation.nMaxOutputChannels = maxOutputChannelCount;
2785    presentation.nDrcCut = drc.drcCut;
2786    presentation.nDrcBoost = drc.drcBoost;
2787    presentation.nHeavyCompression = drc.heavyCompression;
2788    presentation.nTargetReferenceLevel = drc.targetRefLevel;
2789    presentation.nEncodedTargetLevel = drc.encodedTargetLevel;
2790    presentation.nPCMLimiterEnable = pcmLimiterEnable;
2791
2792    status_t res = mOMXNode->setParameter(
2793            OMX_IndexParamAudioAac, &profile, sizeof(profile));
2794    if (res == OK) {
2795        // optional parameters, will not cause configuration failure
2796        mOMXNode->setParameter(
2797                (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAacPresentation,
2798                &presentation, sizeof(presentation));
2799    } else {
2800        ALOGW("did not set AudioAndroidAacPresentation due to error %d when setting AudioAac", res);
2801    }
2802    mSampleRate = sampleRate;
2803    return res;
2804}
2805
2806status_t ACodec::setupAC3Codec(
2807        bool encoder, int32_t numChannels, int32_t sampleRate) {
2808    status_t err = setupRawAudioFormat(
2809            encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels);
2810
2811    if (err != OK) {
2812        return err;
2813    }
2814
2815    if (encoder) {
2816        ALOGW("AC3 encoding is not supported.");
2817        return INVALID_OPERATION;
2818    }
2819
2820    OMX_AUDIO_PARAM_ANDROID_AC3TYPE def;
2821    InitOMXParams(&def);
2822    def.nPortIndex = kPortIndexInput;
2823
2824    err = mOMXNode->getParameter(
2825            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, &def, sizeof(def));
2826
2827    if (err != OK) {
2828        return err;
2829    }
2830
2831    def.nChannels = numChannels;
2832    def.nSampleRate = sampleRate;
2833
2834    return mOMXNode->setParameter(
2835            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, &def, sizeof(def));
2836}
2837
2838status_t ACodec::setupEAC3Codec(
2839        bool encoder, int32_t numChannels, int32_t sampleRate) {
2840    status_t err = setupRawAudioFormat(
2841            encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels);
2842
2843    if (err != OK) {
2844        return err;
2845    }
2846
2847    if (encoder) {
2848        ALOGW("EAC3 encoding is not supported.");
2849        return INVALID_OPERATION;
2850    }
2851
2852    OMX_AUDIO_PARAM_ANDROID_EAC3TYPE def;
2853    InitOMXParams(&def);
2854    def.nPortIndex = kPortIndexInput;
2855
2856    err = mOMXNode->getParameter(
2857            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3, &def, sizeof(def));
2858
2859    if (err != OK) {
2860        return err;
2861    }
2862
2863    def.nChannels = numChannels;
2864    def.nSampleRate = sampleRate;
2865
2866    return mOMXNode->setParameter(
2867            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3, &def, sizeof(def));
2868}
2869
2870static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate(
2871        bool isAMRWB, int32_t bps) {
2872    if (isAMRWB) {
2873        if (bps <= 6600) {
2874            return OMX_AUDIO_AMRBandModeWB0;
2875        } else if (bps <= 8850) {
2876            return OMX_AUDIO_AMRBandModeWB1;
2877        } else if (bps <= 12650) {
2878            return OMX_AUDIO_AMRBandModeWB2;
2879        } else if (bps <= 14250) {
2880            return OMX_AUDIO_AMRBandModeWB3;
2881        } else if (bps <= 15850) {
2882            return OMX_AUDIO_AMRBandModeWB4;
2883        } else if (bps <= 18250) {
2884            return OMX_AUDIO_AMRBandModeWB5;
2885        } else if (bps <= 19850) {
2886            return OMX_AUDIO_AMRBandModeWB6;
2887        } else if (bps <= 23050) {
2888            return OMX_AUDIO_AMRBandModeWB7;
2889        }
2890
2891        // 23850 bps
2892        return OMX_AUDIO_AMRBandModeWB8;
2893    } else {  // AMRNB
2894        if (bps <= 4750) {
2895            return OMX_AUDIO_AMRBandModeNB0;
2896        } else if (bps <= 5150) {
2897            return OMX_AUDIO_AMRBandModeNB1;
2898        } else if (bps <= 5900) {
2899            return OMX_AUDIO_AMRBandModeNB2;
2900        } else if (bps <= 6700) {
2901            return OMX_AUDIO_AMRBandModeNB3;
2902        } else if (bps <= 7400) {
2903            return OMX_AUDIO_AMRBandModeNB4;
2904        } else if (bps <= 7950) {
2905            return OMX_AUDIO_AMRBandModeNB5;
2906        } else if (bps <= 10200) {
2907            return OMX_AUDIO_AMRBandModeNB6;
2908        }
2909
2910        // 12200 bps
2911        return OMX_AUDIO_AMRBandModeNB7;
2912    }
2913}
2914
2915status_t ACodec::setupAMRCodec(bool encoder, bool isWAMR, int32_t bitrate) {
2916    OMX_AUDIO_PARAM_AMRTYPE def;
2917    InitOMXParams(&def);
2918    def.nPortIndex = encoder ? kPortIndexOutput : kPortIndexInput;
2919
2920    status_t err = mOMXNode->getParameter(
2921            OMX_IndexParamAudioAmr, &def, sizeof(def));
2922
2923    if (err != OK) {
2924        return err;
2925    }
2926
2927    def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
2928    def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitrate);
2929
2930    err = mOMXNode->setParameter(
2931            OMX_IndexParamAudioAmr, &def, sizeof(def));
2932
2933    if (err != OK) {
2934        return err;
2935    }
2936
2937    return setupRawAudioFormat(
2938            encoder ? kPortIndexInput : kPortIndexOutput,
2939            isWAMR ? 16000 : 8000 /* sampleRate */,
2940            1 /* numChannels */);
2941}
2942
2943status_t ACodec::setupG711Codec(bool encoder, int32_t sampleRate, int32_t numChannels) {
2944    if (encoder) {
2945        return INVALID_OPERATION;
2946    }
2947
2948    return setupRawAudioFormat(
2949            kPortIndexInput, sampleRate, numChannels);
2950}
2951
2952status_t ACodec::setupFlacCodec(
2953        bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel) {
2954
2955    if (encoder) {
2956        OMX_AUDIO_PARAM_FLACTYPE def;
2957        InitOMXParams(&def);
2958        def.nPortIndex = kPortIndexOutput;
2959
2960        // configure compression level
2961        status_t err = mOMXNode->getParameter(OMX_IndexParamAudioFlac, &def, sizeof(def));
2962        if (err != OK) {
2963            ALOGE("setupFlacCodec(): Error %d getting OMX_IndexParamAudioFlac parameter", err);
2964            return err;
2965        }
2966        def.nCompressionLevel = compressionLevel;
2967        err = mOMXNode->setParameter(OMX_IndexParamAudioFlac, &def, sizeof(def));
2968        if (err != OK) {
2969            ALOGE("setupFlacCodec(): Error %d setting OMX_IndexParamAudioFlac parameter", err);
2970            return err;
2971        }
2972    }
2973
2974    return setupRawAudioFormat(
2975            encoder ? kPortIndexInput : kPortIndexOutput,
2976            sampleRate,
2977            numChannels);
2978}
2979
2980status_t ACodec::setupRawAudioFormat(
2981        OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels, AudioEncoding encoding) {
2982    OMX_PARAM_PORTDEFINITIONTYPE def;
2983    InitOMXParams(&def);
2984    def.nPortIndex = portIndex;
2985
2986    status_t err = mOMXNode->getParameter(
2987            OMX_IndexParamPortDefinition, &def, sizeof(def));
2988
2989    if (err != OK) {
2990        return err;
2991    }
2992
2993    def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
2994
2995    err = mOMXNode->setParameter(
2996            OMX_IndexParamPortDefinition, &def, sizeof(def));
2997
2998    if (err != OK) {
2999        return err;
3000    }
3001
3002    OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
3003    InitOMXParams(&pcmParams);
3004    pcmParams.nPortIndex = portIndex;
3005
3006    err = mOMXNode->getParameter(
3007            OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
3008
3009    if (err != OK) {
3010        return err;
3011    }
3012
3013    pcmParams.nChannels = numChannels;
3014    switch (encoding) {
3015        case kAudioEncodingPcm8bit:
3016            pcmParams.eNumData = OMX_NumericalDataUnsigned;
3017            pcmParams.nBitPerSample = 8;
3018            break;
3019        case kAudioEncodingPcmFloat:
3020            pcmParams.eNumData = OMX_NumericalDataFloat;
3021            pcmParams.nBitPerSample = 32;
3022            break;
3023        case kAudioEncodingPcm16bit:
3024            pcmParams.eNumData = OMX_NumericalDataSigned;
3025            pcmParams.nBitPerSample = 16;
3026            break;
3027        default:
3028            return BAD_VALUE;
3029    }
3030    pcmParams.bInterleaved = OMX_TRUE;
3031    pcmParams.nSamplingRate = sampleRate;
3032    pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
3033
3034    if (getOMXChannelMapping(numChannels, pcmParams.eChannelMapping) != OK) {
3035        return OMX_ErrorNone;
3036    }
3037
3038    err = mOMXNode->setParameter(
3039            OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
3040    // if we could not set up raw format to non-16-bit, try with 16-bit
3041    // NOTE: we will also verify this via readback, in case codec ignores these fields
3042    if (err != OK && encoding != kAudioEncodingPcm16bit) {
3043        pcmParams.eNumData = OMX_NumericalDataSigned;
3044        pcmParams.nBitPerSample = 16;
3045        err = mOMXNode->setParameter(
3046                OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
3047    }
3048    return err;
3049}
3050
3051status_t ACodec::configureTunneledVideoPlayback(
3052        int32_t audioHwSync, const sp<ANativeWindow> &nativeWindow) {
3053    native_handle_t* sidebandHandle;
3054
3055    status_t err = mOMXNode->configureVideoTunnelMode(
3056            kPortIndexOutput, OMX_TRUE, audioHwSync, &sidebandHandle);
3057    if (err != OK) {
3058        ALOGE("configureVideoTunnelMode failed! (err %d).", err);
3059        return err;
3060    }
3061
3062    err = native_window_set_sideband_stream(nativeWindow.get(), sidebandHandle);
3063    if (err != OK) {
3064        ALOGE("native_window_set_sideband_stream(%p) failed! (err %d).",
3065                sidebandHandle, err);
3066        return err;
3067    }
3068
3069    return OK;
3070}
3071
3072status_t ACodec::setVideoPortFormatType(
3073        OMX_U32 portIndex,
3074        OMX_VIDEO_CODINGTYPE compressionFormat,
3075        OMX_COLOR_FORMATTYPE colorFormat,
3076        bool usingNativeBuffers) {
3077    OMX_VIDEO_PARAM_PORTFORMATTYPE format;
3078    InitOMXParams(&format);
3079    format.nPortIndex = portIndex;
3080    format.nIndex = 0;
3081    bool found = false;
3082
3083    for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
3084        format.nIndex = index;
3085        status_t err = mOMXNode->getParameter(
3086                OMX_IndexParamVideoPortFormat,
3087                &format, sizeof(format));
3088
3089        if (err != OK) {
3090            return err;
3091        }
3092
3093        // substitute back flexible color format to codec supported format
3094        OMX_U32 flexibleEquivalent;
3095        if (compressionFormat == OMX_VIDEO_CodingUnused
3096                && IsFlexibleColorFormat(
3097                        mOMXNode, format.eColorFormat, usingNativeBuffers, &flexibleEquivalent)
3098                && colorFormat == flexibleEquivalent) {
3099            ALOGI("[%s] using color format %#x in place of %#x",
3100                    mComponentName.c_str(), format.eColorFormat, colorFormat);
3101            colorFormat = format.eColorFormat;
3102        }
3103
3104        // The following assertion is violated by TI's video decoder.
3105        // CHECK_EQ(format.nIndex, index);
3106
3107        if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) {
3108            if (portIndex == kPortIndexInput
3109                    && colorFormat == format.eColorFormat) {
3110                // eCompressionFormat does not seem right.
3111                found = true;
3112                break;
3113            }
3114            if (portIndex == kPortIndexOutput
3115                    && compressionFormat == format.eCompressionFormat) {
3116                // eColorFormat does not seem right.
3117                found = true;
3118                break;
3119            }
3120        }
3121
3122        if (format.eCompressionFormat == compressionFormat
3123            && format.eColorFormat == colorFormat) {
3124            found = true;
3125            break;
3126        }
3127
3128        if (index == kMaxIndicesToCheck) {
3129            ALOGW("[%s] stopping checking formats after %u: %s(%x)/%s(%x)",
3130                    mComponentName.c_str(), index,
3131                    asString(format.eCompressionFormat), format.eCompressionFormat,
3132                    asString(format.eColorFormat), format.eColorFormat);
3133        }
3134    }
3135
3136    if (!found) {
3137        return UNKNOWN_ERROR;
3138    }
3139
3140    status_t err = mOMXNode->setParameter(
3141            OMX_IndexParamVideoPortFormat, &format, sizeof(format));
3142
3143    return err;
3144}
3145
3146// Set optimal output format. OMX component lists output formats in the order
3147// of preference, but this got more complicated since the introduction of flexible
3148// YUV formats. We support a legacy behavior for applications that do not use
3149// surface output, do not specify an output format, but expect a "usable" standard
3150// OMX format. SW readable and standard formats must be flex-YUV.
3151//
3152// Suggested preference order:
3153// - optimal format for texture rendering (mediaplayer behavior)
3154// - optimal SW readable & texture renderable format (flex-YUV support)
3155// - optimal SW readable non-renderable format (flex-YUV bytebuffer support)
3156// - legacy "usable" standard formats
3157//
3158// For legacy support, we prefer a standard format, but will settle for a SW readable
3159// flex-YUV format.
3160status_t ACodec::setSupportedOutputFormat(bool getLegacyFlexibleFormat) {
3161    OMX_VIDEO_PARAM_PORTFORMATTYPE format, legacyFormat;
3162    InitOMXParams(&format);
3163    format.nPortIndex = kPortIndexOutput;
3164
3165    InitOMXParams(&legacyFormat);
3166    // this field will change when we find a suitable legacy format
3167    legacyFormat.eColorFormat = OMX_COLOR_FormatUnused;
3168
3169    for (OMX_U32 index = 0; ; ++index) {
3170        format.nIndex = index;
3171        status_t err = mOMXNode->getParameter(
3172                OMX_IndexParamVideoPortFormat, &format, sizeof(format));
3173        if (err != OK) {
3174            // no more formats, pick legacy format if found
3175            if (legacyFormat.eColorFormat != OMX_COLOR_FormatUnused) {
3176                 memcpy(&format, &legacyFormat, sizeof(format));
3177                 break;
3178            }
3179            return err;
3180        }
3181        if (format.eCompressionFormat != OMX_VIDEO_CodingUnused) {
3182            return OMX_ErrorBadParameter;
3183        }
3184        if (!getLegacyFlexibleFormat) {
3185            break;
3186        }
3187        // standard formats that were exposed to users before
3188        if (format.eColorFormat == OMX_COLOR_FormatYUV420Planar
3189                || format.eColorFormat == OMX_COLOR_FormatYUV420PackedPlanar
3190                || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
3191                || format.eColorFormat == OMX_COLOR_FormatYUV420PackedSemiPlanar
3192                || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar) {
3193            break;
3194        }
3195        // find best legacy non-standard format
3196        OMX_U32 flexibleEquivalent;
3197        if (legacyFormat.eColorFormat == OMX_COLOR_FormatUnused
3198                && IsFlexibleColorFormat(
3199                        mOMXNode, format.eColorFormat, false /* usingNativeBuffers */,
3200                        &flexibleEquivalent)
3201                && flexibleEquivalent == OMX_COLOR_FormatYUV420Flexible) {
3202            memcpy(&legacyFormat, &format, sizeof(format));
3203        }
3204    }
3205    return mOMXNode->setParameter(
3206            OMX_IndexParamVideoPortFormat, &format, sizeof(format));
3207}
3208
3209static const struct VideoCodingMapEntry {
3210    const char *mMime;
3211    OMX_VIDEO_CODINGTYPE mVideoCodingType;
3212} kVideoCodingMapEntry[] = {
3213    { MEDIA_MIMETYPE_VIDEO_AVC, OMX_VIDEO_CodingAVC },
3214    { MEDIA_MIMETYPE_VIDEO_HEVC, OMX_VIDEO_CodingHEVC },
3215    { MEDIA_MIMETYPE_VIDEO_MPEG4, OMX_VIDEO_CodingMPEG4 },
3216    { MEDIA_MIMETYPE_VIDEO_H263, OMX_VIDEO_CodingH263 },
3217    { MEDIA_MIMETYPE_VIDEO_MPEG2, OMX_VIDEO_CodingMPEG2 },
3218    { MEDIA_MIMETYPE_VIDEO_VP8, OMX_VIDEO_CodingVP8 },
3219    { MEDIA_MIMETYPE_VIDEO_VP9, OMX_VIDEO_CodingVP9 },
3220    { MEDIA_MIMETYPE_VIDEO_DOLBY_VISION, OMX_VIDEO_CodingDolbyVision },
3221};
3222
3223static status_t GetVideoCodingTypeFromMime(
3224        const char *mime, OMX_VIDEO_CODINGTYPE *codingType) {
3225    for (size_t i = 0;
3226         i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]);
3227         ++i) {
3228        if (!strcasecmp(mime, kVideoCodingMapEntry[i].mMime)) {
3229            *codingType = kVideoCodingMapEntry[i].mVideoCodingType;
3230            return OK;
3231        }
3232    }
3233
3234    *codingType = OMX_VIDEO_CodingUnused;
3235
3236    return ERROR_UNSUPPORTED;
3237}
3238
3239static status_t GetMimeTypeForVideoCoding(
3240        OMX_VIDEO_CODINGTYPE codingType, AString *mime) {
3241    for (size_t i = 0;
3242         i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]);
3243         ++i) {
3244        if (codingType == kVideoCodingMapEntry[i].mVideoCodingType) {
3245            *mime = kVideoCodingMapEntry[i].mMime;
3246            return OK;
3247        }
3248    }
3249
3250    mime->clear();
3251
3252    return ERROR_UNSUPPORTED;
3253}
3254
3255status_t ACodec::setPortBufferNum(OMX_U32 portIndex, int bufferNum) {
3256    OMX_PARAM_PORTDEFINITIONTYPE def;
3257    InitOMXParams(&def);
3258    def.nPortIndex = portIndex;
3259    status_t err;
3260    ALOGD("Setting [%s] %s port buffer number: %d", mComponentName.c_str(),
3261            portIndex == kPortIndexInput ? "input" : "output", bufferNum);
3262    err = mOMXNode->getParameter(
3263        OMX_IndexParamPortDefinition, &def, sizeof(def));
3264    if (err != OK) {
3265        return err;
3266    }
3267    def.nBufferCountActual = bufferNum;
3268    err = mOMXNode->setParameter(
3269        OMX_IndexParamPortDefinition, &def, sizeof(def));
3270    if (err != OK) {
3271        // Component could reject this request.
3272        ALOGW("Fail to set [%s] %s port buffer number: %d", mComponentName.c_str(),
3273            portIndex == kPortIndexInput ? "input" : "output", bufferNum);
3274    }
3275    return OK;
3276}
3277
3278status_t ACodec::setupVideoDecoder(
3279        const char *mime, const sp<AMessage> &msg, bool haveNativeWindow,
3280        bool usingSwRenderer, sp<AMessage> &outputFormat) {
3281    int32_t width, height;
3282    if (!msg->findInt32("width", &width)
3283            || !msg->findInt32("height", &height)) {
3284        return INVALID_OPERATION;
3285    }
3286
3287    OMX_VIDEO_CODINGTYPE compressionFormat;
3288    status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
3289
3290    if (err != OK) {
3291        return err;
3292    }
3293
3294    if (compressionFormat == OMX_VIDEO_CodingVP9) {
3295        OMX_VIDEO_PARAM_PROFILELEVELTYPE params;
3296        InitOMXParams(&params);
3297        params.nPortIndex = kPortIndexInput;
3298        // Check if VP9 decoder advertises supported profiles.
3299        params.nProfileIndex = 0;
3300        status_t err = mOMXNode->getParameter(
3301                OMX_IndexParamVideoProfileLevelQuerySupported,
3302                &params, sizeof(params));
3303        mIsLegacyVP9Decoder = err != OK;
3304    }
3305
3306    err = setVideoPortFormatType(
3307            kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
3308
3309    if (err != OK) {
3310        return err;
3311    }
3312
3313    int32_t tmp;
3314    if (msg->findInt32("color-format", &tmp)) {
3315        OMX_COLOR_FORMATTYPE colorFormat =
3316            static_cast<OMX_COLOR_FORMATTYPE>(tmp);
3317        err = setVideoPortFormatType(
3318                kPortIndexOutput, OMX_VIDEO_CodingUnused, colorFormat, haveNativeWindow);
3319        if (err != OK) {
3320            ALOGW("[%s] does not support color format %d",
3321                  mComponentName.c_str(), colorFormat);
3322            err = setSupportedOutputFormat(!haveNativeWindow /* getLegacyFlexibleFormat */);
3323        }
3324    } else {
3325        err = setSupportedOutputFormat(!haveNativeWindow /* getLegacyFlexibleFormat */);
3326    }
3327
3328    if (err != OK) {
3329        return err;
3330    }
3331
3332    // Set the component input buffer number to be |tmp|. If succeed,
3333    // component will set input port buffer number to be |tmp|. If fail,
3334    // component will keep the same buffer number as before.
3335    if (msg->findInt32("android._num-input-buffers", &tmp)) {
3336        err = setPortBufferNum(kPortIndexInput, tmp);
3337        if (err != OK)
3338            return err;
3339    }
3340
3341    // Set the component output buffer number to be |tmp|. If succeed,
3342    // component will set output port buffer number to be |tmp|. If fail,
3343    // component will keep the same buffer number as before.
3344    if (msg->findInt32("android._num-output-buffers", &tmp)) {
3345        err = setPortBufferNum(kPortIndexOutput, tmp);
3346        if (err != OK)
3347            return err;
3348    }
3349
3350    int32_t frameRateInt;
3351    float frameRateFloat;
3352    if (!msg->findFloat("frame-rate", &frameRateFloat)) {
3353        if (!msg->findInt32("frame-rate", &frameRateInt)) {
3354            frameRateInt = -1;
3355        }
3356        frameRateFloat = (float)frameRateInt;
3357    }
3358
3359    err = setVideoFormatOnPort(
3360            kPortIndexInput, width, height, compressionFormat, frameRateFloat);
3361
3362    if (err != OK) {
3363        return err;
3364    }
3365
3366    err = setVideoFormatOnPort(
3367            kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused);
3368
3369    if (err != OK) {
3370        return err;
3371    }
3372
3373    err = setColorAspectsForVideoDecoder(
3374            width, height, haveNativeWindow | usingSwRenderer, msg, outputFormat);
3375    if (err == ERROR_UNSUPPORTED) { // support is optional
3376        err = OK;
3377    }
3378
3379    if (err != OK) {
3380        return err;
3381    }
3382
3383    err = setHDRStaticInfoForVideoCodec(kPortIndexOutput, msg, outputFormat);
3384    if (err == ERROR_UNSUPPORTED) { // support is optional
3385        err = OK;
3386    }
3387    return err;
3388}
3389
3390status_t ACodec::initDescribeColorAspectsIndex() {
3391    status_t err = mOMXNode->getExtensionIndex(
3392            "OMX.google.android.index.describeColorAspects", &mDescribeColorAspectsIndex);
3393    if (err != OK) {
3394        mDescribeColorAspectsIndex = (OMX_INDEXTYPE)0;
3395    }
3396    return err;
3397}
3398
3399status_t ACodec::setCodecColorAspects(DescribeColorAspectsParams &params, bool verify) {
3400    status_t err = ERROR_UNSUPPORTED;
3401    if (mDescribeColorAspectsIndex) {
3402        err = mOMXNode->setConfig(mDescribeColorAspectsIndex, &params, sizeof(params));
3403    }
3404    ALOGV("[%s] setting color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) err=%d(%s)",
3405            mComponentName.c_str(),
3406            params.sAspects.mRange, asString(params.sAspects.mRange),
3407            params.sAspects.mPrimaries, asString(params.sAspects.mPrimaries),
3408            params.sAspects.mMatrixCoeffs, asString(params.sAspects.mMatrixCoeffs),
3409            params.sAspects.mTransfer, asString(params.sAspects.mTransfer),
3410            err, asString(err));
3411
3412    if (verify && err == OK) {
3413        err = getCodecColorAspects(params);
3414    }
3415
3416    ALOGW_IF(err == ERROR_UNSUPPORTED && mDescribeColorAspectsIndex,
3417            "[%s] setting color aspects failed even though codec advertises support",
3418            mComponentName.c_str());
3419    return err;
3420}
3421
3422status_t ACodec::setColorAspectsForVideoDecoder(
3423        int32_t width, int32_t height, bool usingNativeWindow,
3424        const sp<AMessage> &configFormat, sp<AMessage> &outputFormat) {
3425    DescribeColorAspectsParams params;
3426    InitOMXParams(&params);
3427    params.nPortIndex = kPortIndexOutput;
3428
3429    getColorAspectsFromFormat(configFormat, params.sAspects);
3430    if (usingNativeWindow) {
3431        setDefaultCodecColorAspectsIfNeeded(params.sAspects, width, height);
3432        // The default aspects will be set back to the output format during the
3433        // getFormat phase of configure(). Set non-Unspecified values back into the
3434        // format, in case component does not support this enumeration.
3435        setColorAspectsIntoFormat(params.sAspects, outputFormat);
3436    }
3437
3438    (void)initDescribeColorAspectsIndex();
3439
3440    // communicate color aspects to codec
3441    return setCodecColorAspects(params);
3442}
3443
3444status_t ACodec::getCodecColorAspects(DescribeColorAspectsParams &params) {
3445    status_t err = ERROR_UNSUPPORTED;
3446    if (mDescribeColorAspectsIndex) {
3447        err = mOMXNode->getConfig(mDescribeColorAspectsIndex, &params, sizeof(params));
3448    }
3449    ALOGV("[%s] got color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) err=%d(%s)",
3450            mComponentName.c_str(),
3451            params.sAspects.mRange, asString(params.sAspects.mRange),
3452            params.sAspects.mPrimaries, asString(params.sAspects.mPrimaries),
3453            params.sAspects.mMatrixCoeffs, asString(params.sAspects.mMatrixCoeffs),
3454            params.sAspects.mTransfer, asString(params.sAspects.mTransfer),
3455            err, asString(err));
3456    if (params.bRequestingDataSpace) {
3457        ALOGV("for dataspace %#x", params.nDataSpace);
3458    }
3459    if (err == ERROR_UNSUPPORTED && mDescribeColorAspectsIndex
3460            && !params.bRequestingDataSpace && !params.bDataSpaceChanged) {
3461        ALOGW("[%s] getting color aspects failed even though codec advertises support",
3462                mComponentName.c_str());
3463    }
3464    return err;
3465}
3466
3467status_t ACodec::getInputColorAspectsForVideoEncoder(sp<AMessage> &format) {
3468    DescribeColorAspectsParams params;
3469    InitOMXParams(&params);
3470    params.nPortIndex = kPortIndexInput;
3471    status_t err = getCodecColorAspects(params);
3472    if (err == OK) {
3473        // we only set encoder input aspects if codec supports them
3474        setColorAspectsIntoFormat(params.sAspects, format, true /* force */);
3475    }
3476    return err;
3477}
3478
3479status_t ACodec::getDataSpace(
3480        DescribeColorAspectsParams &params, android_dataspace *dataSpace /* nonnull */,
3481        bool tryCodec) {
3482    status_t err = OK;
3483    if (tryCodec) {
3484        // request dataspace guidance from codec.
3485        params.bRequestingDataSpace = OMX_TRUE;
3486        err = getCodecColorAspects(params);
3487        params.bRequestingDataSpace = OMX_FALSE;
3488        if (err == OK && params.nDataSpace != HAL_DATASPACE_UNKNOWN) {
3489            *dataSpace = (android_dataspace)params.nDataSpace;
3490            return err;
3491        } else if (err == ERROR_UNSUPPORTED) {
3492            // ignore not-implemented error for dataspace requests
3493            err = OK;
3494        }
3495    }
3496
3497    // this returns legacy versions if available
3498    *dataSpace = getDataSpaceForColorAspects(params.sAspects, true /* mayexpand */);
3499    ALOGV("[%s] using color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) "
3500          "and dataspace %#x",
3501            mComponentName.c_str(),
3502            params.sAspects.mRange, asString(params.sAspects.mRange),
3503            params.sAspects.mPrimaries, asString(params.sAspects.mPrimaries),
3504            params.sAspects.mMatrixCoeffs, asString(params.sAspects.mMatrixCoeffs),
3505            params.sAspects.mTransfer, asString(params.sAspects.mTransfer),
3506            *dataSpace);
3507    return err;
3508}
3509
3510
3511status_t ACodec::getColorAspectsAndDataSpaceForVideoDecoder(
3512        int32_t width, int32_t height, const sp<AMessage> &configFormat, sp<AMessage> &outputFormat,
3513        android_dataspace *dataSpace) {
3514    DescribeColorAspectsParams params;
3515    InitOMXParams(&params);
3516    params.nPortIndex = kPortIndexOutput;
3517
3518    // reset default format and get resulting format
3519    getColorAspectsFromFormat(configFormat, params.sAspects);
3520    if (dataSpace != NULL) {
3521        setDefaultCodecColorAspectsIfNeeded(params.sAspects, width, height);
3522    }
3523    status_t err = setCodecColorAspects(params, true /* readBack */);
3524
3525    // we always set specified aspects for decoders
3526    setColorAspectsIntoFormat(params.sAspects, outputFormat);
3527
3528    if (dataSpace != NULL) {
3529        status_t res = getDataSpace(params, dataSpace, err == OK /* tryCodec */);
3530        if (err == OK) {
3531            err = res;
3532        }
3533    }
3534
3535    return err;
3536}
3537
3538// initial video encoder setup for bytebuffer mode
3539status_t ACodec::setColorAspectsForVideoEncoder(
3540        const sp<AMessage> &configFormat, sp<AMessage> &outputFormat, sp<AMessage> &inputFormat) {
3541    // copy config to output format as this is not exposed via getFormat
3542    copyColorConfig(configFormat, outputFormat);
3543
3544    DescribeColorAspectsParams params;
3545    InitOMXParams(&params);
3546    params.nPortIndex = kPortIndexInput;
3547    getColorAspectsFromFormat(configFormat, params.sAspects);
3548
3549    (void)initDescribeColorAspectsIndex();
3550
3551    int32_t usingRecorder;
3552    if (configFormat->findInt32("android._using-recorder", &usingRecorder) && usingRecorder) {
3553        android_dataspace dataSpace = HAL_DATASPACE_BT709;
3554        int32_t width, height;
3555        if (configFormat->findInt32("width", &width)
3556                && configFormat->findInt32("height", &height)) {
3557            setDefaultCodecColorAspectsIfNeeded(params.sAspects, width, height);
3558            status_t err = getDataSpace(
3559                    params, &dataSpace, mDescribeColorAspectsIndex /* tryCodec */);
3560            if (err != OK) {
3561                return err;
3562            }
3563            setColorAspectsIntoFormat(params.sAspects, outputFormat);
3564        }
3565        inputFormat->setInt32("android._dataspace", (int32_t)dataSpace);
3566    }
3567
3568    // communicate color aspects to codec, but do not allow change of the platform aspects
3569    ColorAspects origAspects = params.sAspects;
3570    for (int triesLeft = 2; --triesLeft >= 0; ) {
3571        status_t err = setCodecColorAspects(params, true /* readBack */);
3572        if (err != OK
3573                || !ColorUtils::checkIfAspectsChangedAndUnspecifyThem(
3574                        params.sAspects, origAspects, true /* usePlatformAspects */)) {
3575            return err;
3576        }
3577        ALOGW_IF(triesLeft == 0, "[%s] Codec repeatedly changed requested ColorAspects.",
3578                mComponentName.c_str());
3579    }
3580    return OK;
3581}
3582
3583status_t ACodec::setHDRStaticInfoForVideoCodec(
3584        OMX_U32 portIndex, const sp<AMessage> &configFormat, sp<AMessage> &outputFormat) {
3585    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
3586
3587    DescribeHDRStaticInfoParams params;
3588    InitOMXParams(&params);
3589    params.nPortIndex = portIndex;
3590
3591    HDRStaticInfo *info = &params.sInfo;
3592    if (getHDRStaticInfoFromFormat(configFormat, info)) {
3593        setHDRStaticInfoIntoFormat(params.sInfo, outputFormat);
3594    }
3595
3596    (void)initDescribeHDRStaticInfoIndex();
3597
3598    // communicate HDR static Info to codec
3599    return setHDRStaticInfo(params);
3600}
3601
3602// subsequent initial video encoder setup for surface mode
3603status_t ACodec::setInitialColorAspectsForVideoEncoderSurfaceAndGetDataSpace(
3604        android_dataspace *dataSpace /* nonnull */) {
3605    DescribeColorAspectsParams params;
3606    InitOMXParams(&params);
3607    params.nPortIndex = kPortIndexInput;
3608    ColorAspects &aspects = params.sAspects;
3609
3610    // reset default format and store resulting format into both input and output formats
3611    getColorAspectsFromFormat(mConfigFormat, aspects);
3612    int32_t width, height;
3613    if (mInputFormat->findInt32("width", &width) && mInputFormat->findInt32("height", &height)) {
3614        setDefaultCodecColorAspectsIfNeeded(aspects, width, height);
3615    }
3616    setColorAspectsIntoFormat(aspects, mInputFormat);
3617    setColorAspectsIntoFormat(aspects, mOutputFormat);
3618
3619    // communicate color aspects to codec, but do not allow any change
3620    ColorAspects origAspects = aspects;
3621    status_t err = OK;
3622    for (int triesLeft = 2; mDescribeColorAspectsIndex && --triesLeft >= 0; ) {
3623        status_t err = setCodecColorAspects(params, true /* readBack */);
3624        if (err != OK || !ColorUtils::checkIfAspectsChangedAndUnspecifyThem(aspects, origAspects)) {
3625            break;
3626        }
3627        ALOGW_IF(triesLeft == 0, "[%s] Codec repeatedly changed requested ColorAspects.",
3628                mComponentName.c_str());
3629    }
3630
3631    *dataSpace = HAL_DATASPACE_BT709;
3632    aspects = origAspects; // restore desired color aspects
3633    status_t res = getDataSpace(
3634            params, dataSpace, err == OK && mDescribeColorAspectsIndex /* tryCodec */);
3635    if (err == OK) {
3636        err = res;
3637    }
3638    mInputFormat->setInt32("android._dataspace", (int32_t)*dataSpace);
3639    mInputFormat->setBuffer(
3640            "android._color-aspects", ABuffer::CreateAsCopy(&aspects, sizeof(aspects)));
3641
3642    // update input format with codec supported color aspects (basically set unsupported
3643    // aspects to Unspecified)
3644    if (err == OK) {
3645        (void)getInputColorAspectsForVideoEncoder(mInputFormat);
3646    }
3647
3648    ALOGV("set default color aspects, updated input format to %s, output format to %s",
3649            mInputFormat->debugString(4).c_str(), mOutputFormat->debugString(4).c_str());
3650
3651    return err;
3652}
3653
3654status_t ACodec::getHDRStaticInfoForVideoCodec(OMX_U32 portIndex, sp<AMessage> &format) {
3655    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
3656    DescribeHDRStaticInfoParams params;
3657    InitOMXParams(&params);
3658    params.nPortIndex = portIndex;
3659
3660    status_t err = getHDRStaticInfo(params);
3661    if (err == OK) {
3662        // we only set decodec output HDRStaticInfo if codec supports them
3663        setHDRStaticInfoIntoFormat(params.sInfo, format);
3664    }
3665    return err;
3666}
3667
3668status_t ACodec::initDescribeHDRStaticInfoIndex() {
3669    status_t err = mOMXNode->getExtensionIndex(
3670            "OMX.google.android.index.describeHDRStaticInfo", &mDescribeHDRStaticInfoIndex);
3671    if (err != OK) {
3672        mDescribeHDRStaticInfoIndex = (OMX_INDEXTYPE)0;
3673    }
3674    return err;
3675}
3676
3677status_t ACodec::setHDRStaticInfo(const DescribeHDRStaticInfoParams &params) {
3678    status_t err = ERROR_UNSUPPORTED;
3679    if (mDescribeHDRStaticInfoIndex) {
3680        err = mOMXNode->setConfig(mDescribeHDRStaticInfoIndex, &params, sizeof(params));
3681    }
3682
3683    const HDRStaticInfo *info = &params.sInfo;
3684    ALOGV("[%s] setting  HDRStaticInfo (R: %u %u, G: %u %u, B: %u, %u, W: %u, %u, "
3685            "MaxDispL: %u, MinDispL: %u, MaxContentL: %u, MaxFrameAvgL: %u)",
3686            mComponentName.c_str(),
3687            info->sType1.mR.x, info->sType1.mR.y, info->sType1.mG.x, info->sType1.mG.y,
3688            info->sType1.mB.x, info->sType1.mB.y, info->sType1.mW.x, info->sType1.mW.y,
3689            info->sType1.mMaxDisplayLuminance, info->sType1.mMinDisplayLuminance,
3690            info->sType1.mMaxContentLightLevel, info->sType1.mMaxFrameAverageLightLevel);
3691
3692    ALOGW_IF(err == ERROR_UNSUPPORTED && mDescribeHDRStaticInfoIndex,
3693            "[%s] setting HDRStaticInfo failed even though codec advertises support",
3694            mComponentName.c_str());
3695    return err;
3696}
3697
3698status_t ACodec::getHDRStaticInfo(DescribeHDRStaticInfoParams &params) {
3699    status_t err = ERROR_UNSUPPORTED;
3700    if (mDescribeHDRStaticInfoIndex) {
3701        err = mOMXNode->getConfig(mDescribeHDRStaticInfoIndex, &params, sizeof(params));
3702    }
3703
3704    ALOGW_IF(err == ERROR_UNSUPPORTED && mDescribeHDRStaticInfoIndex,
3705            "[%s] getting HDRStaticInfo failed even though codec advertises support",
3706            mComponentName.c_str());
3707    return err;
3708}
3709
3710status_t ACodec::setupVideoEncoder(
3711        const char *mime, const sp<AMessage> &msg,
3712        sp<AMessage> &outputFormat, sp<AMessage> &inputFormat) {
3713    int32_t tmp;
3714    if (!msg->findInt32("color-format", &tmp)) {
3715        return INVALID_OPERATION;
3716    }
3717
3718    OMX_COLOR_FORMATTYPE colorFormat =
3719        static_cast<OMX_COLOR_FORMATTYPE>(tmp);
3720
3721    status_t err = setVideoPortFormatType(
3722            kPortIndexInput, OMX_VIDEO_CodingUnused, colorFormat);
3723
3724    if (err != OK) {
3725        ALOGE("[%s] does not support color format %d",
3726              mComponentName.c_str(), colorFormat);
3727
3728        return err;
3729    }
3730
3731    /* Input port configuration */
3732
3733    OMX_PARAM_PORTDEFINITIONTYPE def;
3734    InitOMXParams(&def);
3735
3736    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
3737
3738    def.nPortIndex = kPortIndexInput;
3739
3740    err = mOMXNode->getParameter(
3741            OMX_IndexParamPortDefinition, &def, sizeof(def));
3742
3743    if (err != OK) {
3744        return err;
3745    }
3746
3747    int32_t width, height, bitrate;
3748    if (!msg->findInt32("width", &width)
3749            || !msg->findInt32("height", &height)
3750            || !msg->findInt32("bitrate", &bitrate)) {
3751        return INVALID_OPERATION;
3752    }
3753
3754    video_def->nFrameWidth = width;
3755    video_def->nFrameHeight = height;
3756
3757    int32_t stride;
3758    if (!msg->findInt32("stride", &stride)) {
3759        stride = width;
3760    }
3761
3762    video_def->nStride = stride;
3763
3764    int32_t sliceHeight;
3765    if (!msg->findInt32("slice-height", &sliceHeight)) {
3766        sliceHeight = height;
3767    }
3768
3769    video_def->nSliceHeight = sliceHeight;
3770
3771    def.nBufferSize = (video_def->nStride * video_def->nSliceHeight * 3) / 2;
3772
3773    float framerate;
3774    if (!msg->findFloat("frame-rate", &framerate)) {
3775        int32_t tmp;
3776        if (!msg->findInt32("frame-rate", &tmp)) {
3777            return INVALID_OPERATION;
3778        }
3779        mFps = (double)tmp;
3780    } else {
3781        mFps = (double)framerate;
3782    }
3783
3784    video_def->xFramerate = (OMX_U32)(mFps * 65536);
3785    video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
3786    // this is redundant as it was already set up in setVideoPortFormatType
3787    // FIXME for now skip this only for flexible YUV formats
3788    if (colorFormat != OMX_COLOR_FormatYUV420Flexible) {
3789        video_def->eColorFormat = colorFormat;
3790    }
3791
3792    err = mOMXNode->setParameter(
3793            OMX_IndexParamPortDefinition, &def, sizeof(def));
3794
3795    if (err != OK) {
3796        ALOGE("[%s] failed to set input port definition parameters.",
3797              mComponentName.c_str());
3798
3799        return err;
3800    }
3801
3802    /* Output port configuration */
3803
3804    OMX_VIDEO_CODINGTYPE compressionFormat;
3805    err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
3806
3807    if (err != OK) {
3808        return err;
3809    }
3810
3811    err = setVideoPortFormatType(
3812            kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused);
3813
3814    if (err != OK) {
3815        ALOGE("[%s] does not support compression format %d",
3816             mComponentName.c_str(), compressionFormat);
3817
3818        return err;
3819    }
3820
3821    def.nPortIndex = kPortIndexOutput;
3822
3823    err = mOMXNode->getParameter(
3824            OMX_IndexParamPortDefinition, &def, sizeof(def));
3825
3826    if (err != OK) {
3827        return err;
3828    }
3829
3830    video_def->nFrameWidth = width;
3831    video_def->nFrameHeight = height;
3832    video_def->xFramerate = 0;
3833    video_def->nBitrate = bitrate;
3834    video_def->eCompressionFormat = compressionFormat;
3835    video_def->eColorFormat = OMX_COLOR_FormatUnused;
3836
3837    err = mOMXNode->setParameter(
3838            OMX_IndexParamPortDefinition, &def, sizeof(def));
3839
3840    if (err != OK) {
3841        ALOGE("[%s] failed to set output port definition parameters.",
3842              mComponentName.c_str());
3843
3844        return err;
3845    }
3846
3847    int32_t intraRefreshPeriod = 0;
3848    if (msg->findInt32("intra-refresh-period", &intraRefreshPeriod)
3849            && intraRefreshPeriod >= 0) {
3850        err = setIntraRefreshPeriod((uint32_t)intraRefreshPeriod, true);
3851        if (err != OK) {
3852            ALOGI("[%s] failed setIntraRefreshPeriod. Failure is fine since this key is optional",
3853                    mComponentName.c_str());
3854            err = OK;
3855        }
3856    }
3857
3858    configureEncoderLatency(msg);
3859
3860    switch (compressionFormat) {
3861        case OMX_VIDEO_CodingMPEG4:
3862            err = setupMPEG4EncoderParameters(msg);
3863            break;
3864
3865        case OMX_VIDEO_CodingH263:
3866            err = setupH263EncoderParameters(msg);
3867            break;
3868
3869        case OMX_VIDEO_CodingAVC:
3870            err = setupAVCEncoderParameters(msg);
3871            break;
3872
3873        case OMX_VIDEO_CodingHEVC:
3874            err = setupHEVCEncoderParameters(msg);
3875            break;
3876
3877        case OMX_VIDEO_CodingVP8:
3878        case OMX_VIDEO_CodingVP9:
3879            err = setupVPXEncoderParameters(msg, outputFormat);
3880            break;
3881
3882        default:
3883            break;
3884    }
3885
3886    if (err != OK) {
3887        return err;
3888    }
3889
3890    // Set up color aspects on input, but propagate them to the output format, as they will
3891    // not be read back from encoder.
3892    err = setColorAspectsForVideoEncoder(msg, outputFormat, inputFormat);
3893    if (err == ERROR_UNSUPPORTED) {
3894        ALOGI("[%s] cannot encode color aspects. Ignoring.", mComponentName.c_str());
3895        err = OK;
3896    }
3897
3898    if (err != OK) {
3899        return err;
3900    }
3901
3902    err = setHDRStaticInfoForVideoCodec(kPortIndexInput, msg, outputFormat);
3903    if (err == ERROR_UNSUPPORTED) { // support is optional
3904        ALOGI("[%s] cannot encode HDR static metadata. Ignoring.", mComponentName.c_str());
3905        err = OK;
3906    }
3907
3908    if (err != OK) {
3909        return err;
3910    }
3911
3912    switch (compressionFormat) {
3913        case OMX_VIDEO_CodingAVC:
3914        case OMX_VIDEO_CodingHEVC:
3915            err = configureTemporalLayers(msg, true /* inConfigure */, outputFormat);
3916            if (err != OK) {
3917                err = OK; // ignore failure
3918            }
3919            break;
3920
3921        case OMX_VIDEO_CodingVP8:
3922        case OMX_VIDEO_CodingVP9:
3923            // TODO: do we need to support android.generic layering? webrtc layering is
3924            // already set up in setupVPXEncoderParameters.
3925            break;
3926
3927        default:
3928            break;
3929    }
3930
3931    if (err == OK) {
3932        ALOGI("setupVideoEncoder succeeded");
3933    }
3934
3935    return err;
3936}
3937
3938status_t ACodec::setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode) {
3939    OMX_VIDEO_PARAM_INTRAREFRESHTYPE params;
3940    InitOMXParams(&params);
3941    params.nPortIndex = kPortIndexOutput;
3942
3943    params.eRefreshMode = static_cast<OMX_VIDEO_INTRAREFRESHTYPE>(mode);
3944
3945    if (params.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic ||
3946            params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) {
3947        int32_t mbs;
3948        if (!msg->findInt32("intra-refresh-CIR-mbs", &mbs)) {
3949            return INVALID_OPERATION;
3950        }
3951        params.nCirMBs = mbs;
3952    }
3953
3954    if (params.eRefreshMode == OMX_VIDEO_IntraRefreshAdaptive ||
3955            params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) {
3956        int32_t mbs;
3957        if (!msg->findInt32("intra-refresh-AIR-mbs", &mbs)) {
3958            return INVALID_OPERATION;
3959        }
3960        params.nAirMBs = mbs;
3961
3962        int32_t ref;
3963        if (!msg->findInt32("intra-refresh-AIR-ref", &ref)) {
3964            return INVALID_OPERATION;
3965        }
3966        params.nAirRef = ref;
3967    }
3968
3969    status_t err = mOMXNode->setParameter(
3970            OMX_IndexParamVideoIntraRefresh, &params, sizeof(params));
3971    return err;
3972}
3973
3974static OMX_U32 setPFramesSpacing(
3975        float iFramesInterval /* seconds */, int32_t frameRate, uint32_t BFramesSpacing = 0) {
3976    // BFramesSpacing is the number of B frames between I/P frames
3977    // PFramesSpacing (the value to be returned) is the number of P frames between I frames
3978    //
3979    // keyFrameInterval = ((PFramesSpacing + 1) * BFramesSpacing) + PFramesSpacing + 1
3980    //                                     ^^^                            ^^^        ^^^
3981    //                              number of B frames                number of P    I frame
3982    //
3983    //                  = (PFramesSpacing + 1) * (BFramesSpacing + 1)
3984    //
3985    // E.g.
3986    //      I   P   I  : I-interval: 8, nPFrames 1, nBFrames 3
3987    //       BBB BBB
3988
3989    if (iFramesInterval < 0) { // just 1 key frame
3990        return 0xFFFFFFFE; // don't use maxint as key-frame-interval calculation will add 1
3991    } else if (iFramesInterval == 0) { // just key frames
3992        return 0;
3993    }
3994
3995    // round down as key-frame-interval is an upper limit
3996    uint32_t keyFrameInterval = uint32_t(frameRate * iFramesInterval);
3997    OMX_U32 ret = keyFrameInterval / (BFramesSpacing + 1);
3998    return ret > 0 ? ret - 1 : 0;
3999}
4000
4001static OMX_VIDEO_CONTROLRATETYPE getBitrateMode(const sp<AMessage> &msg) {
4002    int32_t tmp;
4003    if (!msg->findInt32("bitrate-mode", &tmp)) {
4004        return OMX_Video_ControlRateVariable;
4005    }
4006
4007    return static_cast<OMX_VIDEO_CONTROLRATETYPE>(tmp);
4008}
4009
4010status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) {
4011    int32_t bitrate;
4012    float iFrameInterval;
4013    if (!msg->findInt32("bitrate", &bitrate)
4014            || !msg->findAsFloat("i-frame-interval", &iFrameInterval)) {
4015        return INVALID_OPERATION;
4016    }
4017
4018    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
4019
4020    float frameRate;
4021    if (!msg->findFloat("frame-rate", &frameRate)) {
4022        int32_t tmp;
4023        if (!msg->findInt32("frame-rate", &tmp)) {
4024            return INVALID_OPERATION;
4025        }
4026        frameRate = (float)tmp;
4027    }
4028
4029    OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type;
4030    InitOMXParams(&mpeg4type);
4031    mpeg4type.nPortIndex = kPortIndexOutput;
4032
4033    status_t err = mOMXNode->getParameter(
4034            OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
4035
4036    if (err != OK) {
4037        return err;
4038    }
4039
4040    mpeg4type.nSliceHeaderSpacing = 0;
4041    mpeg4type.bSVH = OMX_FALSE;
4042    mpeg4type.bGov = OMX_FALSE;
4043
4044    mpeg4type.nAllowedPictureTypes =
4045        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
4046
4047    mpeg4type.nBFrames = 0;
4048    mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, mpeg4type.nBFrames);
4049    if (mpeg4type.nPFrames == 0) {
4050        mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
4051    }
4052    mpeg4type.nIDCVLCThreshold = 0;
4053    mpeg4type.bACPred = OMX_TRUE;
4054    mpeg4type.nMaxPacketSize = 256;
4055    mpeg4type.nTimeIncRes = 1000;
4056    mpeg4type.nHeaderExtension = 0;
4057    mpeg4type.bReversibleVLC = OMX_FALSE;
4058
4059    int32_t profile;
4060    if (msg->findInt32("profile", &profile)) {
4061        int32_t level;
4062        if (!msg->findInt32("level", &level)) {
4063            return INVALID_OPERATION;
4064        }
4065
4066        err = verifySupportForProfileAndLevel(profile, level);
4067
4068        if (err != OK) {
4069            return err;
4070        }
4071
4072        mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile);
4073        mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level);
4074    }
4075
4076    err = mOMXNode->setParameter(
4077            OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
4078
4079    if (err != OK) {
4080        return err;
4081    }
4082
4083    err = configureBitrate(bitrate, bitrateMode);
4084
4085    if (err != OK) {
4086        return err;
4087    }
4088
4089    return setupErrorCorrectionParameters();
4090}
4091
4092status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) {
4093    int32_t bitrate;
4094    float iFrameInterval;
4095    if (!msg->findInt32("bitrate", &bitrate)
4096            || !msg->findAsFloat("i-frame-interval", &iFrameInterval)) {
4097        return INVALID_OPERATION;
4098    }
4099
4100    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
4101
4102    float frameRate;
4103    if (!msg->findFloat("frame-rate", &frameRate)) {
4104        int32_t tmp;
4105        if (!msg->findInt32("frame-rate", &tmp)) {
4106            return INVALID_OPERATION;
4107        }
4108        frameRate = (float)tmp;
4109    }
4110
4111    OMX_VIDEO_PARAM_H263TYPE h263type;
4112    InitOMXParams(&h263type);
4113    h263type.nPortIndex = kPortIndexOutput;
4114
4115    status_t err = mOMXNode->getParameter(
4116            OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
4117
4118    if (err != OK) {
4119        return err;
4120    }
4121
4122    h263type.nAllowedPictureTypes =
4123        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
4124
4125    h263type.nBFrames = 0;
4126    h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, h263type.nBFrames);
4127    if (h263type.nPFrames == 0) {
4128        h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
4129    }
4130
4131    int32_t profile;
4132    if (msg->findInt32("profile", &profile)) {
4133        int32_t level;
4134        if (!msg->findInt32("level", &level)) {
4135            return INVALID_OPERATION;
4136        }
4137
4138        err = verifySupportForProfileAndLevel(profile, level);
4139
4140        if (err != OK) {
4141            return err;
4142        }
4143
4144        h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile);
4145        h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level);
4146    }
4147
4148    h263type.bPLUSPTYPEAllowed = OMX_FALSE;
4149    h263type.bForceRoundingTypeToZero = OMX_FALSE;
4150    h263type.nPictureHeaderRepetition = 0;
4151    h263type.nGOBHeaderInterval = 0;
4152
4153    err = mOMXNode->setParameter(
4154            OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
4155
4156    if (err != OK) {
4157        return err;
4158    }
4159
4160    err = configureBitrate(bitrate, bitrateMode);
4161
4162    if (err != OK) {
4163        return err;
4164    }
4165
4166    return setupErrorCorrectionParameters();
4167}
4168
4169// static
4170int /* OMX_VIDEO_AVCLEVELTYPE */ ACodec::getAVCLevelFor(
4171        int width, int height, int rate, int bitrate,
4172        OMX_VIDEO_AVCPROFILETYPE profile) {
4173    // convert bitrate to main/baseline profile kbps equivalent
4174    switch (profile) {
4175        case OMX_VIDEO_AVCProfileHigh10:
4176            bitrate = divUp(bitrate, 3000); break;
4177        case OMX_VIDEO_AVCProfileHigh:
4178            bitrate = divUp(bitrate, 1250); break;
4179        default:
4180            bitrate = divUp(bitrate, 1000); break;
4181    }
4182
4183    // convert size and rate to MBs
4184    width = divUp(width, 16);
4185    height = divUp(height, 16);
4186    int mbs = width * height;
4187    rate *= mbs;
4188    int maxDimension = max(width, height);
4189
4190    static const int limits[][5] = {
4191        /*   MBps     MB   dim  bitrate        level */
4192        {    1485,    99,  28,     64, OMX_VIDEO_AVCLevel1  },
4193        {    1485,    99,  28,    128, OMX_VIDEO_AVCLevel1b },
4194        {    3000,   396,  56,    192, OMX_VIDEO_AVCLevel11 },
4195        {    6000,   396,  56,    384, OMX_VIDEO_AVCLevel12 },
4196        {   11880,   396,  56,    768, OMX_VIDEO_AVCLevel13 },
4197        {   11880,   396,  56,   2000, OMX_VIDEO_AVCLevel2  },
4198        {   19800,   792,  79,   4000, OMX_VIDEO_AVCLevel21 },
4199        {   20250,  1620, 113,   4000, OMX_VIDEO_AVCLevel22 },
4200        {   40500,  1620, 113,  10000, OMX_VIDEO_AVCLevel3  },
4201        {  108000,  3600, 169,  14000, OMX_VIDEO_AVCLevel31 },
4202        {  216000,  5120, 202,  20000, OMX_VIDEO_AVCLevel32 },
4203        {  245760,  8192, 256,  20000, OMX_VIDEO_AVCLevel4  },
4204        {  245760,  8192, 256,  50000, OMX_VIDEO_AVCLevel41 },
4205        {  522240,  8704, 263,  50000, OMX_VIDEO_AVCLevel42 },
4206        {  589824, 22080, 420, 135000, OMX_VIDEO_AVCLevel5  },
4207        {  983040, 36864, 543, 240000, OMX_VIDEO_AVCLevel51 },
4208        { 2073600, 36864, 543, 240000, OMX_VIDEO_AVCLevel52 },
4209    };
4210
4211    for (size_t i = 0; i < ARRAY_SIZE(limits); i++) {
4212        const int (&limit)[5] = limits[i];
4213        if (rate <= limit[0] && mbs <= limit[1] && maxDimension <= limit[2]
4214                && bitrate <= limit[3]) {
4215            return limit[4];
4216        }
4217    }
4218    return 0;
4219}
4220
4221status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) {
4222    int32_t bitrate;
4223    float iFrameInterval;
4224    if (!msg->findInt32("bitrate", &bitrate)
4225            || !msg->findAsFloat("i-frame-interval", &iFrameInterval)) {
4226        return INVALID_OPERATION;
4227    }
4228
4229    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
4230
4231    float frameRate;
4232    if (!msg->findFloat("frame-rate", &frameRate)) {
4233        int32_t tmp;
4234        if (!msg->findInt32("frame-rate", &tmp)) {
4235            return INVALID_OPERATION;
4236        }
4237        frameRate = (float)tmp;
4238    }
4239
4240    status_t err = OK;
4241    int32_t intraRefreshMode = 0;
4242    if (msg->findInt32("intra-refresh-mode", &intraRefreshMode)) {
4243        err = setCyclicIntraMacroblockRefresh(msg, intraRefreshMode);
4244        if (err != OK) {
4245            ALOGE("Setting intra macroblock refresh mode (%d) failed: 0x%x",
4246                    err, intraRefreshMode);
4247            return err;
4248        }
4249    }
4250
4251    OMX_VIDEO_PARAM_AVCTYPE h264type;
4252    InitOMXParams(&h264type);
4253    h264type.nPortIndex = kPortIndexOutput;
4254
4255    err = mOMXNode->getParameter(
4256            OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
4257
4258    if (err != OK) {
4259        return err;
4260    }
4261
4262    h264type.nAllowedPictureTypes =
4263        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
4264
4265    int32_t profile;
4266    if (msg->findInt32("profile", &profile)) {
4267        int32_t level;
4268        if (!msg->findInt32("level", &level)) {
4269            return INVALID_OPERATION;
4270        }
4271
4272        err = verifySupportForProfileAndLevel(profile, level);
4273
4274        if (err != OK) {
4275            return err;
4276        }
4277
4278        h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile);
4279        h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level);
4280    } else {
4281        h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
4282#if 0   /* DON'T YET DEFAULT TO HIGHEST PROFILE */
4283        // Use largest supported profile for AVC recording if profile is not specified.
4284        for (OMX_VIDEO_AVCPROFILETYPE profile : {
4285                OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCProfileMain }) {
4286            if (verifySupportForProfileAndLevel(profile, 0) == OK) {
4287                h264type.eProfile = profile;
4288                break;
4289            }
4290        }
4291#endif
4292    }
4293
4294    ALOGI("setupAVCEncoderParameters with [profile: %s] [level: %s]",
4295            asString(h264type.eProfile), asString(h264type.eLevel));
4296
4297    if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
4298        h264type.nSliceHeaderSpacing = 0;
4299        h264type.bUseHadamard = OMX_TRUE;
4300        h264type.nRefFrames = 1;
4301        h264type.nBFrames = 0;
4302        h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, h264type.nBFrames);
4303        if (h264type.nPFrames == 0) {
4304            h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
4305        }
4306        h264type.nRefIdx10ActiveMinus1 = 0;
4307        h264type.nRefIdx11ActiveMinus1 = 0;
4308        h264type.bEntropyCodingCABAC = OMX_FALSE;
4309        h264type.bWeightedPPrediction = OMX_FALSE;
4310        h264type.bconstIpred = OMX_FALSE;
4311        h264type.bDirect8x8Inference = OMX_FALSE;
4312        h264type.bDirectSpatialTemporal = OMX_FALSE;
4313        h264type.nCabacInitIdc = 0;
4314    } else if (h264type.eProfile == OMX_VIDEO_AVCProfileMain ||
4315            h264type.eProfile == OMX_VIDEO_AVCProfileHigh) {
4316        h264type.nSliceHeaderSpacing = 0;
4317        h264type.bUseHadamard = OMX_TRUE;
4318        h264type.nRefFrames = 2;
4319        h264type.nBFrames = mLatency == 0 ? 1 : std::min(1U, mLatency - 1);
4320        h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, h264type.nBFrames);
4321        h264type.nAllowedPictureTypes =
4322            OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP | OMX_VIDEO_PictureTypeB;
4323        h264type.nRefIdx10ActiveMinus1 = 0;
4324        h264type.nRefIdx11ActiveMinus1 = 0;
4325        h264type.bEntropyCodingCABAC = OMX_TRUE;
4326        h264type.bWeightedPPrediction = OMX_TRUE;
4327        h264type.bconstIpred = OMX_TRUE;
4328        h264type.bDirect8x8Inference = OMX_TRUE;
4329        h264type.bDirectSpatialTemporal = OMX_TRUE;
4330        h264type.nCabacInitIdc = 1;
4331    }
4332
4333    if (h264type.nBFrames != 0) {
4334        h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
4335    }
4336
4337    h264type.bEnableUEP = OMX_FALSE;
4338    h264type.bEnableFMO = OMX_FALSE;
4339    h264type.bEnableASO = OMX_FALSE;
4340    h264type.bEnableRS = OMX_FALSE;
4341    h264type.bFrameMBsOnly = OMX_TRUE;
4342    h264type.bMBAFF = OMX_FALSE;
4343    h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
4344
4345    err = mOMXNode->setParameter(
4346            OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
4347
4348    if (err != OK) {
4349        return err;
4350    }
4351
4352    // TRICKY: if we are enabling temporal layering as well, some codecs may not support layering
4353    // when B-frames are enabled. Detect this now so we can disable B frames if temporal layering
4354    // is preferred.
4355    AString tsSchema;
4356    int32_t preferBFrames = (int32_t)false;
4357    if (msg->findString("ts-schema", &tsSchema)
4358            && (!msg->findInt32("android._prefer-b-frames", &preferBFrames) || !preferBFrames)) {
4359        OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE layering;
4360        InitOMXParams(&layering);
4361        layering.nPortIndex = kPortIndexOutput;
4362        if (mOMXNode->getParameter(
4363                        (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering,
4364                        &layering, sizeof(layering)) == OK
4365                && layering.eSupportedPatterns
4366                && layering.nBLayerCountMax == 0) {
4367            h264type.nBFrames = 0;
4368            h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, h264type.nBFrames);
4369            h264type.nAllowedPictureTypes &= ~OMX_VIDEO_PictureTypeB;
4370            ALOGI("disabling B-frames");
4371            err = mOMXNode->setParameter(
4372                    OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
4373
4374            if (err != OK) {
4375                return err;
4376            }
4377        }
4378    }
4379
4380    return configureBitrate(bitrate, bitrateMode);
4381}
4382
4383status_t ACodec::setupHEVCEncoderParameters(const sp<AMessage> &msg) {
4384    int32_t bitrate;
4385    float iFrameInterval;
4386    if (!msg->findInt32("bitrate", &bitrate)
4387            || !msg->findAsFloat("i-frame-interval", &iFrameInterval)) {
4388        return INVALID_OPERATION;
4389    }
4390
4391    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
4392
4393    float frameRate;
4394    if (!msg->findFloat("frame-rate", &frameRate)) {
4395        int32_t tmp;
4396        if (!msg->findInt32("frame-rate", &tmp)) {
4397            return INVALID_OPERATION;
4398        }
4399        frameRate = (float)tmp;
4400    }
4401
4402    OMX_VIDEO_PARAM_HEVCTYPE hevcType;
4403    InitOMXParams(&hevcType);
4404    hevcType.nPortIndex = kPortIndexOutput;
4405
4406    status_t err = OK;
4407    err = mOMXNode->getParameter(
4408            (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
4409    if (err != OK) {
4410        return err;
4411    }
4412
4413    int32_t profile;
4414    if (msg->findInt32("profile", &profile)) {
4415        int32_t level;
4416        if (!msg->findInt32("level", &level)) {
4417            return INVALID_OPERATION;
4418        }
4419
4420        err = verifySupportForProfileAndLevel(profile, level);
4421        if (err != OK) {
4422            return err;
4423        }
4424
4425        hevcType.eProfile = static_cast<OMX_VIDEO_HEVCPROFILETYPE>(profile);
4426        hevcType.eLevel = static_cast<OMX_VIDEO_HEVCLEVELTYPE>(level);
4427    }
4428    // TODO: finer control?
4429    hevcType.nKeyFrameInterval = setPFramesSpacing(iFrameInterval, frameRate) + 1;
4430
4431    err = mOMXNode->setParameter(
4432            (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
4433    if (err != OK) {
4434        return err;
4435    }
4436
4437    return configureBitrate(bitrate, bitrateMode);
4438}
4439
4440status_t ACodec::setupVPXEncoderParameters(const sp<AMessage> &msg, sp<AMessage> &outputFormat) {
4441    int32_t bitrate;
4442    float iFrameInterval = 0;
4443    size_t tsLayers = 0;
4444    OMX_VIDEO_ANDROID_VPXTEMPORALLAYERPATTERNTYPE pattern =
4445        OMX_VIDEO_VPXTemporalLayerPatternNone;
4446    static const uint32_t kVp8LayerRateAlloction
4447        [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS]
4448        [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS] = {
4449        {100, 100, 100},  // 1 layer
4450        { 60, 100, 100},  // 2 layers {60%, 40%}
4451        { 40,  60, 100},  // 3 layers {40%, 20%, 40%}
4452    };
4453    if (!msg->findInt32("bitrate", &bitrate)) {
4454        return INVALID_OPERATION;
4455    }
4456    msg->findAsFloat("i-frame-interval", &iFrameInterval);
4457
4458    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
4459
4460    float frameRate;
4461    if (!msg->findFloat("frame-rate", &frameRate)) {
4462        int32_t tmp;
4463        if (!msg->findInt32("frame-rate", &tmp)) {
4464            return INVALID_OPERATION;
4465        }
4466        frameRate = (float)tmp;
4467    }
4468
4469    AString tsSchema;
4470    OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE tsType =
4471        OMX_VIDEO_AndroidTemporalLayeringPatternNone;
4472
4473    if (msg->findString("ts-schema", &tsSchema)) {
4474        unsigned int numLayers = 0;
4475        unsigned int numBLayers = 0;
4476        int tags;
4477        char dummy;
4478        if (sscanf(tsSchema.c_str(), "webrtc.vp8.%u-layer%c", &numLayers, &dummy) == 1
4479                && numLayers > 0) {
4480            pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
4481            tsType = OMX_VIDEO_AndroidTemporalLayeringPatternWebRTC;
4482            tsLayers = numLayers;
4483        } else if ((tags = sscanf(tsSchema.c_str(), "android.generic.%u%c%u%c",
4484                        &numLayers, &dummy, &numBLayers, &dummy))
4485                && (tags == 1 || (tags == 3 && dummy == '+'))
4486                && numLayers > 0 && numLayers < UINT32_MAX - numBLayers) {
4487            pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
4488            // VPX does not have a concept of B-frames, so just count all layers
4489            tsType = OMX_VIDEO_AndroidTemporalLayeringPatternAndroid;
4490            tsLayers = numLayers + numBLayers;
4491        } else {
4492            ALOGW("Ignoring unsupported ts-schema [%s]", tsSchema.c_str());
4493        }
4494        tsLayers = min(tsLayers, (size_t)OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS);
4495    }
4496
4497    OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type;
4498    InitOMXParams(&vp8type);
4499    vp8type.nPortIndex = kPortIndexOutput;
4500    status_t err = mOMXNode->getParameter(
4501            (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
4502            &vp8type, sizeof(vp8type));
4503
4504    if (err == OK) {
4505        if (iFrameInterval > 0) {
4506            vp8type.nKeyFrameInterval = setPFramesSpacing(iFrameInterval, frameRate) + 1;
4507        }
4508        vp8type.eTemporalPattern = pattern;
4509        vp8type.nTemporalLayerCount = tsLayers;
4510        if (tsLayers > 0) {
4511            for (size_t i = 0; i < OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS; i++) {
4512                vp8type.nTemporalLayerBitrateRatio[i] =
4513                    kVp8LayerRateAlloction[tsLayers - 1][i];
4514            }
4515        }
4516        if (bitrateMode == OMX_Video_ControlRateConstant) {
4517            vp8type.nMinQuantizer = 2;
4518            vp8type.nMaxQuantizer = 63;
4519        }
4520
4521        err = mOMXNode->setParameter(
4522                (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
4523                &vp8type, sizeof(vp8type));
4524        if (err != OK) {
4525            ALOGW("Extended VP8 parameters set failed: %d", err);
4526        } else if (tsType == OMX_VIDEO_AndroidTemporalLayeringPatternWebRTC) {
4527            // advertise even single layer WebRTC layering, as it is defined
4528            outputFormat->setString("ts-schema", AStringPrintf("webrtc.vp8.%u-layer", tsLayers));
4529        } else if (tsLayers > 0) {
4530            // tsType == OMX_VIDEO_AndroidTemporalLayeringPatternAndroid
4531            outputFormat->setString("ts-schema", AStringPrintf("android.generic.%u", tsLayers));
4532        }
4533    }
4534
4535    return configureBitrate(bitrate, bitrateMode);
4536}
4537
4538status_t ACodec::verifySupportForProfileAndLevel(
4539        int32_t profile, int32_t level) {
4540    OMX_VIDEO_PARAM_PROFILELEVELTYPE params;
4541    InitOMXParams(&params);
4542    params.nPortIndex = kPortIndexOutput;
4543
4544    for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
4545        params.nProfileIndex = index;
4546        status_t err = mOMXNode->getParameter(
4547                OMX_IndexParamVideoProfileLevelQuerySupported,
4548                &params, sizeof(params));
4549
4550        if (err != OK) {
4551            return err;
4552        }
4553
4554        int32_t supportedProfile = static_cast<int32_t>(params.eProfile);
4555        int32_t supportedLevel = static_cast<int32_t>(params.eLevel);
4556
4557        if (profile == supportedProfile && level <= supportedLevel) {
4558            return OK;
4559        }
4560
4561        if (index == kMaxIndicesToCheck) {
4562            ALOGW("[%s] stopping checking profiles after %u: %x/%x",
4563                    mComponentName.c_str(), index,
4564                    params.eProfile, params.eLevel);
4565        }
4566    }
4567    return ERROR_UNSUPPORTED;
4568}
4569
4570status_t ACodec::configureBitrate(
4571        int32_t bitrate, OMX_VIDEO_CONTROLRATETYPE bitrateMode) {
4572    OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
4573    InitOMXParams(&bitrateType);
4574    bitrateType.nPortIndex = kPortIndexOutput;
4575
4576    status_t err = mOMXNode->getParameter(
4577            OMX_IndexParamVideoBitrate, &bitrateType, sizeof(bitrateType));
4578
4579    if (err != OK) {
4580        return err;
4581    }
4582
4583    bitrateType.eControlRate = bitrateMode;
4584    bitrateType.nTargetBitrate = bitrate;
4585
4586    return mOMXNode->setParameter(
4587            OMX_IndexParamVideoBitrate, &bitrateType, sizeof(bitrateType));
4588}
4589
4590void ACodec::configureEncoderLatency(const sp<AMessage> &msg) {
4591    if (!mIsEncoder || !mIsVideo) {
4592        return;
4593    }
4594
4595    int32_t latency = 0, bitrateMode;
4596    if (msg->findInt32("latency", &latency) && latency > 0) {
4597        status_t err = setLatency(latency);
4598        if (err != OK) {
4599            ALOGW("[%s] failed setLatency. Failure is fine since this key is optional",
4600                    mComponentName.c_str());
4601            err = OK;
4602        } else {
4603            mLatency = latency;
4604        }
4605    } else if ((!msg->findInt32("bitrate-mode", &bitrateMode) &&
4606            bitrateMode == OMX_Video_ControlRateConstant)) {
4607        // default the latency to be 1 if latency key is not specified or unsupported and bitrateMode
4608        // is CBR.
4609        mLatency = 1;
4610    }
4611}
4612
4613status_t ACodec::setupErrorCorrectionParameters() {
4614    OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
4615    InitOMXParams(&errorCorrectionType);
4616    errorCorrectionType.nPortIndex = kPortIndexOutput;
4617
4618    status_t err = mOMXNode->getParameter(
4619            OMX_IndexParamVideoErrorCorrection,
4620            &errorCorrectionType, sizeof(errorCorrectionType));
4621
4622    if (err != OK) {
4623        return OK;  // Optional feature. Ignore this failure
4624    }
4625
4626    errorCorrectionType.bEnableHEC = OMX_FALSE;
4627    errorCorrectionType.bEnableResync = OMX_TRUE;
4628    errorCorrectionType.nResynchMarkerSpacing = 256;
4629    errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
4630    errorCorrectionType.bEnableRVLC = OMX_FALSE;
4631
4632    return mOMXNode->setParameter(
4633            OMX_IndexParamVideoErrorCorrection,
4634            &errorCorrectionType, sizeof(errorCorrectionType));
4635}
4636
4637status_t ACodec::setVideoFormatOnPort(
4638        OMX_U32 portIndex,
4639        int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat,
4640        float frameRate) {
4641    OMX_PARAM_PORTDEFINITIONTYPE def;
4642    InitOMXParams(&def);
4643    def.nPortIndex = portIndex;
4644
4645    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
4646
4647    status_t err = mOMXNode->getParameter(
4648            OMX_IndexParamPortDefinition, &def, sizeof(def));
4649    if (err != OK) {
4650        return err;
4651    }
4652
4653    if (portIndex == kPortIndexInput) {
4654        // XXX Need a (much) better heuristic to compute input buffer sizes.
4655        const size_t X = 64 * 1024;
4656        if (def.nBufferSize < X) {
4657            def.nBufferSize = X;
4658        }
4659    }
4660
4661    if (def.eDomain != OMX_PortDomainVideo) {
4662        ALOGE("expected video port, got %s(%d)", asString(def.eDomain), def.eDomain);
4663        return FAILED_TRANSACTION;
4664    }
4665
4666    video_def->nFrameWidth = width;
4667    video_def->nFrameHeight = height;
4668
4669    if (portIndex == kPortIndexInput) {
4670        video_def->eCompressionFormat = compressionFormat;
4671        video_def->eColorFormat = OMX_COLOR_FormatUnused;
4672        if (frameRate >= 0) {
4673            video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f);
4674        }
4675    }
4676
4677    err = mOMXNode->setParameter(
4678            OMX_IndexParamPortDefinition, &def, sizeof(def));
4679
4680    return err;
4681}
4682
4683size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const {
4684    size_t n = 0;
4685
4686    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
4687        const BufferInfo &info = mBuffers[portIndex].itemAt(i);
4688
4689        if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) {
4690            ++n;
4691        }
4692    }
4693
4694    return n;
4695}
4696
4697size_t ACodec::countBuffersOwnedByNativeWindow() const {
4698    size_t n = 0;
4699
4700    for (size_t i = 0; i < mBuffers[kPortIndexOutput].size(); ++i) {
4701        const BufferInfo &info = mBuffers[kPortIndexOutput].itemAt(i);
4702
4703        if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
4704            ++n;
4705        }
4706    }
4707
4708    return n;
4709}
4710
4711void ACodec::waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs() {
4712    if (mNativeWindow == NULL) {
4713        return;
4714    }
4715
4716    while (countBuffersOwnedByNativeWindow() > mNumUndequeuedBuffers
4717            && dequeueBufferFromNativeWindow() != NULL) {
4718        // these buffers will be submitted as regular buffers; account for this
4719        if (storingMetadataInDecodedBuffers() && mMetadataBuffersToSubmit > 0) {
4720            --mMetadataBuffersToSubmit;
4721        }
4722    }
4723}
4724
4725bool ACodec::allYourBuffersAreBelongToUs(
4726        OMX_U32 portIndex) {
4727    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
4728        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
4729
4730        if (info->mStatus != BufferInfo::OWNED_BY_US
4731                && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
4732            ALOGV("[%s] Buffer %u on port %u still has status %d",
4733                    mComponentName.c_str(),
4734                    info->mBufferID, portIndex, info->mStatus);
4735            return false;
4736        }
4737    }
4738
4739    return true;
4740}
4741
4742bool ACodec::allYourBuffersAreBelongToUs() {
4743    return allYourBuffersAreBelongToUs(kPortIndexInput)
4744        && allYourBuffersAreBelongToUs(kPortIndexOutput);
4745}
4746
4747void ACodec::deferMessage(const sp<AMessage> &msg) {
4748    mDeferredQueue.push_back(msg);
4749}
4750
4751void ACodec::processDeferredMessages() {
4752    List<sp<AMessage> > queue = mDeferredQueue;
4753    mDeferredQueue.clear();
4754
4755    List<sp<AMessage> >::iterator it = queue.begin();
4756    while (it != queue.end()) {
4757        onMessageReceived(*it++);
4758    }
4759}
4760
4761status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> &notify) {
4762    const char *niceIndex = portIndex == kPortIndexInput ? "input" : "output";
4763    OMX_PARAM_PORTDEFINITIONTYPE def;
4764    InitOMXParams(&def);
4765    def.nPortIndex = portIndex;
4766
4767    status_t err = mOMXNode->getParameter(OMX_IndexParamPortDefinition, &def, sizeof(def));
4768    if (err != OK) {
4769        return err;
4770    }
4771
4772    if (def.eDir != (portIndex == kPortIndexOutput ? OMX_DirOutput : OMX_DirInput)) {
4773        ALOGE("unexpected dir: %s(%d) on %s port", asString(def.eDir), def.eDir, niceIndex);
4774        return BAD_VALUE;
4775    }
4776
4777    switch (def.eDomain) {
4778        case OMX_PortDomainVideo:
4779        {
4780            OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
4781            switch ((int)videoDef->eCompressionFormat) {
4782                case OMX_VIDEO_CodingUnused:
4783                {
4784                    CHECK(mIsEncoder ^ (portIndex == kPortIndexOutput));
4785                    notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW);
4786
4787                    notify->setInt32("stride", videoDef->nStride);
4788                    notify->setInt32("slice-height", videoDef->nSliceHeight);
4789                    notify->setInt32("color-format", videoDef->eColorFormat);
4790
4791                    if (mNativeWindow == NULL) {
4792                        DescribeColorFormat2Params describeParams;
4793                        InitOMXParams(&describeParams);
4794                        describeParams.eColorFormat = videoDef->eColorFormat;
4795                        describeParams.nFrameWidth = videoDef->nFrameWidth;
4796                        describeParams.nFrameHeight = videoDef->nFrameHeight;
4797                        describeParams.nStride = videoDef->nStride;
4798                        describeParams.nSliceHeight = videoDef->nSliceHeight;
4799                        describeParams.bUsingNativeBuffers = OMX_FALSE;
4800
4801                        if (DescribeColorFormat(mOMXNode, describeParams)) {
4802                            notify->setBuffer(
4803                                    "image-data",
4804                                    ABuffer::CreateAsCopy(
4805                                            &describeParams.sMediaImage,
4806                                            sizeof(describeParams.sMediaImage)));
4807
4808                            MediaImage2 &img = describeParams.sMediaImage;
4809                            MediaImage2::PlaneInfo *plane = img.mPlane;
4810                            ALOGV("[%s] MediaImage { F(%ux%u) @%u+%d+%d @%u+%d+%d @%u+%d+%d }",
4811                                    mComponentName.c_str(), img.mWidth, img.mHeight,
4812                                    plane[0].mOffset, plane[0].mColInc, plane[0].mRowInc,
4813                                    plane[1].mOffset, plane[1].mColInc, plane[1].mRowInc,
4814                                    plane[2].mOffset, plane[2].mColInc, plane[2].mRowInc);
4815                        }
4816                    }
4817
4818                    int32_t width = (int32_t)videoDef->nFrameWidth;
4819                    int32_t height = (int32_t)videoDef->nFrameHeight;
4820
4821                    if (portIndex == kPortIndexOutput) {
4822                        OMX_CONFIG_RECTTYPE rect;
4823                        InitOMXParams(&rect);
4824                        rect.nPortIndex = portIndex;
4825
4826                        if (mOMXNode->getConfig(
4827                                    (portIndex == kPortIndexOutput ?
4828                                            OMX_IndexConfigCommonOutputCrop :
4829                                            OMX_IndexConfigCommonInputCrop),
4830                                    &rect, sizeof(rect)) != OK) {
4831                            rect.nLeft = 0;
4832                            rect.nTop = 0;
4833                            rect.nWidth = videoDef->nFrameWidth;
4834                            rect.nHeight = videoDef->nFrameHeight;
4835                        }
4836
4837                        if (rect.nLeft < 0 ||
4838                            rect.nTop < 0 ||
4839                            rect.nLeft + rect.nWidth > videoDef->nFrameWidth ||
4840                            rect.nTop + rect.nHeight > videoDef->nFrameHeight) {
4841                            ALOGE("Wrong cropped rect (%d, %d) - (%u, %u) vs. frame (%u, %u)",
4842                                    rect.nLeft, rect.nTop,
4843                                    rect.nLeft + rect.nWidth, rect.nTop + rect.nHeight,
4844                                    videoDef->nFrameWidth, videoDef->nFrameHeight);
4845                            return BAD_VALUE;
4846                        }
4847
4848                        notify->setRect(
4849                                "crop",
4850                                rect.nLeft,
4851                                rect.nTop,
4852                                rect.nLeft + rect.nWidth - 1,
4853                                rect.nTop + rect.nHeight - 1);
4854
4855                        width = rect.nWidth;
4856                        height = rect.nHeight;
4857
4858                        android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN;
4859                        (void)getColorAspectsAndDataSpaceForVideoDecoder(
4860                                width, height, mConfigFormat, notify,
4861                                mUsingNativeWindow ? &dataSpace : NULL);
4862                        if (mUsingNativeWindow) {
4863                            notify->setInt32("android._dataspace", dataSpace);
4864                        }
4865                        (void)getHDRStaticInfoForVideoCodec(kPortIndexOutput, notify);
4866                    } else {
4867                        (void)getInputColorAspectsForVideoEncoder(notify);
4868                        if (mConfigFormat->contains("hdr-static-info")) {
4869                            (void)getHDRStaticInfoForVideoCodec(kPortIndexInput, notify);
4870                        }
4871                        uint32_t latency = 0;
4872                        if (mIsEncoder && getLatency(&latency) == OK && latency > 0) {
4873                            notify->setInt32("latency", latency);
4874                        }
4875                    }
4876
4877                    break;
4878                }
4879
4880                case OMX_VIDEO_CodingVP8:
4881                case OMX_VIDEO_CodingVP9:
4882                {
4883                    OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type;
4884                    InitOMXParams(&vp8type);
4885                    vp8type.nPortIndex = kPortIndexOutput;
4886                    status_t err = mOMXNode->getParameter(
4887                            (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
4888                            &vp8type,
4889                            sizeof(vp8type));
4890
4891                    if (err == OK) {
4892                        if (vp8type.eTemporalPattern == OMX_VIDEO_VPXTemporalLayerPatternWebRTC
4893                                && vp8type.nTemporalLayerCount > 0
4894                                && vp8type.nTemporalLayerCount
4895                                        <= OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS) {
4896                            // advertise as android.generic if we configured for android.generic
4897                            AString origSchema;
4898                            if (notify->findString("ts-schema", &origSchema)
4899                                    && origSchema.startsWith("android.generic")) {
4900                                notify->setString("ts-schema", AStringPrintf(
4901                                        "android.generic.%u", vp8type.nTemporalLayerCount));
4902                            } else {
4903                                notify->setString("ts-schema", AStringPrintf(
4904                                        "webrtc.vp8.%u-layer", vp8type.nTemporalLayerCount));
4905                            }
4906                        }
4907                    }
4908                    // Fall through to set up mime.
4909                }
4910
4911                default:
4912                {
4913                    if (mIsEncoder ^ (portIndex == kPortIndexOutput)) {
4914                        // should be CodingUnused
4915                        ALOGE("Raw port video compression format is %s(%d)",
4916                                asString(videoDef->eCompressionFormat),
4917                                videoDef->eCompressionFormat);
4918                        return BAD_VALUE;
4919                    }
4920                    AString mime;
4921                    if (GetMimeTypeForVideoCoding(
4922                        videoDef->eCompressionFormat, &mime) != OK) {
4923                        notify->setString("mime", "application/octet-stream");
4924                    } else {
4925                        notify->setString("mime", mime.c_str());
4926                    }
4927                    uint32_t intraRefreshPeriod = 0;
4928                    if (mIsEncoder && getIntraRefreshPeriod(&intraRefreshPeriod) == OK
4929                            && intraRefreshPeriod > 0) {
4930                        notify->setInt32("intra-refresh-period", intraRefreshPeriod);
4931                    }
4932                    break;
4933                }
4934            }
4935            notify->setInt32("width", videoDef->nFrameWidth);
4936            notify->setInt32("height", videoDef->nFrameHeight);
4937            ALOGV("[%s] %s format is %s", mComponentName.c_str(),
4938                    portIndex == kPortIndexInput ? "input" : "output",
4939                    notify->debugString().c_str());
4940
4941            break;
4942        }
4943
4944        case OMX_PortDomainAudio:
4945        {
4946            OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
4947
4948            switch ((int)audioDef->eEncoding) {
4949                case OMX_AUDIO_CodingPCM:
4950                {
4951                    OMX_AUDIO_PARAM_PCMMODETYPE params;
4952                    InitOMXParams(&params);
4953                    params.nPortIndex = portIndex;
4954
4955                    err = mOMXNode->getParameter(
4956                            OMX_IndexParamAudioPcm, &params, sizeof(params));
4957                    if (err != OK) {
4958                        return err;
4959                    }
4960
4961                    if (params.nChannels <= 0
4962                            || (params.nChannels != 1 && !params.bInterleaved)
4963                            || params.ePCMMode != OMX_AUDIO_PCMModeLinear) {
4964                        ALOGE("unsupported PCM port: %u channels%s, %u-bit",
4965                                params.nChannels,
4966                                params.bInterleaved ? " interleaved" : "",
4967                                params.nBitPerSample);
4968                        return FAILED_TRANSACTION;
4969                    }
4970
4971                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
4972                    notify->setInt32("channel-count", params.nChannels);
4973                    notify->setInt32("sample-rate", params.nSamplingRate);
4974
4975                    AudioEncoding encoding = kAudioEncodingPcm16bit;
4976                    if (params.eNumData == OMX_NumericalDataUnsigned
4977                            && params.nBitPerSample == 8u) {
4978                        encoding = kAudioEncodingPcm8bit;
4979                    } else if (params.eNumData == OMX_NumericalDataFloat
4980                            && params.nBitPerSample == 32u) {
4981                        encoding = kAudioEncodingPcmFloat;
4982                    } else if (params.nBitPerSample != 16u
4983                            || params.eNumData != OMX_NumericalDataSigned) {
4984                        ALOGE("unsupported PCM port: %s(%d), %s(%d) mode ",
4985                                asString(params.eNumData), params.eNumData,
4986                                asString(params.ePCMMode), params.ePCMMode);
4987                        return FAILED_TRANSACTION;
4988                    }
4989                    notify->setInt32("pcm-encoding", encoding);
4990
4991                    if (mChannelMaskPresent) {
4992                        notify->setInt32("channel-mask", mChannelMask);
4993                    }
4994                    break;
4995                }
4996
4997                case OMX_AUDIO_CodingAAC:
4998                {
4999                    OMX_AUDIO_PARAM_AACPROFILETYPE params;
5000                    InitOMXParams(&params);
5001                    params.nPortIndex = portIndex;
5002
5003                    err = mOMXNode->getParameter(
5004                            OMX_IndexParamAudioAac, &params, sizeof(params));
5005                    if (err != OK) {
5006                        return err;
5007                    }
5008
5009                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
5010                    notify->setInt32("channel-count", params.nChannels);
5011                    notify->setInt32("sample-rate", params.nSampleRate);
5012                    break;
5013                }
5014
5015                case OMX_AUDIO_CodingAMR:
5016                {
5017                    OMX_AUDIO_PARAM_AMRTYPE params;
5018                    InitOMXParams(&params);
5019                    params.nPortIndex = portIndex;
5020
5021                    err = mOMXNode->getParameter(
5022                            OMX_IndexParamAudioAmr, &params, sizeof(params));
5023                    if (err != OK) {
5024                        return err;
5025                    }
5026
5027                    notify->setInt32("channel-count", 1);
5028                    if (params.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0) {
5029                        notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_WB);
5030                        notify->setInt32("sample-rate", 16000);
5031                    } else {
5032                        notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_NB);
5033                        notify->setInt32("sample-rate", 8000);
5034                    }
5035                    break;
5036                }
5037
5038                case OMX_AUDIO_CodingFLAC:
5039                {
5040                    OMX_AUDIO_PARAM_FLACTYPE params;
5041                    InitOMXParams(&params);
5042                    params.nPortIndex = portIndex;
5043
5044                    err = mOMXNode->getParameter(
5045                            OMX_IndexParamAudioFlac, &params, sizeof(params));
5046                    if (err != OK) {
5047                        return err;
5048                    }
5049
5050                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_FLAC);
5051                    notify->setInt32("channel-count", params.nChannels);
5052                    notify->setInt32("sample-rate", params.nSampleRate);
5053                    break;
5054                }
5055
5056                case OMX_AUDIO_CodingMP3:
5057                {
5058                    OMX_AUDIO_PARAM_MP3TYPE params;
5059                    InitOMXParams(&params);
5060                    params.nPortIndex = portIndex;
5061
5062                    err = mOMXNode->getParameter(
5063                            OMX_IndexParamAudioMp3, &params, sizeof(params));
5064                    if (err != OK) {
5065                        return err;
5066                    }
5067
5068                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MPEG);
5069                    notify->setInt32("channel-count", params.nChannels);
5070                    notify->setInt32("sample-rate", params.nSampleRate);
5071                    break;
5072                }
5073
5074                case OMX_AUDIO_CodingVORBIS:
5075                {
5076                    OMX_AUDIO_PARAM_VORBISTYPE params;
5077                    InitOMXParams(&params);
5078                    params.nPortIndex = portIndex;
5079
5080                    err = mOMXNode->getParameter(
5081                            OMX_IndexParamAudioVorbis, &params, sizeof(params));
5082                    if (err != OK) {
5083                        return err;
5084                    }
5085
5086                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_VORBIS);
5087                    notify->setInt32("channel-count", params.nChannels);
5088                    notify->setInt32("sample-rate", params.nSampleRate);
5089                    break;
5090                }
5091
5092                case OMX_AUDIO_CodingAndroidAC3:
5093                {
5094                    OMX_AUDIO_PARAM_ANDROID_AC3TYPE params;
5095                    InitOMXParams(&params);
5096                    params.nPortIndex = portIndex;
5097
5098                    err = mOMXNode->getParameter(
5099                            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
5100                            &params, sizeof(params));
5101                    if (err != OK) {
5102                        return err;
5103                    }
5104
5105                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AC3);
5106                    notify->setInt32("channel-count", params.nChannels);
5107                    notify->setInt32("sample-rate", params.nSampleRate);
5108                    break;
5109                }
5110
5111                case OMX_AUDIO_CodingAndroidEAC3:
5112                {
5113                    OMX_AUDIO_PARAM_ANDROID_EAC3TYPE params;
5114                    InitOMXParams(&params);
5115                    params.nPortIndex = portIndex;
5116
5117                    err = mOMXNode->getParameter(
5118                            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
5119                            &params, sizeof(params));
5120                    if (err != OK) {
5121                        return err;
5122                    }
5123
5124                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_EAC3);
5125                    notify->setInt32("channel-count", params.nChannels);
5126                    notify->setInt32("sample-rate", params.nSampleRate);
5127                    break;
5128                }
5129
5130                case OMX_AUDIO_CodingAndroidOPUS:
5131                {
5132                    OMX_AUDIO_PARAM_ANDROID_OPUSTYPE params;
5133                    InitOMXParams(&params);
5134                    params.nPortIndex = portIndex;
5135
5136                    err = mOMXNode->getParameter(
5137                            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus,
5138                            &params, sizeof(params));
5139                    if (err != OK) {
5140                        return err;
5141                    }
5142
5143                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_OPUS);
5144                    notify->setInt32("channel-count", params.nChannels);
5145                    notify->setInt32("sample-rate", params.nSampleRate);
5146                    break;
5147                }
5148
5149                case OMX_AUDIO_CodingG711:
5150                {
5151                    OMX_AUDIO_PARAM_PCMMODETYPE params;
5152                    InitOMXParams(&params);
5153                    params.nPortIndex = portIndex;
5154
5155                    err = mOMXNode->getParameter(
5156                            (OMX_INDEXTYPE)OMX_IndexParamAudioPcm, &params, sizeof(params));
5157                    if (err != OK) {
5158                        return err;
5159                    }
5160
5161                    const char *mime = NULL;
5162                    if (params.ePCMMode == OMX_AUDIO_PCMModeMULaw) {
5163                        mime = MEDIA_MIMETYPE_AUDIO_G711_MLAW;
5164                    } else if (params.ePCMMode == OMX_AUDIO_PCMModeALaw) {
5165                        mime = MEDIA_MIMETYPE_AUDIO_G711_ALAW;
5166                    } else { // params.ePCMMode == OMX_AUDIO_PCMModeLinear
5167                        mime = MEDIA_MIMETYPE_AUDIO_RAW;
5168                    }
5169                    notify->setString("mime", mime);
5170                    notify->setInt32("channel-count", params.nChannels);
5171                    notify->setInt32("sample-rate", params.nSamplingRate);
5172                    notify->setInt32("pcm-encoding", kAudioEncodingPcm16bit);
5173                    break;
5174                }
5175
5176                case OMX_AUDIO_CodingGSMFR:
5177                {
5178                    OMX_AUDIO_PARAM_PCMMODETYPE params;
5179                    InitOMXParams(&params);
5180                    params.nPortIndex = portIndex;
5181
5182                    err = mOMXNode->getParameter(
5183                                OMX_IndexParamAudioPcm, &params, sizeof(params));
5184                    if (err != OK) {
5185                        return err;
5186                    }
5187
5188                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MSGSM);
5189                    notify->setInt32("channel-count", params.nChannels);
5190                    notify->setInt32("sample-rate", params.nSamplingRate);
5191                    break;
5192                }
5193
5194                default:
5195                    ALOGE("Unsupported audio coding: %s(%d)\n",
5196                            asString(audioDef->eEncoding), audioDef->eEncoding);
5197                    return BAD_TYPE;
5198            }
5199            break;
5200        }
5201
5202        default:
5203            ALOGE("Unsupported domain: %s(%d)", asString(def.eDomain), def.eDomain);
5204            return BAD_TYPE;
5205    }
5206
5207    return getVendorParameters(portIndex, notify);
5208}
5209
5210void ACodec::onDataSpaceChanged(android_dataspace dataSpace, const ColorAspects &aspects) {
5211    // aspects are normally communicated in ColorAspects
5212    int32_t range, standard, transfer;
5213    convertCodecColorAspectsToPlatformAspects(aspects, &range, &standard, &transfer);
5214
5215    // if some aspects are unspecified, use dataspace fields
5216    if (range != 0) {
5217        range = (dataSpace & HAL_DATASPACE_RANGE_MASK) >> HAL_DATASPACE_RANGE_SHIFT;
5218    }
5219    if (standard != 0) {
5220        standard = (dataSpace & HAL_DATASPACE_STANDARD_MASK) >> HAL_DATASPACE_STANDARD_SHIFT;
5221    }
5222    if (transfer != 0) {
5223        transfer = (dataSpace & HAL_DATASPACE_TRANSFER_MASK) >> HAL_DATASPACE_TRANSFER_SHIFT;
5224    }
5225
5226    mOutputFormat = mOutputFormat->dup(); // trigger an output format changed event
5227    if (range != 0) {
5228        mOutputFormat->setInt32("color-range", range);
5229    }
5230    if (standard != 0) {
5231        mOutputFormat->setInt32("color-standard", standard);
5232    }
5233    if (transfer != 0) {
5234        mOutputFormat->setInt32("color-transfer", transfer);
5235    }
5236
5237    ALOGD("dataspace changed to %#x (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) "
5238          "(R:%d(%s), S:%d(%s), T:%d(%s))",
5239            dataSpace,
5240            aspects.mRange, asString(aspects.mRange),
5241            aspects.mPrimaries, asString(aspects.mPrimaries),
5242            aspects.mMatrixCoeffs, asString(aspects.mMatrixCoeffs),
5243            aspects.mTransfer, asString(aspects.mTransfer),
5244            range, asString((ColorRange)range),
5245            standard, asString((ColorStandard)standard),
5246            transfer, asString((ColorTransfer)transfer));
5247}
5248
5249void ACodec::onOutputFormatChanged(sp<const AMessage> expectedFormat) {
5250    // store new output format, at the same time mark that this is no longer the first frame
5251    mOutputFormat = mBaseOutputFormat->dup();
5252
5253    if (getPortFormat(kPortIndexOutput, mOutputFormat) != OK) {
5254        ALOGE("[%s] Failed to get port format to send format change", mComponentName.c_str());
5255        return;
5256    }
5257
5258    if (expectedFormat != NULL) {
5259        sp<const AMessage> changes = expectedFormat->changesFrom(mOutputFormat);
5260        sp<const AMessage> to = mOutputFormat->changesFrom(expectedFormat);
5261        if (changes->countEntries() != 0 || to->countEntries() != 0) {
5262            ALOGW("[%s] BAD CODEC: Output format changed unexpectedly from (diff) %s to (diff) %s",
5263                    mComponentName.c_str(),
5264                    changes->debugString(4).c_str(), to->debugString(4).c_str());
5265        }
5266    }
5267
5268    if (!mIsVideo && !mIsEncoder) {
5269        AudioEncoding pcmEncoding = kAudioEncodingPcm16bit;
5270        (void)mConfigFormat->findInt32("pcm-encoding", (int32_t*)&pcmEncoding);
5271        AudioEncoding codecPcmEncoding = kAudioEncodingPcm16bit;
5272        (void)mOutputFormat->findInt32("pcm-encoding", (int32_t*)&pcmEncoding);
5273
5274        mConverter[kPortIndexOutput] = AudioConverter::Create(codecPcmEncoding, pcmEncoding);
5275        if (mConverter[kPortIndexOutput] != NULL) {
5276            mOutputFormat->setInt32("pcm-encoding", pcmEncoding);
5277        }
5278    }
5279
5280    if (mTunneled) {
5281        sendFormatChange();
5282    }
5283}
5284
5285void ACodec::sendFormatChange() {
5286    AString mime;
5287    CHECK(mOutputFormat->findString("mime", &mime));
5288
5289    if (mime == MEDIA_MIMETYPE_AUDIO_RAW && (mEncoderDelay || mEncoderPadding)) {
5290        int32_t channelCount, sampleRate;
5291        CHECK(mOutputFormat->findInt32("channel-count", &channelCount));
5292        CHECK(mOutputFormat->findInt32("sample-rate", &sampleRate));
5293        if (mSampleRate != 0 && sampleRate != 0) {
5294            mEncoderDelay = mEncoderDelay * sampleRate / mSampleRate;
5295            mEncoderPadding = mEncoderPadding * sampleRate / mSampleRate;
5296            mSampleRate = sampleRate;
5297        }
5298        if (mSkipCutBuffer != NULL) {
5299            size_t prevbufsize = mSkipCutBuffer->size();
5300            if (prevbufsize != 0) {
5301                ALOGW("Replacing SkipCutBuffer holding %zu bytes", prevbufsize);
5302            }
5303        }
5304        mSkipCutBuffer = new SkipCutBuffer(mEncoderDelay, mEncoderPadding, channelCount);
5305    }
5306
5307    // mLastOutputFormat is not used when tunneled; doing this just to stay consistent
5308    mLastOutputFormat = mOutputFormat;
5309}
5310
5311void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) {
5312    ALOGE("signalError(omxError %#x, internalError %d)", error, internalError);
5313
5314    if (internalError == UNKNOWN_ERROR) { // find better error code
5315        const status_t omxStatus = statusFromOMXError(error);
5316        if (omxStatus != 0) {
5317            internalError = omxStatus;
5318        } else {
5319            ALOGW("Invalid OMX error %#x", error);
5320        }
5321    }
5322
5323    mFatalError = true;
5324    mCallback->onError(internalError, ACTION_CODE_FATAL);
5325}
5326
5327status_t ACodec::requestIDRFrame() {
5328    if (!mIsEncoder) {
5329        return ERROR_UNSUPPORTED;
5330    }
5331
5332    OMX_CONFIG_INTRAREFRESHVOPTYPE params;
5333    InitOMXParams(&params);
5334
5335    params.nPortIndex = kPortIndexOutput;
5336    params.IntraRefreshVOP = OMX_TRUE;
5337
5338    return mOMXNode->setConfig(
5339            OMX_IndexConfigVideoIntraVOPRefresh,
5340            &params,
5341            sizeof(params));
5342}
5343
5344////////////////////////////////////////////////////////////////////////////////
5345
5346ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
5347    : AState(parentState),
5348      mCodec(codec) {
5349}
5350
5351ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(
5352        OMX_U32 /* portIndex */) {
5353    return KEEP_BUFFERS;
5354}
5355
5356void ACodec::BaseState::stateExited() {
5357    ++mCodec->mStateGeneration;
5358}
5359
5360bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) {
5361    switch (msg->what()) {
5362        case kWhatInputBufferFilled:
5363        {
5364            onInputBufferFilled(msg);
5365            break;
5366        }
5367
5368        case kWhatOutputBufferDrained:
5369        {
5370            onOu