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