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