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