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