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