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