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