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