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