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