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