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