ACodec.cpp revision 5207ffe7a35148a1e4ea188cf2224fb230a92a0e
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    if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
3697        h264type.nSliceHeaderSpacing = 0;
3698        h264type.bUseHadamard = OMX_TRUE;
3699        h264type.nRefFrames = 1;
3700        h264type.nBFrames = 0;
3701        h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
3702        if (h264type.nPFrames == 0) {
3703            h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
3704        }
3705        h264type.nRefIdx10ActiveMinus1 = 0;
3706        h264type.nRefIdx11ActiveMinus1 = 0;
3707        h264type.bEntropyCodingCABAC = OMX_FALSE;
3708        h264type.bWeightedPPrediction = OMX_FALSE;
3709        h264type.bconstIpred = OMX_FALSE;
3710        h264type.bDirect8x8Inference = OMX_FALSE;
3711        h264type.bDirectSpatialTemporal = OMX_FALSE;
3712        h264type.nCabacInitIdc = 0;
3713    } else if (h264type.eProfile == OMX_VIDEO_AVCProfileMain ||
3714            h264type.eProfile == OMX_VIDEO_AVCProfileHigh) {
3715        h264type.nSliceHeaderSpacing = 0;
3716        h264type.bUseHadamard = OMX_TRUE;
3717        h264type.nRefFrames = 2;
3718        h264type.nBFrames = 1;
3719        h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
3720        h264type.nAllowedPictureTypes =
3721            OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP | OMX_VIDEO_PictureTypeB;
3722        h264type.nRefIdx10ActiveMinus1 = 0;
3723        h264type.nRefIdx11ActiveMinus1 = 0;
3724        h264type.bEntropyCodingCABAC = OMX_TRUE;
3725        h264type.bWeightedPPrediction = OMX_TRUE;
3726        h264type.bconstIpred = OMX_TRUE;
3727        h264type.bDirect8x8Inference = OMX_TRUE;
3728        h264type.bDirectSpatialTemporal = OMX_TRUE;
3729        h264type.nCabacInitIdc = 1;
3730    }
3731
3732    if (h264type.nBFrames != 0) {
3733        h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
3734    }
3735
3736    h264type.bEnableUEP = OMX_FALSE;
3737    h264type.bEnableFMO = OMX_FALSE;
3738    h264type.bEnableASO = OMX_FALSE;
3739    h264type.bEnableRS = OMX_FALSE;
3740    h264type.bFrameMBsOnly = OMX_TRUE;
3741    h264type.bMBAFF = OMX_FALSE;
3742    h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
3743
3744    err = mOMX->setParameter(
3745            mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
3746
3747    if (err != OK) {
3748        return err;
3749    }
3750
3751    return configureBitrate(bitrate, bitrateMode);
3752}
3753
3754status_t ACodec::setupHEVCEncoderParameters(const sp<AMessage> &msg) {
3755    int32_t bitrate, iFrameInterval;
3756    if (!msg->findInt32("bitrate", &bitrate)
3757            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
3758        return INVALID_OPERATION;
3759    }
3760
3761    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
3762
3763    float frameRate;
3764    if (!msg->findFloat("frame-rate", &frameRate)) {
3765        int32_t tmp;
3766        if (!msg->findInt32("frame-rate", &tmp)) {
3767            return INVALID_OPERATION;
3768        }
3769        frameRate = (float)tmp;
3770    }
3771
3772    OMX_VIDEO_PARAM_HEVCTYPE hevcType;
3773    InitOMXParams(&hevcType);
3774    hevcType.nPortIndex = kPortIndexOutput;
3775
3776    status_t err = OK;
3777    err = mOMX->getParameter(
3778            mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
3779    if (err != OK) {
3780        return err;
3781    }
3782
3783    int32_t profile;
3784    if (msg->findInt32("profile", &profile)) {
3785        int32_t level;
3786        if (!msg->findInt32("level", &level)) {
3787            return INVALID_OPERATION;
3788        }
3789
3790        err = verifySupportForProfileAndLevel(profile, level);
3791        if (err != OK) {
3792            return err;
3793        }
3794
3795        hevcType.eProfile = static_cast<OMX_VIDEO_HEVCPROFILETYPE>(profile);
3796        hevcType.eLevel = static_cast<OMX_VIDEO_HEVCLEVELTYPE>(level);
3797    }
3798    // TODO: finer control?
3799    hevcType.nKeyFrameInterval = setPFramesSpacing(iFrameInterval, frameRate);
3800
3801    err = mOMX->setParameter(
3802            mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
3803    if (err != OK) {
3804        return err;
3805    }
3806
3807    return configureBitrate(bitrate, bitrateMode);
3808}
3809
3810status_t ACodec::setupVPXEncoderParameters(const sp<AMessage> &msg) {
3811    int32_t bitrate;
3812    int32_t iFrameInterval = 0;
3813    size_t tsLayers = 0;
3814    OMX_VIDEO_ANDROID_VPXTEMPORALLAYERPATTERNTYPE pattern =
3815        OMX_VIDEO_VPXTemporalLayerPatternNone;
3816    static const uint32_t kVp8LayerRateAlloction
3817        [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS]
3818        [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS] = {
3819        {100, 100, 100},  // 1 layer
3820        { 60, 100, 100},  // 2 layers {60%, 40%}
3821        { 40,  60, 100},  // 3 layers {40%, 20%, 40%}
3822    };
3823    if (!msg->findInt32("bitrate", &bitrate)) {
3824        return INVALID_OPERATION;
3825    }
3826    msg->findInt32("i-frame-interval", &iFrameInterval);
3827
3828    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
3829
3830    float frameRate;
3831    if (!msg->findFloat("frame-rate", &frameRate)) {
3832        int32_t tmp;
3833        if (!msg->findInt32("frame-rate", &tmp)) {
3834            return INVALID_OPERATION;
3835        }
3836        frameRate = (float)tmp;
3837    }
3838
3839    AString tsSchema;
3840    if (msg->findString("ts-schema", &tsSchema)) {
3841        if (tsSchema == "webrtc.vp8.1-layer") {
3842            pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
3843            tsLayers = 1;
3844        } else if (tsSchema == "webrtc.vp8.2-layer") {
3845            pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
3846            tsLayers = 2;
3847        } else if (tsSchema == "webrtc.vp8.3-layer") {
3848            pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
3849            tsLayers = 3;
3850        } else {
3851            ALOGW("Unsupported ts-schema [%s]", tsSchema.c_str());
3852        }
3853    }
3854
3855    OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type;
3856    InitOMXParams(&vp8type);
3857    vp8type.nPortIndex = kPortIndexOutput;
3858    status_t err = mOMX->getParameter(
3859            mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
3860            &vp8type, sizeof(vp8type));
3861
3862    if (err == OK) {
3863        if (iFrameInterval > 0) {
3864            vp8type.nKeyFrameInterval = setPFramesSpacing(iFrameInterval, frameRate);
3865        }
3866        vp8type.eTemporalPattern = pattern;
3867        vp8type.nTemporalLayerCount = tsLayers;
3868        if (tsLayers > 0) {
3869            for (size_t i = 0; i < OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS; i++) {
3870                vp8type.nTemporalLayerBitrateRatio[i] =
3871                    kVp8LayerRateAlloction[tsLayers - 1][i];
3872            }
3873        }
3874        if (bitrateMode == OMX_Video_ControlRateConstant) {
3875            vp8type.nMinQuantizer = 2;
3876            vp8type.nMaxQuantizer = 63;
3877        }
3878
3879        err = mOMX->setParameter(
3880                mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
3881                &vp8type, sizeof(vp8type));
3882        if (err != OK) {
3883            ALOGW("Extended VP8 parameters set failed: %d", err);
3884        }
3885    }
3886
3887    return configureBitrate(bitrate, bitrateMode);
3888}
3889
3890status_t ACodec::verifySupportForProfileAndLevel(
3891        int32_t profile, int32_t level) {
3892    OMX_VIDEO_PARAM_PROFILELEVELTYPE params;
3893    InitOMXParams(&params);
3894    params.nPortIndex = kPortIndexOutput;
3895
3896    for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
3897        params.nProfileIndex = index;
3898        status_t err = mOMX->getParameter(
3899                mNode,
3900                OMX_IndexParamVideoProfileLevelQuerySupported,
3901                &params,
3902                sizeof(params));
3903
3904        if (err != OK) {
3905            return err;
3906        }
3907
3908        int32_t supportedProfile = static_cast<int32_t>(params.eProfile);
3909        int32_t supportedLevel = static_cast<int32_t>(params.eLevel);
3910
3911        if (profile == supportedProfile && level <= supportedLevel) {
3912            return OK;
3913        }
3914
3915        if (index == kMaxIndicesToCheck) {
3916            ALOGW("[%s] stopping checking profiles after %u: %x/%x",
3917                    mComponentName.c_str(), index,
3918                    params.eProfile, params.eLevel);
3919        }
3920    }
3921    return ERROR_UNSUPPORTED;
3922}
3923
3924status_t ACodec::configureBitrate(
3925        int32_t bitrate, OMX_VIDEO_CONTROLRATETYPE bitrateMode) {
3926    OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
3927    InitOMXParams(&bitrateType);
3928    bitrateType.nPortIndex = kPortIndexOutput;
3929
3930    status_t err = mOMX->getParameter(
3931            mNode, OMX_IndexParamVideoBitrate,
3932            &bitrateType, sizeof(bitrateType));
3933
3934    if (err != OK) {
3935        return err;
3936    }
3937
3938    bitrateType.eControlRate = bitrateMode;
3939    bitrateType.nTargetBitrate = bitrate;
3940
3941    return mOMX->setParameter(
3942            mNode, OMX_IndexParamVideoBitrate,
3943            &bitrateType, sizeof(bitrateType));
3944}
3945
3946status_t ACodec::setupErrorCorrectionParameters() {
3947    OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
3948    InitOMXParams(&errorCorrectionType);
3949    errorCorrectionType.nPortIndex = kPortIndexOutput;
3950
3951    status_t err = mOMX->getParameter(
3952            mNode, OMX_IndexParamVideoErrorCorrection,
3953            &errorCorrectionType, sizeof(errorCorrectionType));
3954
3955    if (err != OK) {
3956        return OK;  // Optional feature. Ignore this failure
3957    }
3958
3959    errorCorrectionType.bEnableHEC = OMX_FALSE;
3960    errorCorrectionType.bEnableResync = OMX_TRUE;
3961    errorCorrectionType.nResynchMarkerSpacing = 256;
3962    errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
3963    errorCorrectionType.bEnableRVLC = OMX_FALSE;
3964
3965    return mOMX->setParameter(
3966            mNode, OMX_IndexParamVideoErrorCorrection,
3967            &errorCorrectionType, sizeof(errorCorrectionType));
3968}
3969
3970status_t ACodec::setVideoFormatOnPort(
3971        OMX_U32 portIndex,
3972        int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat,
3973        float frameRate) {
3974    OMX_PARAM_PORTDEFINITIONTYPE def;
3975    InitOMXParams(&def);
3976    def.nPortIndex = portIndex;
3977
3978    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
3979
3980    status_t err = mOMX->getParameter(
3981            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
3982    if (err != OK) {
3983        return err;
3984    }
3985
3986    if (portIndex == kPortIndexInput) {
3987        // XXX Need a (much) better heuristic to compute input buffer sizes.
3988        const size_t X = 64 * 1024;
3989        if (def.nBufferSize < X) {
3990            def.nBufferSize = X;
3991        }
3992    }
3993
3994    if (def.eDomain != OMX_PortDomainVideo) {
3995        ALOGE("expected video port, got %s(%d)", asString(def.eDomain), def.eDomain);
3996        return FAILED_TRANSACTION;
3997    }
3998
3999    video_def->nFrameWidth = width;
4000    video_def->nFrameHeight = height;
4001
4002    if (portIndex == kPortIndexInput) {
4003        video_def->eCompressionFormat = compressionFormat;
4004        video_def->eColorFormat = OMX_COLOR_FormatUnused;
4005        if (frameRate >= 0) {
4006            video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f);
4007        }
4008    }
4009
4010    err = mOMX->setParameter(
4011            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
4012
4013    return err;
4014}
4015
4016status_t ACodec::initNativeWindow() {
4017    if (mNativeWindow != NULL) {
4018        return mOMX->enableNativeBuffers(mNode, kPortIndexOutput, OMX_TRUE /* graphic */, OMX_TRUE);
4019    }
4020
4021    mOMX->enableNativeBuffers(mNode, kPortIndexOutput, OMX_TRUE /* graphic */, OMX_FALSE);
4022    return OK;
4023}
4024
4025size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const {
4026    size_t n = 0;
4027
4028    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
4029        const BufferInfo &info = mBuffers[portIndex].itemAt(i);
4030
4031        if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) {
4032            ++n;
4033        }
4034    }
4035
4036    return n;
4037}
4038
4039size_t ACodec::countBuffersOwnedByNativeWindow() const {
4040    size_t n = 0;
4041
4042    for (size_t i = 0; i < mBuffers[kPortIndexOutput].size(); ++i) {
4043        const BufferInfo &info = mBuffers[kPortIndexOutput].itemAt(i);
4044
4045        if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
4046            ++n;
4047        }
4048    }
4049
4050    return n;
4051}
4052
4053void ACodec::waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs() {
4054    if (mNativeWindow == NULL) {
4055        return;
4056    }
4057
4058    while (countBuffersOwnedByNativeWindow() > mNumUndequeuedBuffers
4059            && dequeueBufferFromNativeWindow() != NULL) {
4060        // these buffers will be submitted as regular buffers; account for this
4061        if (storingMetadataInDecodedBuffers() && mMetadataBuffersToSubmit > 0) {
4062            --mMetadataBuffersToSubmit;
4063        }
4064    }
4065}
4066
4067bool ACodec::allYourBuffersAreBelongToUs(
4068        OMX_U32 portIndex) {
4069    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
4070        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
4071
4072        if (info->mStatus != BufferInfo::OWNED_BY_US
4073                && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
4074            ALOGV("[%s] Buffer %u on port %u still has status %d",
4075                    mComponentName.c_str(),
4076                    info->mBufferID, portIndex, info->mStatus);
4077            return false;
4078        }
4079    }
4080
4081    return true;
4082}
4083
4084bool ACodec::allYourBuffersAreBelongToUs() {
4085    return allYourBuffersAreBelongToUs(kPortIndexInput)
4086        && allYourBuffersAreBelongToUs(kPortIndexOutput);
4087}
4088
4089void ACodec::deferMessage(const sp<AMessage> &msg) {
4090    mDeferredQueue.push_back(msg);
4091}
4092
4093void ACodec::processDeferredMessages() {
4094    List<sp<AMessage> > queue = mDeferredQueue;
4095    mDeferredQueue.clear();
4096
4097    List<sp<AMessage> >::iterator it = queue.begin();
4098    while (it != queue.end()) {
4099        onMessageReceived(*it++);
4100    }
4101}
4102
4103// static
4104bool ACodec::describeDefaultColorFormat(DescribeColorFormat2Params &params) {
4105    MediaImage2 &image = params.sMediaImage;
4106    memset(&image, 0, sizeof(image));
4107
4108    image.mType = MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN;
4109    image.mNumPlanes = 0;
4110
4111    const OMX_COLOR_FORMATTYPE fmt = params.eColorFormat;
4112    image.mWidth = params.nFrameWidth;
4113    image.mHeight = params.nFrameHeight;
4114
4115    // only supporting YUV420
4116    if (fmt != OMX_COLOR_FormatYUV420Planar &&
4117        fmt != OMX_COLOR_FormatYUV420PackedPlanar &&
4118        fmt != OMX_COLOR_FormatYUV420SemiPlanar &&
4119        fmt != OMX_COLOR_FormatYUV420PackedSemiPlanar &&
4120        fmt != (OMX_COLOR_FORMATTYPE)HAL_PIXEL_FORMAT_YV12) {
4121        ALOGW("do not know color format 0x%x = %d", fmt, fmt);
4122        return false;
4123    }
4124
4125    // TEMPORARY FIX for some vendors that advertise sliceHeight as 0
4126    if (params.nStride != 0 && params.nSliceHeight == 0) {
4127        ALOGW("using sliceHeight=%u instead of what codec advertised (=0)",
4128                params.nFrameHeight);
4129        params.nSliceHeight = params.nFrameHeight;
4130    }
4131
4132    // we need stride and slice-height to be non-zero and sensible. These values were chosen to
4133    // prevent integer overflows further down the line, and do not indicate support for
4134    // 32kx32k video.
4135    if (params.nStride == 0 || params.nSliceHeight == 0
4136            || params.nStride > 32768 || params.nSliceHeight > 32768) {
4137        ALOGW("cannot describe color format 0x%x = %d with stride=%u and sliceHeight=%u",
4138                fmt, fmt, params.nStride, params.nSliceHeight);
4139        return false;
4140    }
4141
4142    // set-up YUV format
4143    image.mType = MediaImage2::MEDIA_IMAGE_TYPE_YUV;
4144    image.mNumPlanes = 3;
4145    image.mBitDepth = 8;
4146    image.mBitDepthAllocated = 8;
4147    image.mPlane[image.Y].mOffset = 0;
4148    image.mPlane[image.Y].mColInc = 1;
4149    image.mPlane[image.Y].mRowInc = params.nStride;
4150    image.mPlane[image.Y].mHorizSubsampling = 1;
4151    image.mPlane[image.Y].mVertSubsampling = 1;
4152
4153    switch ((int)fmt) {
4154        case HAL_PIXEL_FORMAT_YV12:
4155            if (params.bUsingNativeBuffers) {
4156                size_t ystride = align(params.nStride, 16);
4157                size_t cstride = align(params.nStride / 2, 16);
4158                image.mPlane[image.Y].mRowInc = ystride;
4159
4160                image.mPlane[image.V].mOffset = ystride * params.nSliceHeight;
4161                image.mPlane[image.V].mColInc = 1;
4162                image.mPlane[image.V].mRowInc = cstride;
4163                image.mPlane[image.V].mHorizSubsampling = 2;
4164                image.mPlane[image.V].mVertSubsampling = 2;
4165
4166                image.mPlane[image.U].mOffset = image.mPlane[image.V].mOffset
4167                        + (cstride * params.nSliceHeight / 2);
4168                image.mPlane[image.U].mColInc = 1;
4169                image.mPlane[image.U].mRowInc = cstride;
4170                image.mPlane[image.U].mHorizSubsampling = 2;
4171                image.mPlane[image.U].mVertSubsampling = 2;
4172                break;
4173            } else {
4174                // fall through as YV12 is used for YUV420Planar by some codecs
4175            }
4176
4177        case OMX_COLOR_FormatYUV420Planar:
4178        case OMX_COLOR_FormatYUV420PackedPlanar:
4179            image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight;
4180            image.mPlane[image.U].mColInc = 1;
4181            image.mPlane[image.U].mRowInc = params.nStride / 2;
4182            image.mPlane[image.U].mHorizSubsampling = 2;
4183            image.mPlane[image.U].mVertSubsampling = 2;
4184
4185            image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset
4186                    + (params.nStride * params.nSliceHeight / 4);
4187            image.mPlane[image.V].mColInc = 1;
4188            image.mPlane[image.V].mRowInc = params.nStride / 2;
4189            image.mPlane[image.V].mHorizSubsampling = 2;
4190            image.mPlane[image.V].mVertSubsampling = 2;
4191            break;
4192
4193        case OMX_COLOR_FormatYUV420SemiPlanar:
4194            // FIXME: NV21 for sw-encoder, NV12 for decoder and hw-encoder
4195        case OMX_COLOR_FormatYUV420PackedSemiPlanar:
4196            // NV12
4197            image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight;
4198            image.mPlane[image.U].mColInc = 2;
4199            image.mPlane[image.U].mRowInc = params.nStride;
4200            image.mPlane[image.U].mHorizSubsampling = 2;
4201            image.mPlane[image.U].mVertSubsampling = 2;
4202
4203            image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset + 1;
4204            image.mPlane[image.V].mColInc = 2;
4205            image.mPlane[image.V].mRowInc = params.nStride;
4206            image.mPlane[image.V].mHorizSubsampling = 2;
4207            image.mPlane[image.V].mVertSubsampling = 2;
4208            break;
4209
4210        default:
4211            TRESPASS();
4212    }
4213    return true;
4214}
4215
4216// static
4217bool ACodec::describeColorFormat(
4218        const sp<IOMX> &omx, IOMX::node_id node,
4219        DescribeColorFormat2Params &describeParams)
4220{
4221    OMX_INDEXTYPE describeColorFormatIndex;
4222    if (omx->getExtensionIndex(
4223            node, "OMX.google.android.index.describeColorFormat",
4224            &describeColorFormatIndex) == OK) {
4225        DescribeColorFormatParams describeParamsV1(describeParams);
4226        if (omx->getParameter(
4227                node, describeColorFormatIndex,
4228                &describeParamsV1, sizeof(describeParamsV1)) == OK) {
4229            describeParams.initFromV1(describeParamsV1);
4230            return describeParams.sMediaImage.mType != MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN;
4231        }
4232    } else if (omx->getExtensionIndex(
4233            node, "OMX.google.android.index.describeColorFormat2", &describeColorFormatIndex) == OK
4234               && omx->getParameter(
4235            node, describeColorFormatIndex, &describeParams, sizeof(describeParams)) == OK) {
4236        return describeParams.sMediaImage.mType != MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN;
4237    }
4238
4239    return describeDefaultColorFormat(describeParams);
4240}
4241
4242// static
4243bool ACodec::isFlexibleColorFormat(
4244         const sp<IOMX> &omx, IOMX::node_id node,
4245         uint32_t colorFormat, bool usingNativeBuffers, OMX_U32 *flexibleEquivalent) {
4246    DescribeColorFormat2Params describeParams;
4247    InitOMXParams(&describeParams);
4248    describeParams.eColorFormat = (OMX_COLOR_FORMATTYPE)colorFormat;
4249    // reasonable dummy values
4250    describeParams.nFrameWidth = 128;
4251    describeParams.nFrameHeight = 128;
4252    describeParams.nStride = 128;
4253    describeParams.nSliceHeight = 128;
4254    describeParams.bUsingNativeBuffers = (OMX_BOOL)usingNativeBuffers;
4255
4256    CHECK(flexibleEquivalent != NULL);
4257
4258    if (!describeColorFormat(omx, node, describeParams)) {
4259        return false;
4260    }
4261
4262    const MediaImage2 &img = describeParams.sMediaImage;
4263    if (img.mType == MediaImage2::MEDIA_IMAGE_TYPE_YUV) {
4264        if (img.mNumPlanes != 3
4265                || img.mPlane[img.Y].mHorizSubsampling != 1
4266                || img.mPlane[img.Y].mVertSubsampling != 1) {
4267            return false;
4268        }
4269
4270        // YUV 420
4271        if (img.mPlane[img.U].mHorizSubsampling == 2
4272                && img.mPlane[img.U].mVertSubsampling == 2
4273                && img.mPlane[img.V].mHorizSubsampling == 2
4274                && img.mPlane[img.V].mVertSubsampling == 2) {
4275            // possible flexible YUV420 format
4276            if (img.mBitDepth <= 8) {
4277               *flexibleEquivalent = OMX_COLOR_FormatYUV420Flexible;
4278               return true;
4279            }
4280        }
4281    }
4282    return false;
4283}
4284
4285status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> &notify) {
4286    const char *niceIndex = portIndex == kPortIndexInput ? "input" : "output";
4287    OMX_PARAM_PORTDEFINITIONTYPE def;
4288    InitOMXParams(&def);
4289    def.nPortIndex = portIndex;
4290
4291    status_t err = mOMX->getParameter(mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
4292    if (err != OK) {
4293        return err;
4294    }
4295
4296    if (def.eDir != (portIndex == kPortIndexOutput ? OMX_DirOutput : OMX_DirInput)) {
4297        ALOGE("unexpected dir: %s(%d) on %s port", asString(def.eDir), def.eDir, niceIndex);
4298        return BAD_VALUE;
4299    }
4300
4301    switch (def.eDomain) {
4302        case OMX_PortDomainVideo:
4303        {
4304            OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
4305            switch ((int)videoDef->eCompressionFormat) {
4306                case OMX_VIDEO_CodingUnused:
4307                {
4308                    CHECK(mIsEncoder ^ (portIndex == kPortIndexOutput));
4309                    notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW);
4310
4311                    notify->setInt32("stride", videoDef->nStride);
4312                    notify->setInt32("slice-height", videoDef->nSliceHeight);
4313                    notify->setInt32("color-format", videoDef->eColorFormat);
4314
4315                    if (mNativeWindow == NULL) {
4316                        DescribeColorFormat2Params describeParams;
4317                        InitOMXParams(&describeParams);
4318                        describeParams.eColorFormat = videoDef->eColorFormat;
4319                        describeParams.nFrameWidth = videoDef->nFrameWidth;
4320                        describeParams.nFrameHeight = videoDef->nFrameHeight;
4321                        describeParams.nStride = videoDef->nStride;
4322                        describeParams.nSliceHeight = videoDef->nSliceHeight;
4323                        describeParams.bUsingNativeBuffers = OMX_FALSE;
4324
4325                        if (describeColorFormat(mOMX, mNode, describeParams)) {
4326                            notify->setBuffer(
4327                                    "image-data",
4328                                    ABuffer::CreateAsCopy(
4329                                            &describeParams.sMediaImage,
4330                                            sizeof(describeParams.sMediaImage)));
4331
4332                            MediaImage2 &img = describeParams.sMediaImage;
4333                            MediaImage2::PlaneInfo *plane = img.mPlane;
4334                            ALOGV("[%s] MediaImage { F(%ux%u) @%u+%d+%d @%u+%d+%d @%u+%d+%d }",
4335                                    mComponentName.c_str(), img.mWidth, img.mHeight,
4336                                    plane[0].mOffset, plane[0].mColInc, plane[0].mRowInc,
4337                                    plane[1].mOffset, plane[1].mColInc, plane[1].mRowInc,
4338                                    plane[2].mOffset, plane[2].mColInc, plane[2].mRowInc);
4339                        }
4340                    }
4341
4342                    if (portIndex != kPortIndexOutput) {
4343                        // TODO: also get input crop
4344                        break;
4345                    }
4346
4347                    (void)getColorAspects(portIndex, notify);
4348
4349                    OMX_CONFIG_RECTTYPE rect;
4350                    InitOMXParams(&rect);
4351                    rect.nPortIndex = portIndex;
4352
4353                    if (mOMX->getConfig(
4354                                mNode,
4355                                (portIndex == kPortIndexOutput ?
4356                                        OMX_IndexConfigCommonOutputCrop :
4357                                        OMX_IndexConfigCommonInputCrop),
4358                                &rect, sizeof(rect)) != OK) {
4359                        rect.nLeft = 0;
4360                        rect.nTop = 0;
4361                        rect.nWidth = videoDef->nFrameWidth;
4362                        rect.nHeight = videoDef->nFrameHeight;
4363                    }
4364
4365                    if (rect.nLeft < 0 ||
4366                        rect.nTop < 0 ||
4367                        rect.nLeft + rect.nWidth > videoDef->nFrameWidth ||
4368                        rect.nTop + rect.nHeight > videoDef->nFrameHeight) {
4369                        ALOGE("Wrong cropped rect (%d, %d) - (%u, %u) vs. frame (%u, %u)",
4370                                rect.nLeft, rect.nTop,
4371                                rect.nLeft + rect.nWidth, rect.nTop + rect.nHeight,
4372                                videoDef->nFrameWidth, videoDef->nFrameHeight);
4373                        return BAD_VALUE;
4374                    }
4375
4376                    notify->setRect(
4377                            "crop",
4378                            rect.nLeft,
4379                            rect.nTop,
4380                            rect.nLeft + rect.nWidth - 1,
4381                            rect.nTop + rect.nHeight - 1);
4382
4383                    break;
4384                }
4385
4386                case OMX_VIDEO_CodingVP8:
4387                case OMX_VIDEO_CodingVP9:
4388                {
4389                    OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type;
4390                    InitOMXParams(&vp8type);
4391                    vp8type.nPortIndex = kPortIndexOutput;
4392                    status_t err = mOMX->getParameter(
4393                            mNode,
4394                            (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
4395                            &vp8type,
4396                            sizeof(vp8type));
4397
4398                    if (err == OK) {
4399                        AString tsSchema = "none";
4400                        if (vp8type.eTemporalPattern
4401                                == OMX_VIDEO_VPXTemporalLayerPatternWebRTC) {
4402                            switch (vp8type.nTemporalLayerCount) {
4403                                case 1:
4404                                {
4405                                    tsSchema = "webrtc.vp8.1-layer";
4406                                    break;
4407                                }
4408                                case 2:
4409                                {
4410                                    tsSchema = "webrtc.vp8.2-layer";
4411                                    break;
4412                                }
4413                                case 3:
4414                                {
4415                                    tsSchema = "webrtc.vp8.3-layer";
4416                                    break;
4417                                }
4418                                default:
4419                                {
4420                                    break;
4421                                }
4422                            }
4423                        }
4424                        notify->setString("ts-schema", tsSchema);
4425                    }
4426                    // Fall through to set up mime.
4427                }
4428
4429                default:
4430                {
4431                    if (mIsEncoder ^ (portIndex == kPortIndexOutput)) {
4432                        // should be CodingUnused
4433                        ALOGE("Raw port video compression format is %s(%d)",
4434                                asString(videoDef->eCompressionFormat),
4435                                videoDef->eCompressionFormat);
4436                        return BAD_VALUE;
4437                    }
4438                    AString mime;
4439                    if (GetMimeTypeForVideoCoding(
4440                        videoDef->eCompressionFormat, &mime) != OK) {
4441                        notify->setString("mime", "application/octet-stream");
4442                    } else {
4443                        notify->setString("mime", mime.c_str());
4444                    }
4445                    uint32_t intraRefreshPeriod = 0;
4446                    if (mIsEncoder && getIntraRefreshPeriod(&intraRefreshPeriod) == OK
4447                            && intraRefreshPeriod > 0) {
4448                        notify->setInt32("intra-refresh-period", intraRefreshPeriod);
4449                    }
4450                    break;
4451                }
4452            }
4453            notify->setInt32("width", videoDef->nFrameWidth);
4454            notify->setInt32("height", videoDef->nFrameHeight);
4455            ALOGV("[%s] %s format is %s", mComponentName.c_str(),
4456                    portIndex == kPortIndexInput ? "input" : "output",
4457                    notify->debugString().c_str());
4458
4459            break;
4460        }
4461
4462        case OMX_PortDomainAudio:
4463        {
4464            OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
4465
4466            switch ((int)audioDef->eEncoding) {
4467                case OMX_AUDIO_CodingPCM:
4468                {
4469                    OMX_AUDIO_PARAM_PCMMODETYPE params;
4470                    InitOMXParams(&params);
4471                    params.nPortIndex = portIndex;
4472
4473                    err = mOMX->getParameter(
4474                            mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
4475                    if (err != OK) {
4476                        return err;
4477                    }
4478
4479                    if (params.nChannels <= 0
4480                            || (params.nChannels != 1 && !params.bInterleaved)
4481                            || params.nBitPerSample != 16u
4482                            || params.eNumData != OMX_NumericalDataSigned
4483                            || params.ePCMMode != OMX_AUDIO_PCMModeLinear) {
4484                        ALOGE("unsupported PCM port: %u channels%s, %u-bit, %s(%d), %s(%d) mode ",
4485                                params.nChannels,
4486                                params.bInterleaved ? " interleaved" : "",
4487                                params.nBitPerSample,
4488                                asString(params.eNumData), params.eNumData,
4489                                asString(params.ePCMMode), params.ePCMMode);
4490                        return FAILED_TRANSACTION;
4491                    }
4492
4493                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
4494                    notify->setInt32("channel-count", params.nChannels);
4495                    notify->setInt32("sample-rate", params.nSamplingRate);
4496
4497                    if (mChannelMaskPresent) {
4498                        notify->setInt32("channel-mask", mChannelMask);
4499                    }
4500                    break;
4501                }
4502
4503                case OMX_AUDIO_CodingAAC:
4504                {
4505                    OMX_AUDIO_PARAM_AACPROFILETYPE params;
4506                    InitOMXParams(&params);
4507                    params.nPortIndex = portIndex;
4508
4509                    err = mOMX->getParameter(
4510                            mNode, OMX_IndexParamAudioAac, &params, sizeof(params));
4511                    if (err != OK) {
4512                        return err;
4513                    }
4514
4515                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
4516                    notify->setInt32("channel-count", params.nChannels);
4517                    notify->setInt32("sample-rate", params.nSampleRate);
4518                    break;
4519                }
4520
4521                case OMX_AUDIO_CodingAMR:
4522                {
4523                    OMX_AUDIO_PARAM_AMRTYPE params;
4524                    InitOMXParams(&params);
4525                    params.nPortIndex = portIndex;
4526
4527                    err = mOMX->getParameter(
4528                            mNode, OMX_IndexParamAudioAmr, &params, sizeof(params));
4529                    if (err != OK) {
4530                        return err;
4531                    }
4532
4533                    notify->setInt32("channel-count", 1);
4534                    if (params.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0) {
4535                        notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_WB);
4536                        notify->setInt32("sample-rate", 16000);
4537                    } else {
4538                        notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_NB);
4539                        notify->setInt32("sample-rate", 8000);
4540                    }
4541                    break;
4542                }
4543
4544                case OMX_AUDIO_CodingFLAC:
4545                {
4546                    OMX_AUDIO_PARAM_FLACTYPE params;
4547                    InitOMXParams(&params);
4548                    params.nPortIndex = portIndex;
4549
4550                    err = mOMX->getParameter(
4551                            mNode, OMX_IndexParamAudioFlac, &params, sizeof(params));
4552                    if (err != OK) {
4553                        return err;
4554                    }
4555
4556                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_FLAC);
4557                    notify->setInt32("channel-count", params.nChannels);
4558                    notify->setInt32("sample-rate", params.nSampleRate);
4559                    break;
4560                }
4561
4562                case OMX_AUDIO_CodingMP3:
4563                {
4564                    OMX_AUDIO_PARAM_MP3TYPE params;
4565                    InitOMXParams(&params);
4566                    params.nPortIndex = portIndex;
4567
4568                    err = mOMX->getParameter(
4569                            mNode, OMX_IndexParamAudioMp3, &params, sizeof(params));
4570                    if (err != OK) {
4571                        return err;
4572                    }
4573
4574                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MPEG);
4575                    notify->setInt32("channel-count", params.nChannels);
4576                    notify->setInt32("sample-rate", params.nSampleRate);
4577                    break;
4578                }
4579
4580                case OMX_AUDIO_CodingVORBIS:
4581                {
4582                    OMX_AUDIO_PARAM_VORBISTYPE params;
4583                    InitOMXParams(&params);
4584                    params.nPortIndex = portIndex;
4585
4586                    err = mOMX->getParameter(
4587                            mNode, OMX_IndexParamAudioVorbis, &params, sizeof(params));
4588                    if (err != OK) {
4589                        return err;
4590                    }
4591
4592                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_VORBIS);
4593                    notify->setInt32("channel-count", params.nChannels);
4594                    notify->setInt32("sample-rate", params.nSampleRate);
4595                    break;
4596                }
4597
4598                case OMX_AUDIO_CodingAndroidAC3:
4599                {
4600                    OMX_AUDIO_PARAM_ANDROID_AC3TYPE params;
4601                    InitOMXParams(&params);
4602                    params.nPortIndex = portIndex;
4603
4604                    err = mOMX->getParameter(
4605                            mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
4606                            &params, sizeof(params));
4607                    if (err != OK) {
4608                        return err;
4609                    }
4610
4611                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AC3);
4612                    notify->setInt32("channel-count", params.nChannels);
4613                    notify->setInt32("sample-rate", params.nSampleRate);
4614                    break;
4615                }
4616
4617                case OMX_AUDIO_CodingAndroidEAC3:
4618                {
4619                    OMX_AUDIO_PARAM_ANDROID_EAC3TYPE params;
4620                    InitOMXParams(&params);
4621                    params.nPortIndex = portIndex;
4622
4623                    err = mOMX->getParameter(
4624                            mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
4625                            &params, sizeof(params));
4626                    if (err != OK) {
4627                        return err;
4628                    }
4629
4630                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_EAC3);
4631                    notify->setInt32("channel-count", params.nChannels);
4632                    notify->setInt32("sample-rate", params.nSampleRate);
4633                    break;
4634                }
4635
4636                case OMX_AUDIO_CodingAndroidOPUS:
4637                {
4638                    OMX_AUDIO_PARAM_ANDROID_OPUSTYPE params;
4639                    InitOMXParams(&params);
4640                    params.nPortIndex = portIndex;
4641
4642                    err = mOMX->getParameter(
4643                            mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus,
4644                            &params, sizeof(params));
4645                    if (err != OK) {
4646                        return err;
4647                    }
4648
4649                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_OPUS);
4650                    notify->setInt32("channel-count", params.nChannels);
4651                    notify->setInt32("sample-rate", params.nSampleRate);
4652                    break;
4653                }
4654
4655                case OMX_AUDIO_CodingG711:
4656                {
4657                    OMX_AUDIO_PARAM_PCMMODETYPE params;
4658                    InitOMXParams(&params);
4659                    params.nPortIndex = portIndex;
4660
4661                    err = mOMX->getParameter(
4662                            mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioPcm, &params, sizeof(params));
4663                    if (err != OK) {
4664                        return err;
4665                    }
4666
4667                    const char *mime = NULL;
4668                    if (params.ePCMMode == OMX_AUDIO_PCMModeMULaw) {
4669                        mime = MEDIA_MIMETYPE_AUDIO_G711_MLAW;
4670                    } else if (params.ePCMMode == OMX_AUDIO_PCMModeALaw) {
4671                        mime = MEDIA_MIMETYPE_AUDIO_G711_ALAW;
4672                    } else { // params.ePCMMode == OMX_AUDIO_PCMModeLinear
4673                        mime = MEDIA_MIMETYPE_AUDIO_RAW;
4674                    }
4675                    notify->setString("mime", mime);
4676                    notify->setInt32("channel-count", params.nChannels);
4677                    notify->setInt32("sample-rate", params.nSamplingRate);
4678                    break;
4679                }
4680
4681                case OMX_AUDIO_CodingGSMFR:
4682                {
4683                    OMX_AUDIO_PARAM_PCMMODETYPE params;
4684                    InitOMXParams(&params);
4685                    params.nPortIndex = portIndex;
4686
4687                    err = mOMX->getParameter(
4688                                mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
4689                    if (err != OK) {
4690                        return err;
4691                    }
4692
4693                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MSGSM);
4694                    notify->setInt32("channel-count", params.nChannels);
4695                    notify->setInt32("sample-rate", params.nSamplingRate);
4696                    break;
4697                }
4698
4699                default:
4700                    ALOGE("Unsupported audio coding: %s(%d)\n",
4701                            asString(audioDef->eEncoding), audioDef->eEncoding);
4702                    return BAD_TYPE;
4703            }
4704            break;
4705        }
4706
4707        default:
4708            ALOGE("Unsupported domain: %s(%d)", asString(def.eDomain), def.eDomain);
4709            return BAD_TYPE;
4710    }
4711
4712    return OK;
4713}
4714
4715void ACodec::sendFormatChange(const sp<AMessage> &reply) {
4716    sp<AMessage> notify = mBaseOutputFormat->dup();
4717    notify->setInt32("what", kWhatOutputFormatChanged);
4718
4719    if (getPortFormat(kPortIndexOutput, notify) != OK) {
4720        ALOGE("[%s] Failed to get port format to send format change", mComponentName.c_str());
4721        return;
4722    }
4723
4724    AString mime;
4725    CHECK(notify->findString("mime", &mime));
4726
4727    int32_t left, top, right, bottom;
4728    if (mime == MEDIA_MIMETYPE_VIDEO_RAW &&
4729        mNativeWindow != NULL &&
4730        notify->findRect("crop", &left, &top, &right, &bottom)) {
4731        // notify renderer of the crop change
4732        // NOTE: native window uses extended right-bottom coordinate
4733        reply->setRect("crop", left, top, right + 1, bottom + 1);
4734    } else if (mime == MEDIA_MIMETYPE_AUDIO_RAW &&
4735               (mEncoderDelay || mEncoderPadding)) {
4736        int32_t channelCount;
4737        CHECK(notify->findInt32("channel-count", &channelCount));
4738        if (mSkipCutBuffer != NULL) {
4739            size_t prevbufsize = mSkipCutBuffer->size();
4740            if (prevbufsize != 0) {
4741                ALOGW("Replacing SkipCutBuffer holding %zu bytes", prevbufsize);
4742            }
4743        }
4744        mSkipCutBuffer = new SkipCutBuffer(mEncoderDelay, mEncoderPadding, channelCount);
4745    }
4746
4747    notify->post();
4748
4749    mSentFormat = true;
4750}
4751
4752void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) {
4753    sp<AMessage> notify = mNotify->dup();
4754    notify->setInt32("what", CodecBase::kWhatError);
4755    ALOGE("signalError(omxError %#x, internalError %d)", error, internalError);
4756
4757    if (internalError == UNKNOWN_ERROR) { // find better error code
4758        const status_t omxStatus = statusFromOMXError(error);
4759        if (omxStatus != 0) {
4760            internalError = omxStatus;
4761        } else {
4762            ALOGW("Invalid OMX error %#x", error);
4763        }
4764    }
4765
4766    mFatalError = true;
4767
4768    notify->setInt32("err", internalError);
4769    notify->setInt32("actionCode", ACTION_CODE_FATAL); // could translate from OMX error.
4770    notify->post();
4771}
4772
4773////////////////////////////////////////////////////////////////////////////////
4774
4775ACodec::PortDescription::PortDescription() {
4776}
4777
4778status_t ACodec::requestIDRFrame() {
4779    if (!mIsEncoder) {
4780        return ERROR_UNSUPPORTED;
4781    }
4782
4783    OMX_CONFIG_INTRAREFRESHVOPTYPE params;
4784    InitOMXParams(&params);
4785
4786    params.nPortIndex = kPortIndexOutput;
4787    params.IntraRefreshVOP = OMX_TRUE;
4788
4789    return mOMX->setConfig(
4790            mNode,
4791            OMX_IndexConfigVideoIntraVOPRefresh,
4792            &params,
4793            sizeof(params));
4794}
4795
4796void ACodec::PortDescription::addBuffer(
4797        IOMX::buffer_id id, const sp<ABuffer> &buffer,
4798        const sp<NativeHandle> &handle, const sp<RefBase> &memRef) {
4799    mBufferIDs.push_back(id);
4800    mBuffers.push_back(buffer);
4801    mHandles.push_back(handle);
4802    mMemRefs.push_back(memRef);
4803}
4804
4805size_t ACodec::PortDescription::countBuffers() {
4806    return mBufferIDs.size();
4807}
4808
4809IOMX::buffer_id ACodec::PortDescription::bufferIDAt(size_t index) const {
4810    return mBufferIDs.itemAt(index);
4811}
4812
4813sp<ABuffer> ACodec::PortDescription::bufferAt(size_t index) const {
4814    return mBuffers.itemAt(index);
4815}
4816
4817sp<NativeHandle> ACodec::PortDescription::handleAt(size_t index) const {
4818    return mHandles.itemAt(index);
4819}
4820
4821sp<RefBase> ACodec::PortDescription::memRefAt(size_t index) const {
4822    return mMemRefs.itemAt(index);
4823}
4824
4825////////////////////////////////////////////////////////////////////////////////
4826
4827ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
4828    : AState(parentState),
4829      mCodec(codec) {
4830}
4831
4832ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(
4833        OMX_U32 /* portIndex */) {
4834    return KEEP_BUFFERS;
4835}
4836
4837bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) {
4838    switch (msg->what()) {
4839        case kWhatInputBufferFilled:
4840        {
4841            onInputBufferFilled(msg);
4842            break;
4843        }
4844
4845        case kWhatOutputBufferDrained:
4846        {
4847            onOutputBufferDrained(msg);
4848            break;
4849        }
4850
4851        case ACodec::kWhatOMXMessageList:
4852        {
4853            return checkOMXMessage(msg) ? onOMXMessageList(msg) : true;
4854        }
4855
4856        case ACodec::kWhatOMXMessageItem:
4857        {
4858            // no need to check as we already did it for kWhatOMXMessageList
4859            return onOMXMessage(msg);
4860        }
4861
4862        case ACodec::kWhatOMXMessage:
4863        {
4864            return checkOMXMessage(msg) ? onOMXMessage(msg) : true;
4865        }
4866
4867        case ACodec::kWhatSetSurface:
4868        {
4869            sp<AReplyToken> replyID;
4870            CHECK(msg->senderAwaitsResponse(&replyID));
4871
4872            sp<RefBase> obj;
4873            CHECK(msg->findObject("surface", &obj));
4874
4875            status_t err = mCodec->handleSetSurface(static_cast<Surface *>(obj.get()));
4876
4877            sp<AMessage> response = new AMessage;
4878            response->setInt32("err", err);
4879            response->postReply(replyID);
4880            break;
4881        }
4882
4883        case ACodec::kWhatCreateInputSurface:
4884        case ACodec::kWhatSetInputSurface:
4885        case ACodec::kWhatSignalEndOfInputStream:
4886        {
4887            // This may result in an app illegal state exception.
4888            ALOGE("Message 0x%x was not handled", msg->what());
4889            mCodec->signalError(OMX_ErrorUndefined, INVALID_OPERATION);
4890            return true;
4891        }
4892
4893        case ACodec::kWhatOMXDied:
4894        {
4895            // This will result in kFlagSawMediaServerDie handling in MediaCodec.
4896            ALOGE("OMX/mediaserver died, signalling error!");
4897            mCodec->signalError(OMX_ErrorResourcesLost, DEAD_OBJECT);
4898            break;
4899        }
4900
4901        case ACodec::kWhatReleaseCodecInstance:
4902        {
4903            ALOGI("[%s] forcing the release of codec",
4904                    mCodec->mComponentName.c_str());
4905            status_t err = mCodec->mOMX->freeNode(mCodec->mNode);
4906            ALOGE_IF("[%s] failed to release codec instance: err=%d",
4907                       mCodec->mComponentName.c_str(), err);
4908            sp<AMessage> notify = mCodec->mNotify->dup();
4909            notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
4910            notify->post();
4911            break;
4912        }
4913
4914        default:
4915            return false;
4916    }
4917
4918    return true;
4919}
4920
4921bool ACodec::BaseState::checkOMXMessage(const sp<AMessage> &msg) {
4922    // there is a possibility that this is an outstanding message for a
4923    // codec that we have already destroyed
4924    if (mCodec->mNode == 0) {
4925        ALOGI("ignoring message as already freed component: %s",
4926                msg->debugString().c_str());
4927        return false;
4928    }
4929
4930    IOMX::node_id nodeID;
4931    CHECK(msg->findInt32("node", (int32_t*)&nodeID));
4932    if (nodeID != mCodec->mNode) {
4933        ALOGE("Unexpected message for nodeID: %u, should have been %u", nodeID, mCodec->mNode);
4934        return false;
4935    }
4936    return true;
4937}
4938
4939bool ACodec::BaseState::onOMXMessageList(const sp<AMessage> &msg) {
4940    sp<RefBase> obj;
4941    CHECK(msg->findObject("messages", &obj));
4942    sp<MessageList> msgList = static_cast<MessageList *>(obj.get());
4943
4944    bool receivedRenderedEvents = false;
4945    for (std::list<sp<AMessage>>::const_iterator it = msgList->getList().cbegin();
4946          it != msgList->getList().cend(); ++it) {
4947        (*it)->setWhat(ACodec::kWhatOMXMessageItem);
4948        mCodec->handleMessage(*it);
4949        int32_t type;
4950        CHECK((*it)->findInt32("type", &type));
4951        if (type == omx_message::FRAME_RENDERED) {
4952            receivedRenderedEvents = true;
4953        }
4954    }
4955
4956    if (receivedRenderedEvents) {
4957        // NOTE: all buffers are rendered in this case
4958        mCodec->notifyOfRenderedFrames();
4959    }
4960    return true;
4961}
4962
4963bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) {
4964    int32_t type;
4965    CHECK(msg->findInt32("type", &type));
4966
4967    switch (type) {
4968        case omx_message::EVENT:
4969        {
4970            int32_t event, data1, data2;
4971            CHECK(msg->findInt32("event", &event));
4972            CHECK(msg->findInt32("data1", &data1));
4973            CHECK(msg->findInt32("data2", &data2));
4974
4975            if (event == OMX_EventCmdComplete
4976                    && data1 == OMX_CommandFlush
4977                    && data2 == (int32_t)OMX_ALL) {
4978                // Use of this notification is not consistent across
4979                // implementations. We'll drop this notification and rely
4980                // on flush-complete notifications on the individual port
4981                // indices instead.
4982
4983                return true;
4984            }
4985
4986            return onOMXEvent(
4987                    static_cast<OMX_EVENTTYPE>(event),
4988                    static_cast<OMX_U32>(data1),
4989                    static_cast<OMX_U32>(data2));
4990        }
4991
4992        case omx_message::EMPTY_BUFFER_DONE:
4993        {
4994            IOMX::buffer_id bufferID;
4995            int32_t fenceFd;
4996
4997            CHECK(msg->findInt32("buffer", (int32_t*)&bufferID));
4998            CHECK(msg->findInt32("fence_fd", &fenceFd));
4999
5000            return onOMXEmptyBufferDone(bufferID, fenceFd);
5001        }
5002
5003        case omx_message::FILL_BUFFER_DONE:
5004        {
5005            IOMX::buffer_id bufferID;
5006            CHECK(msg->findInt32("buffer", (int32_t*)&bufferID));
5007
5008            int32_t rangeOffset, rangeLength, flags, fenceFd;
5009            int64_t timeUs;
5010
5011            CHECK(msg->findInt32("range_offset", &rangeOffset));
5012            CHECK(msg->findInt32("range_length", &rangeLength));
5013            CHECK(msg->findInt32("flags", &flags));
5014            CHECK(msg->findInt64("timestamp", &timeUs));
5015            CHECK(msg->findInt32("fence_fd", &fenceFd));
5016
5017            return onOMXFillBufferDone(
5018                    bufferID,
5019                    (size_t)rangeOffset, (size_t)rangeLength,
5020                    (OMX_U32)flags,
5021                    timeUs,
5022                    fenceFd);
5023        }
5024
5025        case omx_message::FRAME_RENDERED:
5026        {
5027            int64_t mediaTimeUs, systemNano;
5028
5029            CHECK(msg->findInt64("media_time_us", &mediaTimeUs));
5030            CHECK(msg->findInt64("system_nano", &systemNano));
5031
5032            return onOMXFrameRendered(
5033                    mediaTimeUs, systemNano);
5034        }
5035
5036        default:
5037            ALOGE("Unexpected message type: %d", type);
5038            return false;
5039    }
5040}
5041
5042bool ACodec::BaseState::onOMXFrameRendered(
5043        int64_t mediaTimeUs __unused, nsecs_t systemNano __unused) {
5044    // ignore outside of Executing and PortSettingsChanged states
5045    return true;
5046}
5047
5048bool ACodec::BaseState::onOMXEvent(
5049        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5050    if (event != OMX_EventError) {
5051        ALOGV("[%s] EVENT(%d, 0x%08x, 0x%08x)",
5052             mCodec->mComponentName.c_str(), event, data1, data2);
5053
5054        return false;
5055    }
5056
5057    ALOGE("[%s] ERROR(0x%08x)", mCodec->mComponentName.c_str(), data1);
5058
5059    // verify OMX component sends back an error we expect.
5060    OMX_ERRORTYPE omxError = (OMX_ERRORTYPE)data1;
5061    if (!isOMXError(omxError)) {
5062        ALOGW("Invalid OMX error %#x", omxError);
5063        omxError = OMX_ErrorUndefined;
5064    }
5065    mCodec->signalError(omxError);
5066
5067    return true;
5068}
5069
5070bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID, int fenceFd) {
5071    ALOGV("[%s] onOMXEmptyBufferDone %u",
5072         mCodec->mComponentName.c_str(), bufferID);
5073
5074    BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
5075    BufferInfo::Status status = BufferInfo::getSafeStatus(info);
5076    if (status != BufferInfo::OWNED_BY_COMPONENT) {
5077        ALOGE("Wrong ownership in EBD: %s(%d) buffer #%u", _asString(status), status, bufferID);
5078        mCodec->dumpBuffers(kPortIndexInput);
5079        if (fenceFd >= 0) {
5080            ::close(fenceFd);
5081        }
5082        return false;
5083    }
5084    info->mStatus = BufferInfo::OWNED_BY_US;
5085
5086    // input buffers cannot take fences, so wait for any fence now
5087    (void)mCodec->waitForFence(fenceFd, "onOMXEmptyBufferDone");
5088    fenceFd = -1;
5089
5090    // still save fence for completeness
5091    info->setWriteFence(fenceFd, "onOMXEmptyBufferDone");
5092
5093    // We're in "store-metadata-in-buffers" mode, the underlying
5094    // OMX component had access to data that's implicitly refcounted
5095    // by this "MediaBuffer" object. Now that the OMX component has
5096    // told us that it's done with the input buffer, we can decrement
5097    // the mediaBuffer's reference count.
5098    info->mData->setMediaBufferBase(NULL);
5099
5100    PortMode mode = getPortMode(kPortIndexInput);
5101
5102    switch (mode) {
5103        case KEEP_BUFFERS:
5104            break;
5105
5106        case RESUBMIT_BUFFERS:
5107            postFillThisBuffer(info);
5108            break;
5109
5110        case FREE_BUFFERS:
5111        default:
5112            ALOGE("SHOULD NOT REACH HERE: cannot free empty output buffers");
5113            return false;
5114    }
5115
5116    return true;
5117}
5118
5119void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) {
5120    if (mCodec->mPortEOS[kPortIndexInput]) {
5121        return;
5122    }
5123
5124    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
5125
5126    sp<AMessage> notify = mCodec->mNotify->dup();
5127    notify->setInt32("what", CodecBase::kWhatFillThisBuffer);
5128    notify->setInt32("buffer-id", info->mBufferID);
5129
5130    info->mData->meta()->clear();
5131    notify->setBuffer("buffer", info->mData);
5132
5133    sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec);
5134    reply->setInt32("buffer-id", info->mBufferID);
5135
5136    notify->setMessage("reply", reply);
5137
5138    notify->post();
5139
5140    info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
5141}
5142
5143void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
5144    IOMX::buffer_id bufferID;
5145    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
5146    sp<ABuffer> buffer;
5147    int32_t err = OK;
5148    bool eos = false;
5149    PortMode mode = getPortMode(kPortIndexInput);
5150
5151    if (!msg->findBuffer("buffer", &buffer)) {
5152        /* these are unfilled buffers returned by client */
5153        CHECK(msg->findInt32("err", &err));
5154
5155        if (err == OK) {
5156            /* buffers with no errors are returned on MediaCodec.flush */
5157            mode = KEEP_BUFFERS;
5158        } else {
5159            ALOGV("[%s] saw error %d instead of an input buffer",
5160                 mCodec->mComponentName.c_str(), err);
5161            eos = true;
5162        }
5163
5164        buffer.clear();
5165    }
5166
5167    int32_t tmp;
5168    if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) {
5169        eos = true;
5170        err = ERROR_END_OF_STREAM;
5171    }
5172
5173    BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
5174    BufferInfo::Status status = BufferInfo::getSafeStatus(info);
5175    if (status != BufferInfo::OWNED_BY_UPSTREAM) {
5176        ALOGE("Wrong ownership in IBF: %s(%d) buffer #%u", _asString(status), status, bufferID);
5177        mCodec->dumpBuffers(kPortIndexInput);
5178        mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
5179        return;
5180    }
5181
5182    info->mStatus = BufferInfo::OWNED_BY_US;
5183
5184    switch (mode) {
5185        case KEEP_BUFFERS:
5186        {
5187            if (eos) {
5188                if (!mCodec->mPortEOS[kPortIndexInput]) {
5189                    mCodec->mPortEOS[kPortIndexInput] = true;
5190                    mCodec->mInputEOSResult = err;
5191                }
5192            }
5193            break;
5194        }
5195
5196        case RESUBMIT_BUFFERS:
5197        {
5198            if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) {
5199                // Do not send empty input buffer w/o EOS to the component.
5200                if (buffer->size() == 0 && !eos) {
5201                    postFillThisBuffer(info);
5202                    break;
5203                }
5204
5205                int64_t timeUs;
5206                CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
5207
5208                OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
5209
5210                int32_t isCSD;
5211                if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) {
5212                    flags |= OMX_BUFFERFLAG_CODECCONFIG;
5213                }
5214
5215                if (eos) {
5216                    flags |= OMX_BUFFERFLAG_EOS;
5217                }
5218
5219                if (buffer != info->mData) {
5220                    ALOGV("[%s] Needs to copy input data for buffer %u. (%p != %p)",
5221                         mCodec->mComponentName.c_str(),
5222                         bufferID,
5223                         buffer.get(), info->mData.get());
5224
5225                    if (buffer->size() > info->mData->capacity()) {
5226                        ALOGE("data size (%zu) is greated than buffer capacity (%zu)",
5227                                buffer->size(),           // this is the data received
5228                                info->mData->capacity()); // this is out buffer size
5229                        mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
5230                        return;
5231                    }
5232                    memcpy(info->mData->data(), buffer->data(), buffer->size());
5233                }
5234
5235                if (flags & OMX_BUFFERFLAG_CODECCONFIG) {
5236                    ALOGV("[%s] calling emptyBuffer %u w/ codec specific data",
5237                         mCodec->mComponentName.c_str(), bufferID);
5238                } else if (flags & OMX_BUFFERFLAG_EOS) {
5239                    ALOGV("[%s] calling emptyBuffer %u w/ EOS",
5240                         mCodec->mComponentName.c_str(), bufferID);
5241                } else {
5242#if TRACK_BUFFER_TIMING
5243                    ALOGI("[%s] calling emptyBuffer %u w/ time %lld us",
5244                         mCodec->mComponentName.c_str(), bufferID, (long long)timeUs);
5245#else
5246                    ALOGV("[%s] calling emptyBuffer %u w/ time %lld us",
5247                         mCodec->mComponentName.c_str(), bufferID, (long long)timeUs);
5248#endif
5249                }
5250
5251#if TRACK_BUFFER_TIMING
5252                ACodec::BufferStats stats;
5253                stats.mEmptyBufferTimeUs = ALooper::GetNowUs();
5254                stats.mFillBufferDoneTimeUs = -1ll;
5255                mCodec->mBufferStats.add(timeUs, stats);
5256#endif
5257
5258                if (mCodec->storingMetadataInDecodedBuffers()) {
5259                    // try to submit an output buffer for each input buffer
5260                    PortMode outputMode = getPortMode(kPortIndexOutput);
5261
5262                    ALOGV("MetadataBuffersToSubmit=%u portMode=%s",
5263                            mCodec->mMetadataBuffersToSubmit,
5264                            (outputMode == FREE_BUFFERS ? "FREE" :
5265                             outputMode == KEEP_BUFFERS ? "KEEP" : "RESUBMIT"));
5266                    if (outputMode == RESUBMIT_BUFFERS) {
5267                        mCodec->submitOutputMetadataBuffer();
5268                    }
5269                }
5270                info->checkReadFence("onInputBufferFilled");
5271                status_t err2 = mCodec->mOMX->emptyBuffer(
5272                    mCodec->mNode,
5273                    bufferID,
5274                    0,
5275                    buffer->size(),
5276                    flags,
5277                    timeUs,
5278                    info->mFenceFd);
5279                info->mFenceFd = -1;
5280                if (err2 != OK) {
5281                    mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err2));
5282                    return;
5283                }
5284                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
5285
5286                if (!eos && err == OK) {
5287                    getMoreInputDataIfPossible();
5288                } else {
5289                    ALOGV("[%s] Signalled EOS (%d) on the input port",
5290                         mCodec->mComponentName.c_str(), err);
5291
5292                    mCodec->mPortEOS[kPortIndexInput] = true;
5293                    mCodec->mInputEOSResult = err;
5294                }
5295            } else if (!mCodec->mPortEOS[kPortIndexInput]) {
5296                if (err != OK && err != ERROR_END_OF_STREAM) {
5297                    ALOGV("[%s] Signalling EOS on the input port due to error %d",
5298                         mCodec->mComponentName.c_str(), err);
5299                } else {
5300                    ALOGV("[%s] Signalling EOS on the input port",
5301                         mCodec->mComponentName.c_str());
5302                }
5303
5304                ALOGV("[%s] calling emptyBuffer %u signalling EOS",
5305                     mCodec->mComponentName.c_str(), bufferID);
5306
5307                info->checkReadFence("onInputBufferFilled");
5308                status_t err2 = mCodec->mOMX->emptyBuffer(
5309                        mCodec->mNode,
5310                        bufferID,
5311                        0,
5312                        0,
5313                        OMX_BUFFERFLAG_EOS,
5314                        0,
5315                        info->mFenceFd);
5316                info->mFenceFd = -1;
5317                if (err2 != OK) {
5318                    mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err2));
5319                    return;
5320                }
5321                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
5322
5323                mCodec->mPortEOS[kPortIndexInput] = true;
5324                mCodec->mInputEOSResult = err;
5325            }
5326            break;
5327        }
5328
5329        case FREE_BUFFERS:
5330            break;
5331
5332        default:
5333            ALOGE("invalid port mode: %d", mode);
5334            break;
5335    }
5336}
5337
5338void ACodec::BaseState::getMoreInputDataIfPossible() {
5339    if (mCodec->mPortEOS[kPortIndexInput]) {
5340        return;
5341    }
5342
5343    BufferInfo *eligible = NULL;
5344
5345    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
5346        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
5347
5348#if 0
5349        if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) {
5350            // There's already a "read" pending.
5351            return;
5352        }
5353#endif
5354
5355        if (info->mStatus == BufferInfo::OWNED_BY_US) {
5356            eligible = info;
5357        }
5358    }
5359
5360    if (eligible == NULL) {
5361        return;
5362    }
5363
5364    postFillThisBuffer(eligible);
5365}
5366
5367bool ACodec::BaseState::onOMXFillBufferDone(
5368        IOMX::buffer_id bufferID,
5369        size_t rangeOffset, size_t rangeLength,
5370        OMX_U32 flags,
5371        int64_t timeUs,
5372        int fenceFd) {
5373    ALOGV("[%s] onOMXFillBufferDone %u time %" PRId64 " us, flags = 0x%08x",
5374         mCodec->mComponentName.c_str(), bufferID, timeUs, flags);
5375
5376    ssize_t index;
5377    status_t err= OK;
5378
5379#if TRACK_BUFFER_TIMING
5380    index = mCodec->mBufferStats.indexOfKey(timeUs);
5381    if (index >= 0) {
5382        ACodec::BufferStats *stats = &mCodec->mBufferStats.editValueAt(index);
5383        stats->mFillBufferDoneTimeUs = ALooper::GetNowUs();
5384
5385        ALOGI("frame PTS %lld: %lld",
5386                timeUs,
5387                stats->mFillBufferDoneTimeUs - stats->mEmptyBufferTimeUs);
5388
5389        mCodec->mBufferStats.removeItemsAt(index);
5390        stats = NULL;
5391    }
5392#endif
5393
5394    BufferInfo *info =
5395        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
5396    BufferInfo::Status status = BufferInfo::getSafeStatus(info);
5397    if (status != BufferInfo::OWNED_BY_COMPONENT) {
5398        ALOGE("Wrong ownership in FBD: %s(%d) buffer #%u", _asString(status), status, bufferID);
5399        mCodec->dumpBuffers(kPortIndexOutput);
5400        mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
5401        if (fenceFd >= 0) {
5402            ::close(fenceFd);
5403        }
5404        return true;
5405    }
5406
5407    info->mDequeuedAt = ++mCodec->mDequeueCounter;
5408    info->mStatus = BufferInfo::OWNED_BY_US;
5409
5410    if (info->mRenderInfo != NULL) {
5411        // The fence for an emptied buffer must have signaled, but there still could be queued
5412        // or out-of-order dequeued buffers in the render queue prior to this buffer. Drop these,
5413        // as we will soon requeue this buffer to the surface. While in theory we could still keep
5414        // track of buffers that are requeued to the surface, it is better to add support to the
5415        // buffer-queue to notify us of released buffers and their fences (in the future).
5416        mCodec->notifyOfRenderedFrames(true /* dropIncomplete */);
5417    }
5418
5419    // byte buffers cannot take fences, so wait for any fence now
5420    if (mCodec->mNativeWindow == NULL) {
5421        (void)mCodec->waitForFence(fenceFd, "onOMXFillBufferDone");
5422        fenceFd = -1;
5423    }
5424    info->setReadFence(fenceFd, "onOMXFillBufferDone");
5425
5426    PortMode mode = getPortMode(kPortIndexOutput);
5427
5428    switch (mode) {
5429        case KEEP_BUFFERS:
5430            break;
5431
5432        case RESUBMIT_BUFFERS:
5433        {
5434            if (rangeLength == 0 && (!(flags & OMX_BUFFERFLAG_EOS)
5435                    || mCodec->mPortEOS[kPortIndexOutput])) {
5436                ALOGV("[%s] calling fillBuffer %u",
5437                     mCodec->mComponentName.c_str(), info->mBufferID);
5438
5439                err = mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID, info->mFenceFd);
5440                info->mFenceFd = -1;
5441                if (err != OK) {
5442                    mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5443                    return true;
5444                }
5445
5446                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
5447                break;
5448            }
5449
5450            sp<AMessage> reply =
5451                new AMessage(kWhatOutputBufferDrained, mCodec);
5452
5453            if (!mCodec->mSentFormat && rangeLength > 0) {
5454                mCodec->sendFormatChange(reply);
5455            }
5456            if (mCodec->usingMetadataOnEncoderOutput()) {
5457                native_handle_t *handle = NULL;
5458                VideoGrallocMetadata &grallocMeta = *(VideoGrallocMetadata *)info->mData->data();
5459                VideoNativeMetadata &nativeMeta = *(VideoNativeMetadata *)info->mData->data();
5460                if (info->mData->size() >= sizeof(grallocMeta)
5461                        && grallocMeta.eType == kMetadataBufferTypeGrallocSource) {
5462                    handle = (native_handle_t *)(uintptr_t)grallocMeta.pHandle;
5463                } else if (info->mData->size() >= sizeof(nativeMeta)
5464                        && nativeMeta.eType == kMetadataBufferTypeANWBuffer) {
5465#ifdef OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
5466                    // ANativeWindowBuffer is only valid on 32-bit/mediaserver process
5467                    handle = NULL;
5468#else
5469                    handle = (native_handle_t *)nativeMeta.pBuffer->handle;
5470#endif
5471                }
5472                info->mData->meta()->setPointer("handle", handle);
5473                info->mData->meta()->setInt32("rangeOffset", rangeOffset);
5474                info->mData->meta()->setInt32("rangeLength", rangeLength);
5475            } else {
5476                info->mData->setRange(rangeOffset, rangeLength);
5477            }
5478#if 0
5479            if (mCodec->mNativeWindow == NULL) {
5480                if (IsIDR(info->mData)) {
5481                    ALOGI("IDR frame");
5482                }
5483            }
5484#endif
5485
5486            if (mCodec->mSkipCutBuffer != NULL) {
5487                mCodec->mSkipCutBuffer->submit(info->mData);
5488            }
5489            info->mData->meta()->setInt64("timeUs", timeUs);
5490
5491            sp<AMessage> notify = mCodec->mNotify->dup();
5492            notify->setInt32("what", CodecBase::kWhatDrainThisBuffer);
5493            notify->setInt32("buffer-id", info->mBufferID);
5494            notify->setBuffer("buffer", info->mData);
5495            notify->setInt32("flags", flags);
5496
5497            reply->setInt32("buffer-id", info->mBufferID);
5498
5499            notify->setMessage("reply", reply);
5500
5501            notify->post();
5502
5503            info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;
5504
5505            if (flags & OMX_BUFFERFLAG_EOS) {
5506                ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str());
5507
5508                sp<AMessage> notify = mCodec->mNotify->dup();
5509                notify->setInt32("what", CodecBase::kWhatEOS);
5510                notify->setInt32("err", mCodec->mInputEOSResult);
5511                notify->post();
5512
5513                mCodec->mPortEOS[kPortIndexOutput] = true;
5514            }
5515            break;
5516        }
5517
5518        case FREE_BUFFERS:
5519            err = mCodec->freeBuffer(kPortIndexOutput, index);
5520            if (err != OK) {
5521                mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5522                return true;
5523            }
5524            break;
5525
5526        default:
5527            ALOGE("Invalid port mode: %d", mode);
5528            return false;
5529    }
5530
5531    return true;
5532}
5533
5534void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
5535    IOMX::buffer_id bufferID;
5536    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
5537    ssize_t index;
5538    BufferInfo *info = mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
5539    BufferInfo::Status status = BufferInfo::getSafeStatus(info);
5540    if (status != BufferInfo::OWNED_BY_DOWNSTREAM) {
5541        ALOGE("Wrong ownership in OBD: %s(%d) buffer #%u", _asString(status), status, bufferID);
5542        mCodec->dumpBuffers(kPortIndexOutput);
5543        mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
5544        return;
5545    }
5546
5547    android_native_rect_t crop;
5548    if (msg->findRect("crop", &crop.left, &crop.top, &crop.right, &crop.bottom)) {
5549        status_t err = native_window_set_crop(mCodec->mNativeWindow.get(), &crop);
5550        ALOGW_IF(err != NO_ERROR, "failed to set crop: %d", err);
5551    }
5552
5553    int32_t render;
5554    if (mCodec->mNativeWindow != NULL
5555            && msg->findInt32("render", &render) && render != 0
5556            && info->mData != NULL && info->mData->size() != 0) {
5557        ATRACE_NAME("render");
5558        // The client wants this buffer to be rendered.
5559
5560        // save buffers sent to the surface so we can get render time when they return
5561        int64_t mediaTimeUs = -1;
5562        info->mData->meta()->findInt64("timeUs", &mediaTimeUs);
5563        if (mediaTimeUs >= 0) {
5564            mCodec->mRenderTracker.onFrameQueued(
5565                    mediaTimeUs, info->mGraphicBuffer, new Fence(::dup(info->mFenceFd)));
5566        }
5567
5568        int64_t timestampNs = 0;
5569        if (!msg->findInt64("timestampNs", &timestampNs)) {
5570            // use media timestamp if client did not request a specific render timestamp
5571            if (info->mData->meta()->findInt64("timeUs", &timestampNs)) {
5572                ALOGV("using buffer PTS of %lld", (long long)timestampNs);
5573                timestampNs *= 1000;
5574            }
5575        }
5576
5577        status_t err;
5578        err = native_window_set_buffers_timestamp(mCodec->mNativeWindow.get(), timestampNs);
5579        ALOGW_IF(err != NO_ERROR, "failed to set buffer timestamp: %d", err);
5580
5581        info->checkReadFence("onOutputBufferDrained before queueBuffer");
5582        err = mCodec->mNativeWindow->queueBuffer(
5583                    mCodec->mNativeWindow.get(), info->mGraphicBuffer.get(), info->mFenceFd);
5584        info->mFenceFd = -1;
5585        if (err == OK) {
5586            info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
5587        } else {
5588            ALOGE("queueBuffer failed in onOutputBufferDrained: %d", err);
5589            mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5590            info->mStatus = BufferInfo::OWNED_BY_US;
5591            // keeping read fence as write fence to avoid clobbering
5592            info->mIsReadFence = false;
5593        }
5594    } else {
5595        if (mCodec->mNativeWindow != NULL &&
5596            (info->mData == NULL || info->mData->size() != 0)) {
5597            // move read fence into write fence to avoid clobbering
5598            info->mIsReadFence = false;
5599            ATRACE_NAME("frame-drop");
5600        }
5601        info->mStatus = BufferInfo::OWNED_BY_US;
5602    }
5603
5604    PortMode mode = getPortMode(kPortIndexOutput);
5605
5606    switch (mode) {
5607        case KEEP_BUFFERS:
5608        {
5609            // XXX fishy, revisit!!! What about the FREE_BUFFERS case below?
5610
5611            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
5612                // We cannot resubmit the buffer we just rendered, dequeue
5613                // the spare instead.
5614
5615                info = mCodec->dequeueBufferFromNativeWindow();
5616            }
5617            break;
5618        }
5619
5620        case RESUBMIT_BUFFERS:
5621        {
5622            if (!mCodec->mPortEOS[kPortIndexOutput]) {
5623                if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
5624                    // We cannot resubmit the buffer we just rendered, dequeue
5625                    // the spare instead.
5626
5627                    info = mCodec->dequeueBufferFromNativeWindow();
5628                }
5629
5630                if (info != NULL) {
5631                    ALOGV("[%s] calling fillBuffer %u",
5632                         mCodec->mComponentName.c_str(), info->mBufferID);
5633                    info->checkWriteFence("onOutputBufferDrained::RESUBMIT_BUFFERS");
5634                    status_t err = mCodec->mOMX->fillBuffer(
5635                            mCodec->mNode, info->mBufferID, info->mFenceFd);
5636                    info->mFenceFd = -1;
5637                    if (err == OK) {
5638                        info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
5639                    } else {
5640                        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5641                    }
5642                }
5643            }
5644            break;
5645        }
5646
5647        case FREE_BUFFERS:
5648        {
5649            status_t err = mCodec->freeBuffer(kPortIndexOutput, index);
5650            if (err != OK) {
5651                mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5652            }
5653            break;
5654        }
5655
5656        default:
5657            ALOGE("Invalid port mode: %d", mode);
5658            return;
5659    }
5660}
5661
5662////////////////////////////////////////////////////////////////////////////////
5663
5664ACodec::UninitializedState::UninitializedState(ACodec *codec)
5665    : BaseState(codec) {
5666}
5667
5668void ACodec::UninitializedState::stateEntered() {
5669    ALOGV("Now uninitialized");
5670
5671    if (mDeathNotifier != NULL) {
5672        mCodec->mNodeBinder->unlinkToDeath(mDeathNotifier);
5673        mDeathNotifier.clear();
5674    }
5675
5676    mCodec->mNativeWindow.clear();
5677    mCodec->mNativeWindowUsageBits = 0;
5678    mCodec->mNode = 0;
5679    mCodec->mOMX.clear();
5680    mCodec->mQuirks = 0;
5681    mCodec->mFlags = 0;
5682    mCodec->mInputMetadataType = kMetadataBufferTypeInvalid;
5683    mCodec->mOutputMetadataType = kMetadataBufferTypeInvalid;
5684    mCodec->mComponentName.clear();
5685}
5686
5687bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
5688    bool handled = false;
5689
5690    switch (msg->what()) {
5691        case ACodec::kWhatSetup:
5692        {
5693            onSetup(msg);
5694
5695            handled = true;
5696            break;
5697        }
5698
5699        case ACodec::kWhatAllocateComponent:
5700        {
5701            onAllocateComponent(msg);
5702            handled = true;
5703            break;
5704        }
5705
5706        case ACodec::kWhatShutdown:
5707        {
5708            int32_t keepComponentAllocated;
5709            CHECK(msg->findInt32(
5710                        "keepComponentAllocated", &keepComponentAllocated));
5711            ALOGW_IF(keepComponentAllocated,
5712                     "cannot keep component allocated on shutdown in Uninitialized state");
5713
5714            sp<AMessage> notify = mCodec->mNotify->dup();
5715            notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
5716            notify->post();
5717
5718            handled = true;
5719            break;
5720        }
5721
5722        case ACodec::kWhatFlush:
5723        {
5724            sp<AMessage> notify = mCodec->mNotify->dup();
5725            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
5726            notify->post();
5727
5728            handled = true;
5729            break;
5730        }
5731
5732        case ACodec::kWhatReleaseCodecInstance:
5733        {
5734            // nothing to do, as we have already signaled shutdown
5735            handled = true;
5736            break;
5737        }
5738
5739        default:
5740            return BaseState::onMessageReceived(msg);
5741    }
5742
5743    return handled;
5744}
5745
5746void ACodec::UninitializedState::onSetup(
5747        const sp<AMessage> &msg) {
5748    if (onAllocateComponent(msg)
5749            && mCodec->mLoadedState->onConfigureComponent(msg)) {
5750        mCodec->mLoadedState->onStart();
5751    }
5752}
5753
5754bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
5755    ALOGV("onAllocateComponent");
5756
5757    CHECK(mCodec->mNode == 0);
5758
5759    OMXClient client;
5760    if (client.connect() != OK) {
5761        mCodec->signalError(OMX_ErrorUndefined, NO_INIT);
5762        return false;
5763    }
5764
5765    sp<IOMX> omx = client.interface();
5766
5767    sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec);
5768
5769    Vector<AString> matchingCodecs;
5770
5771    AString mime;
5772
5773    AString componentName;
5774    uint32_t quirks = 0;
5775    int32_t encoder = false;
5776    if (msg->findString("componentName", &componentName)) {
5777        sp<IMediaCodecList> list = MediaCodecList::getInstance();
5778        if (list != NULL && list->findCodecByName(componentName.c_str()) >= 0) {
5779            matchingCodecs.add(componentName);
5780        }
5781    } else {
5782        CHECK(msg->findString("mime", &mime));
5783
5784        if (!msg->findInt32("encoder", &encoder)) {
5785            encoder = false;
5786        }
5787
5788        MediaCodecList::findMatchingCodecs(
5789                mime.c_str(),
5790                encoder, // createEncoder
5791                0,       // flags
5792                &matchingCodecs);
5793    }
5794
5795    sp<CodecObserver> observer = new CodecObserver;
5796    IOMX::node_id node = 0;
5797
5798    status_t err = NAME_NOT_FOUND;
5799    for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
5800            ++matchIndex) {
5801        componentName = matchingCodecs[matchIndex];
5802        quirks = MediaCodecList::getQuirksFor(componentName.c_str());
5803
5804        pid_t tid = gettid();
5805        int prevPriority = androidGetThreadPriority(tid);
5806        androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
5807        err = omx->allocateNode(componentName.c_str(), observer, &mCodec->mNodeBinder, &node);
5808        androidSetThreadPriority(tid, prevPriority);
5809
5810        if (err == OK) {
5811            break;
5812        } else {
5813            ALOGW("Allocating component '%s' failed, try next one.", componentName.c_str());
5814        }
5815
5816        node = 0;
5817    }
5818
5819    if (node == 0) {
5820        if (!mime.empty()) {
5821            ALOGE("Unable to instantiate a %scoder for type '%s' with err %#x.",
5822                    encoder ? "en" : "de", mime.c_str(), err);
5823        } else {
5824            ALOGE("Unable to instantiate codec '%s' with err %#x.", componentName.c_str(), err);
5825        }
5826
5827        mCodec->signalError((OMX_ERRORTYPE)err, makeNoSideEffectStatus(err));
5828        return false;
5829    }
5830
5831    mDeathNotifier = new DeathNotifier(notify);
5832    if (mCodec->mNodeBinder == NULL ||
5833            mCodec->mNodeBinder->linkToDeath(mDeathNotifier) != OK) {
5834        // This was a local binder, if it dies so do we, we won't care
5835        // about any notifications in the afterlife.
5836        mDeathNotifier.clear();
5837    }
5838
5839    notify = new AMessage(kWhatOMXMessageList, mCodec);
5840    observer->setNotificationMessage(notify);
5841
5842    mCodec->mComponentName = componentName;
5843    mCodec->mRenderTracker.setComponentName(componentName);
5844    mCodec->mFlags = 0;
5845
5846    if (componentName.endsWith(".secure")) {
5847        mCodec->mFlags |= kFlagIsSecure;
5848        mCodec->mFlags |= kFlagIsGrallocUsageProtected;
5849        mCodec->mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
5850    }
5851
5852    mCodec->mQuirks = quirks;
5853    mCodec->mOMX = omx;
5854    mCodec->mNode = node;
5855
5856    {
5857        sp<AMessage> notify = mCodec->mNotify->dup();
5858        notify->setInt32("what", CodecBase::kWhatComponentAllocated);
5859        notify->setString("componentName", mCodec->mComponentName.c_str());
5860        notify->post();
5861    }
5862
5863    mCodec->changeState(mCodec->mLoadedState);
5864
5865    return true;
5866}
5867
5868////////////////////////////////////////////////////////////////////////////////
5869
5870ACodec::LoadedState::LoadedState(ACodec *codec)
5871    : BaseState(codec) {
5872}
5873
5874void ACodec::LoadedState::stateEntered() {
5875    ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
5876
5877    mCodec->mPortEOS[kPortIndexInput] =
5878        mCodec->mPortEOS[kPortIndexOutput] = false;
5879
5880    mCodec->mInputEOSResult = OK;
5881
5882    mCodec->mDequeueCounter = 0;
5883    mCodec->mMetadataBuffersToSubmit = 0;
5884    mCodec->mRepeatFrameDelayUs = -1ll;
5885    mCodec->mInputFormat.clear();
5886    mCodec->mOutputFormat.clear();
5887    mCodec->mBaseOutputFormat.clear();
5888
5889    if (mCodec->mShutdownInProgress) {
5890        bool keepComponentAllocated = mCodec->mKeepComponentAllocated;
5891
5892        mCodec->mShutdownInProgress = false;
5893        mCodec->mKeepComponentAllocated = false;
5894
5895        onShutdown(keepComponentAllocated);
5896    }
5897    mCodec->mExplicitShutdown = false;
5898
5899    mCodec->processDeferredMessages();
5900}
5901
5902void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) {
5903    if (!keepComponentAllocated) {
5904        (void)mCodec->mOMX->freeNode(mCodec->mNode);
5905
5906        mCodec->changeState(mCodec->mUninitializedState);
5907    }
5908
5909    if (mCodec->mExplicitShutdown) {
5910        sp<AMessage> notify = mCodec->mNotify->dup();
5911        notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
5912        notify->post();
5913        mCodec->mExplicitShutdown = false;
5914    }
5915}
5916
5917bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) {
5918    bool handled = false;
5919
5920    switch (msg->what()) {
5921        case ACodec::kWhatConfigureComponent:
5922        {
5923            onConfigureComponent(msg);
5924            handled = true;
5925            break;
5926        }
5927
5928        case ACodec::kWhatCreateInputSurface:
5929        {
5930            onCreateInputSurface(msg);
5931            handled = true;
5932            break;
5933        }
5934
5935        case ACodec::kWhatSetInputSurface:
5936        {
5937            onSetInputSurface(msg);
5938            handled = true;
5939            break;
5940        }
5941
5942        case ACodec::kWhatStart:
5943        {
5944            onStart();
5945            handled = true;
5946            break;
5947        }
5948
5949        case ACodec::kWhatShutdown:
5950        {
5951            int32_t keepComponentAllocated;
5952            CHECK(msg->findInt32(
5953                        "keepComponentAllocated", &keepComponentAllocated));
5954
5955            mCodec->mExplicitShutdown = true;
5956            onShutdown(keepComponentAllocated);
5957
5958            handled = true;
5959            break;
5960        }
5961
5962        case ACodec::kWhatFlush:
5963        {
5964            sp<AMessage> notify = mCodec->mNotify->dup();
5965            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
5966            notify->post();
5967
5968            handled = true;
5969            break;
5970        }
5971
5972        default:
5973            return BaseState::onMessageReceived(msg);
5974    }
5975
5976    return handled;
5977}
5978
5979bool ACodec::LoadedState::onConfigureComponent(
5980        const sp<AMessage> &msg) {
5981    ALOGV("onConfigureComponent");
5982
5983    CHECK(mCodec->mNode != 0);
5984
5985    status_t err = OK;
5986    AString mime;
5987    if (!msg->findString("mime", &mime)) {
5988        err = BAD_VALUE;
5989    } else {
5990        err = mCodec->configureCodec(mime.c_str(), msg);
5991    }
5992    if (err != OK) {
5993        ALOGE("[%s] configureCodec returning error %d",
5994              mCodec->mComponentName.c_str(), err);
5995
5996        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5997        return false;
5998    }
5999
6000    {
6001        sp<AMessage> notify = mCodec->mNotify->dup();
6002        notify->setInt32("what", CodecBase::kWhatComponentConfigured);
6003        notify->setMessage("input-format", mCodec->mInputFormat);
6004        notify->setMessage("output-format", mCodec->mOutputFormat);
6005        notify->post();
6006    }
6007
6008    return true;
6009}
6010
6011status_t ACodec::LoadedState::setupInputSurface() {
6012    status_t err = OK;
6013
6014    if (mCodec->mRepeatFrameDelayUs > 0ll) {
6015        err = mCodec->mOMX->setInternalOption(
6016                mCodec->mNode,
6017                kPortIndexInput,
6018                IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY,
6019                &mCodec->mRepeatFrameDelayUs,
6020                sizeof(mCodec->mRepeatFrameDelayUs));
6021
6022        if (err != OK) {
6023            ALOGE("[%s] Unable to configure option to repeat previous "
6024                  "frames (err %d)",
6025                  mCodec->mComponentName.c_str(),
6026                  err);
6027            return err;
6028        }
6029    }
6030
6031    if (mCodec->mMaxPtsGapUs > 0ll) {
6032        err = mCodec->mOMX->setInternalOption(
6033                mCodec->mNode,
6034                kPortIndexInput,
6035                IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP,
6036                &mCodec->mMaxPtsGapUs,
6037                sizeof(mCodec->mMaxPtsGapUs));
6038
6039        if (err != OK) {
6040            ALOGE("[%s] Unable to configure max timestamp gap (err %d)",
6041                    mCodec->mComponentName.c_str(),
6042                    err);
6043            return err;
6044        }
6045    }
6046
6047    if (mCodec->mMaxFps > 0) {
6048        err = mCodec->mOMX->setInternalOption(
6049                mCodec->mNode,
6050                kPortIndexInput,
6051                IOMX::INTERNAL_OPTION_MAX_FPS,
6052                &mCodec->mMaxFps,
6053                sizeof(mCodec->mMaxFps));
6054
6055        if (err != OK) {
6056            ALOGE("[%s] Unable to configure max fps (err %d)",
6057                    mCodec->mComponentName.c_str(),
6058                    err);
6059            return err;
6060        }
6061    }
6062
6063    if (mCodec->mTimePerCaptureUs > 0ll
6064            && mCodec->mTimePerFrameUs > 0ll) {
6065        int64_t timeLapse[2];
6066        timeLapse[0] = mCodec->mTimePerFrameUs;
6067        timeLapse[1] = mCodec->mTimePerCaptureUs;
6068        err = mCodec->mOMX->setInternalOption(
6069                mCodec->mNode,
6070                kPortIndexInput,
6071                IOMX::INTERNAL_OPTION_TIME_LAPSE,
6072                &timeLapse[0],
6073                sizeof(timeLapse));
6074
6075        if (err != OK) {
6076            ALOGE("[%s] Unable to configure time lapse (err %d)",
6077                    mCodec->mComponentName.c_str(),
6078                    err);
6079            return err;
6080        }
6081    }
6082
6083    if (mCodec->mCreateInputBuffersSuspended) {
6084        bool suspend = true;
6085        err = mCodec->mOMX->setInternalOption(
6086                mCodec->mNode,
6087                kPortIndexInput,
6088                IOMX::INTERNAL_OPTION_SUSPEND,
6089                &suspend,
6090                sizeof(suspend));
6091
6092        if (err != OK) {
6093            ALOGE("[%s] Unable to configure option to suspend (err %d)",
6094                  mCodec->mComponentName.c_str(),
6095                  err);
6096            return err;
6097        }
6098    }
6099
6100    uint32_t usageBits;
6101    if (mCodec->mOMX->getParameter(
6102            mCodec->mNode, (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
6103            &usageBits, sizeof(usageBits)) == OK) {
6104        mCodec->mInputFormat->setInt32(
6105                "using-sw-read-often", !!(usageBits & GRALLOC_USAGE_SW_READ_OFTEN));
6106    }
6107
6108    return OK;
6109}
6110
6111void ACodec::LoadedState::onCreateInputSurface(
6112        const sp<AMessage> & /* msg */) {
6113    ALOGV("onCreateInputSurface");
6114
6115    sp<AMessage> notify = mCodec->mNotify->dup();
6116    notify->setInt32("what", CodecBase::kWhatInputSurfaceCreated);
6117
6118    sp<IGraphicBufferProducer> bufferProducer;
6119    status_t err = mCodec->mOMX->createInputSurface(
6120            mCodec->mNode, kPortIndexInput, &bufferProducer, &mCodec->mInputMetadataType);
6121
6122    if (err == OK) {
6123        err = setupInputSurface();
6124    }
6125
6126    if (err == OK) {
6127        notify->setObject("input-surface",
6128                new BufferProducerWrapper(bufferProducer));
6129    } else {
6130        // Can't use mCodec->signalError() here -- MediaCodec won't forward
6131        // the error through because it's in the "configured" state.  We
6132        // send a kWhatInputSurfaceCreated with an error value instead.
6133        ALOGE("[%s] onCreateInputSurface returning error %d",
6134                mCodec->mComponentName.c_str(), err);
6135        notify->setInt32("err", err);
6136    }
6137    notify->post();
6138}
6139
6140void ACodec::LoadedState::onSetInputSurface(
6141        const sp<AMessage> &msg) {
6142    ALOGV("onSetInputSurface");
6143
6144    sp<AMessage> notify = mCodec->mNotify->dup();
6145    notify->setInt32("what", CodecBase::kWhatInputSurfaceAccepted);
6146
6147    sp<RefBase> obj;
6148    CHECK(msg->findObject("input-surface", &obj));
6149    sp<PersistentSurface> surface = static_cast<PersistentSurface *>(obj.get());
6150
6151    status_t err = mCodec->mOMX->setInputSurface(
6152            mCodec->mNode, kPortIndexInput, surface->getBufferConsumer(),
6153            &mCodec->mInputMetadataType);
6154
6155    if (err == OK) {
6156        err = setupInputSurface();
6157    }
6158
6159    if (err != OK) {
6160        // Can't use mCodec->signalError() here -- MediaCodec won't forward
6161        // the error through because it's in the "configured" state.  We
6162        // send a kWhatInputSurfaceAccepted with an error value instead.
6163        ALOGE("[%s] onSetInputSurface returning error %d",
6164                mCodec->mComponentName.c_str(), err);
6165        notify->setInt32("err", err);
6166    }
6167    notify->post();
6168}
6169
6170void ACodec::LoadedState::onStart() {
6171    ALOGV("onStart");
6172
6173    status_t err = mCodec->mOMX->sendCommand(mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle);
6174    if (err != OK) {
6175        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6176    } else {
6177        mCodec->changeState(mCodec->mLoadedToIdleState);
6178    }
6179}
6180
6181////////////////////////////////////////////////////////////////////////////////
6182
6183ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec)
6184    : BaseState(codec) {
6185}
6186
6187void ACodec::LoadedToIdleState::stateEntered() {
6188    ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
6189
6190    status_t err;
6191    if ((err = allocateBuffers()) != OK) {
6192        ALOGE("Failed to allocate buffers after transitioning to IDLE state "
6193             "(error 0x%08x)",
6194             err);
6195
6196        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6197
6198        mCodec->mOMX->sendCommand(
6199                mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded);
6200        if (mCodec->allYourBuffersAreBelongToUs(kPortIndexInput)) {
6201            mCodec->freeBuffersOnPort(kPortIndexInput);
6202        }
6203        if (mCodec->allYourBuffersAreBelongToUs(kPortIndexOutput)) {
6204            mCodec->freeBuffersOnPort(kPortIndexOutput);
6205        }
6206
6207        mCodec->changeState(mCodec->mLoadedState);
6208    }
6209}
6210
6211status_t ACodec::LoadedToIdleState::allocateBuffers() {
6212    status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput);
6213
6214    if (err != OK) {
6215        return err;
6216    }
6217
6218    return mCodec->allocateBuffersOnPort(kPortIndexOutput);
6219}
6220
6221bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
6222    switch (msg->what()) {
6223        case kWhatSetParameters:
6224        case kWhatShutdown:
6225        {
6226            mCodec->deferMessage(msg);
6227            return true;
6228        }
6229
6230        case kWhatSignalEndOfInputStream:
6231        {
6232            mCodec->onSignalEndOfInputStream();
6233            return true;
6234        }
6235
6236        case kWhatResume:
6237        {
6238            // We'll be active soon enough.
6239            return true;
6240        }
6241
6242        case kWhatFlush:
6243        {
6244            // We haven't even started yet, so we're flushed alright...
6245            sp<AMessage> notify = mCodec->mNotify->dup();
6246            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
6247            notify->post();
6248            return true;
6249        }
6250
6251        default:
6252            return BaseState::onMessageReceived(msg);
6253    }
6254}
6255
6256bool ACodec::LoadedToIdleState::onOMXEvent(
6257        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
6258    switch (event) {
6259        case OMX_EventCmdComplete:
6260        {
6261            status_t err = OK;
6262            if (data1 != (OMX_U32)OMX_CommandStateSet
6263                    || data2 != (OMX_U32)OMX_StateIdle) {
6264                ALOGE("Unexpected command completion in LoadedToIdleState: %s(%u) %s(%u)",
6265                        asString((OMX_COMMANDTYPE)data1), data1,
6266                        asString((OMX_STATETYPE)data2), data2);
6267                err = FAILED_TRANSACTION;
6268            }
6269
6270            if (err == OK) {
6271                err = mCodec->mOMX->sendCommand(
6272                    mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting);
6273            }
6274
6275            if (err != OK) {
6276                mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6277            } else {
6278                mCodec->changeState(mCodec->mIdleToExecutingState);
6279            }
6280
6281            return true;
6282        }
6283
6284        default:
6285            return BaseState::onOMXEvent(event, data1, data2);
6286    }
6287}
6288
6289////////////////////////////////////////////////////////////////////////////////
6290
6291ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec)
6292    : BaseState(codec) {
6293}
6294
6295void ACodec::IdleToExecutingState::stateEntered() {
6296    ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
6297}
6298
6299bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
6300    switch (msg->what()) {
6301        case kWhatSetParameters:
6302        case kWhatShutdown:
6303        {
6304            mCodec->deferMessage(msg);
6305            return true;
6306        }
6307
6308        case kWhatResume:
6309        {
6310            // We'll be active soon enough.
6311            return true;
6312        }
6313
6314        case kWhatFlush:
6315        {
6316            // We haven't even started yet, so we're flushed alright...
6317            sp<AMessage> notify = mCodec->mNotify->dup();
6318            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
6319            notify->post();
6320
6321            return true;
6322        }
6323
6324        case kWhatSignalEndOfInputStream:
6325        {
6326            mCodec->onSignalEndOfInputStream();
6327            return true;
6328        }
6329
6330        default:
6331            return BaseState::onMessageReceived(msg);
6332    }
6333}
6334
6335bool ACodec::IdleToExecutingState::onOMXEvent(
6336        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
6337    switch (event) {
6338        case OMX_EventCmdComplete:
6339        {
6340            if (data1 != (OMX_U32)OMX_CommandStateSet
6341                    || data2 != (OMX_U32)OMX_StateExecuting) {
6342                ALOGE("Unexpected command completion in IdleToExecutingState: %s(%u) %s(%u)",
6343                        asString((OMX_COMMANDTYPE)data1), data1,
6344                        asString((OMX_STATETYPE)data2), data2);
6345                mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
6346                return true;
6347            }
6348
6349            mCodec->mExecutingState->resume();
6350            mCodec->changeState(mCodec->mExecutingState);
6351
6352            return true;
6353        }
6354
6355        default:
6356            return BaseState::onOMXEvent(event, data1, data2);
6357    }
6358}
6359
6360////////////////////////////////////////////////////////////////////////////////
6361
6362ACodec::ExecutingState::ExecutingState(ACodec *codec)
6363    : BaseState(codec),
6364      mActive(false) {
6365}
6366
6367ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode(
6368        OMX_U32 /* portIndex */) {
6369    return RESUBMIT_BUFFERS;
6370}
6371
6372void ACodec::ExecutingState::submitOutputMetaBuffers() {
6373    // submit as many buffers as there are input buffers with the codec
6374    // in case we are in port reconfiguring
6375    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
6376        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
6377
6378        if (info->mStatus == BufferInfo::OWNED_BY_COMPONENT) {
6379            if (mCodec->submitOutputMetadataBuffer() != OK)
6380                break;
6381        }
6382    }
6383
6384    // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
6385    mCodec->signalSubmitOutputMetadataBufferIfEOS_workaround();
6386}
6387
6388void ACodec::ExecutingState::submitRegularOutputBuffers() {
6389    bool failed = false;
6390    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
6391        BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
6392
6393        if (mCodec->mNativeWindow != NULL) {
6394            if (info->mStatus != BufferInfo::OWNED_BY_US
6395                    && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
6396                ALOGE("buffers should be owned by us or the surface");
6397                failed = true;
6398                break;
6399            }
6400
6401            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
6402                continue;
6403            }
6404        } else {
6405            if (info->mStatus != BufferInfo::OWNED_BY_US) {
6406                ALOGE("buffers should be owned by us");
6407                failed = true;
6408                break;
6409            }
6410        }
6411
6412        ALOGV("[%s] calling fillBuffer %u", mCodec->mComponentName.c_str(), info->mBufferID);
6413
6414        info->checkWriteFence("submitRegularOutputBuffers");
6415        status_t err = mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID, info->mFenceFd);
6416        info->mFenceFd = -1;
6417        if (err != OK) {
6418            failed = true;
6419            break;
6420        }
6421
6422        info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
6423    }
6424
6425    if (failed) {
6426        mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
6427    }
6428}
6429
6430void ACodec::ExecutingState::submitOutputBuffers() {
6431    submitRegularOutputBuffers();
6432    if (mCodec->storingMetadataInDecodedBuffers()) {
6433        submitOutputMetaBuffers();
6434    }
6435}
6436
6437void ACodec::ExecutingState::resume() {
6438    if (mActive) {
6439        ALOGV("[%s] We're already active, no need to resume.", mCodec->mComponentName.c_str());
6440        return;
6441    }
6442
6443    submitOutputBuffers();
6444
6445    // Post all available input buffers
6446    if (mCodec->mBuffers[kPortIndexInput].size() == 0u) {
6447        ALOGW("[%s] we don't have any input buffers to resume", mCodec->mComponentName.c_str());
6448    }
6449
6450    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); i++) {
6451        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
6452        if (info->mStatus == BufferInfo::OWNED_BY_US) {
6453            postFillThisBuffer(info);
6454        }
6455    }
6456
6457    mActive = true;
6458}
6459
6460void ACodec::ExecutingState::stateEntered() {
6461    ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
6462
6463    mCodec->mRenderTracker.clear(systemTime(CLOCK_MONOTONIC));
6464    mCodec->processDeferredMessages();
6465}
6466
6467bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) {
6468    bool handled = false;
6469
6470    switch (msg->what()) {
6471        case kWhatShutdown:
6472        {
6473            int32_t keepComponentAllocated;
6474            CHECK(msg->findInt32(
6475                        "keepComponentAllocated", &keepComponentAllocated));
6476
6477            mCodec->mShutdownInProgress = true;
6478            mCodec->mExplicitShutdown = true;
6479            mCodec->mKeepComponentAllocated = keepComponentAllocated;
6480
6481            mActive = false;
6482
6483            status_t err = mCodec->mOMX->sendCommand(
6484                    mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle);
6485            if (err != OK) {
6486                if (keepComponentAllocated) {
6487                    mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
6488                }
6489                // TODO: do some recovery here.
6490            } else {
6491                mCodec->changeState(mCodec->mExecutingToIdleState);
6492            }
6493
6494            handled = true;
6495            break;
6496        }
6497
6498        case kWhatFlush:
6499        {
6500            ALOGV("[%s] ExecutingState flushing now "
6501                 "(codec owns %zu/%zu input, %zu/%zu output).",
6502                    mCodec->mComponentName.c_str(),
6503                    mCodec->countBuffersOwnedByComponent(kPortIndexInput),
6504                    mCodec->mBuffers[kPortIndexInput].size(),
6505                    mCodec->countBuffersOwnedByComponent(kPortIndexOutput),
6506                    mCodec->mBuffers[kPortIndexOutput].size());
6507
6508            mActive = false;
6509
6510            status_t err = mCodec->mOMX->sendCommand(mCodec->mNode, OMX_CommandFlush, OMX_ALL);
6511            if (err != OK) {
6512                mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
6513            } else {
6514                mCodec->changeState(mCodec->mFlushingState);
6515            }
6516
6517            handled = true;
6518            break;
6519        }
6520
6521        case kWhatResume:
6522        {
6523            resume();
6524
6525            handled = true;
6526            break;
6527        }
6528
6529        case kWhatRequestIDRFrame:
6530        {
6531            status_t err = mCodec->requestIDRFrame();
6532            if (err != OK) {
6533                ALOGW("Requesting an IDR frame failed.");
6534            }
6535
6536            handled = true;
6537            break;
6538        }
6539
6540        case kWhatSetParameters:
6541        {
6542            sp<AMessage> params;
6543            CHECK(msg->findMessage("params", &params));
6544
6545            status_t err = mCodec->setParameters(params);
6546
6547            sp<AMessage> reply;
6548            if (msg->findMessage("reply", &reply)) {
6549                reply->setInt32("err", err);
6550                reply->post();
6551            }
6552
6553            handled = true;
6554            break;
6555        }
6556
6557        case ACodec::kWhatSignalEndOfInputStream:
6558        {
6559            mCodec->onSignalEndOfInputStream();
6560            handled = true;
6561            break;
6562        }
6563
6564        // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
6565        case kWhatSubmitOutputMetadataBufferIfEOS:
6566        {
6567            if (mCodec->mPortEOS[kPortIndexInput] &&
6568                    !mCodec->mPortEOS[kPortIndexOutput]) {
6569                status_t err = mCodec->submitOutputMetadataBuffer();
6570                if (err == OK) {
6571                    mCodec->signalSubmitOutputMetadataBufferIfEOS_workaround();
6572                }
6573            }
6574            return true;
6575        }
6576
6577        default:
6578            handled = BaseState::onMessageReceived(msg);
6579            break;
6580    }
6581
6582    return handled;
6583}
6584
6585status_t ACodec::setParameters(const sp<AMessage> &params) {
6586    int32_t videoBitrate;
6587    if (params->findInt32("video-bitrate", &videoBitrate)) {
6588        OMX_VIDEO_CONFIG_BITRATETYPE configParams;
6589        InitOMXParams(&configParams);
6590        configParams.nPortIndex = kPortIndexOutput;
6591        configParams.nEncodeBitrate = videoBitrate;
6592
6593        status_t err = mOMX->setConfig(
6594                mNode,
6595                OMX_IndexConfigVideoBitrate,
6596                &configParams,
6597                sizeof(configParams));
6598
6599        if (err != OK) {
6600            ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d",
6601                   videoBitrate, err);
6602
6603            return err;
6604        }
6605    }
6606
6607    int64_t skipFramesBeforeUs;
6608    if (params->findInt64("skip-frames-before", &skipFramesBeforeUs)) {
6609        status_t err =
6610            mOMX->setInternalOption(
6611                     mNode,
6612                     kPortIndexInput,
6613                     IOMX::INTERNAL_OPTION_START_TIME,
6614                     &skipFramesBeforeUs,
6615                     sizeof(skipFramesBeforeUs));
6616
6617        if (err != OK) {
6618            ALOGE("Failed to set parameter 'skip-frames-before' (err %d)", err);
6619            return err;
6620        }
6621    }
6622
6623    int32_t dropInputFrames;
6624    if (params->findInt32("drop-input-frames", &dropInputFrames)) {
6625        bool suspend = dropInputFrames != 0;
6626
6627        status_t err =
6628            mOMX->setInternalOption(
6629                     mNode,
6630                     kPortIndexInput,
6631                     IOMX::INTERNAL_OPTION_SUSPEND,
6632                     &suspend,
6633                     sizeof(suspend));
6634
6635        if (err != OK) {
6636            ALOGE("Failed to set parameter 'drop-input-frames' (err %d)", err);
6637            return err;
6638        }
6639    }
6640
6641    int32_t dummy;
6642    if (params->findInt32("request-sync", &dummy)) {
6643        status_t err = requestIDRFrame();
6644
6645        if (err != OK) {
6646            ALOGE("Requesting a sync frame failed w/ err %d", err);
6647            return err;
6648        }
6649    }
6650
6651    float rate;
6652    if (params->findFloat("operating-rate", &rate) && rate > 0) {
6653        status_t err = setOperatingRate(rate, mIsVideo);
6654        if (err != OK) {
6655            ALOGE("Failed to set parameter 'operating-rate' (err %d)", err);
6656            return err;
6657        }
6658    }
6659
6660    int32_t intraRefreshPeriod = 0;
6661    if (params->findInt32("intra-refresh-period", &intraRefreshPeriod)
6662            && intraRefreshPeriod > 0) {
6663        status_t err = setIntraRefreshPeriod(intraRefreshPeriod, false);
6664        if (err != OK) {
6665            ALOGI("[%s] failed setIntraRefreshPeriod. Failure is fine since this key is optional",
6666                    mComponentName.c_str());
6667            err = OK;
6668        }
6669    }
6670
6671    return OK;
6672}
6673
6674void ACodec::onSignalEndOfInputStream() {
6675    sp<AMessage> notify = mNotify->dup();
6676    notify->setInt32("what", CodecBase::kWhatSignaledInputEOS);
6677
6678    status_t err = mOMX->signalEndOfInputStream(mNode);
6679    if (err != OK) {
6680        notify->setInt32("err", err);
6681    }
6682    notify->post();
6683}
6684
6685bool ACodec::ExecutingState::onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano) {
6686    mCodec->onFrameRendered(mediaTimeUs, systemNano);
6687    return true;
6688}
6689
6690bool ACodec::ExecutingState::onOMXEvent(
6691        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
6692    switch (event) {
6693        case OMX_EventPortSettingsChanged:
6694        {
6695            CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
6696
6697            if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
6698                mCodec->mMetadataBuffersToSubmit = 0;
6699                CHECK_EQ(mCodec->mOMX->sendCommand(
6700                            mCodec->mNode,
6701                            OMX_CommandPortDisable, kPortIndexOutput),
6702                         (status_t)OK);
6703
6704                mCodec->freeOutputBuffersNotOwnedByComponent();
6705
6706                mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
6707            } else if (data2 == OMX_IndexConfigCommonOutputCrop
6708                    || data2 == OMX_IndexConfigAndroidIntraRefresh) {
6709                mCodec->mSentFormat = false;
6710
6711                if (mCodec->mTunneled) {
6712                    sp<AMessage> dummy = new AMessage(kWhatOutputBufferDrained, mCodec);
6713                    mCodec->sendFormatChange(dummy);
6714                }
6715            } else {
6716                ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08x",
6717                     mCodec->mComponentName.c_str(), data2);
6718            }
6719
6720            return true;
6721        }
6722
6723        case OMX_EventBufferFlag:
6724        {
6725            return true;
6726        }
6727
6728        default:
6729            return BaseState::onOMXEvent(event, data1, data2);
6730    }
6731}
6732
6733////////////////////////////////////////////////////////////////////////////////
6734
6735ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState(
6736        ACodec *codec)
6737    : BaseState(codec) {
6738}
6739
6740ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode(
6741        OMX_U32 portIndex) {
6742    if (portIndex == kPortIndexOutput) {
6743        return FREE_BUFFERS;
6744    }
6745
6746    CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput);
6747
6748    return RESUBMIT_BUFFERS;
6749}
6750
6751bool ACodec::OutputPortSettingsChangedState::onMessageReceived(
6752        const sp<AMessage> &msg) {
6753    bool handled = false;
6754
6755    switch (msg->what()) {
6756        case kWhatFlush:
6757        case kWhatShutdown:
6758        case kWhatResume:
6759        case kWhatSetParameters:
6760        {
6761            if (msg->what() == kWhatResume) {
6762                ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
6763            }
6764
6765            mCodec->deferMessage(msg);
6766            handled = true;
6767            break;
6768        }
6769
6770        default:
6771            handled = BaseState::onMessageReceived(msg);
6772            break;
6773    }
6774
6775    return handled;
6776}
6777
6778void ACodec::OutputPortSettingsChangedState::stateEntered() {
6779    ALOGV("[%s] Now handling output port settings change",
6780         mCodec->mComponentName.c_str());
6781}
6782
6783bool ACodec::OutputPortSettingsChangedState::onOMXFrameRendered(
6784        int64_t mediaTimeUs, nsecs_t systemNano) {
6785    mCodec->onFrameRendered(mediaTimeUs, systemNano);
6786    return true;
6787}
6788
6789bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
6790        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
6791    switch (event) {
6792        case OMX_EventCmdComplete:
6793        {
6794            if (data1 == (OMX_U32)OMX_CommandPortDisable) {
6795                if (data2 != (OMX_U32)kPortIndexOutput) {
6796                    ALOGW("ignoring EventCmdComplete CommandPortDisable for port %u", data2);
6797                    return false;
6798                }
6799
6800                ALOGV("[%s] Output port now disabled.", mCodec->mComponentName.c_str());
6801
6802                status_t err = OK;
6803                if (!mCodec->mBuffers[kPortIndexOutput].isEmpty()) {
6804                    ALOGE("disabled port should be empty, but has %zu buffers",
6805                            mCodec->mBuffers[kPortIndexOutput].size());
6806                    err = FAILED_TRANSACTION;
6807                } else {
6808                    mCodec->mDealer[kPortIndexOutput].clear();
6809                }
6810
6811                if (err == OK) {
6812                    err = mCodec->mOMX->sendCommand(
6813                            mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput);
6814                }
6815
6816                if (err == OK) {
6817                    err = mCodec->allocateBuffersOnPort(kPortIndexOutput);
6818                    ALOGE_IF(err != OK, "Failed to allocate output port buffers after port "
6819                            "reconfiguration: (%d)", err);
6820                }
6821
6822                if (err != OK) {
6823                    mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6824
6825                    // This is technically not correct, but appears to be
6826                    // the only way to free the component instance.
6827                    // Controlled transitioning from excecuting->idle
6828                    // and idle->loaded seem impossible probably because
6829                    // the output port never finishes re-enabling.
6830                    mCodec->mShutdownInProgress = true;
6831                    mCodec->mKeepComponentAllocated = false;
6832                    mCodec->changeState(mCodec->mLoadedState);
6833                }
6834
6835                return true;
6836            } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
6837                if (data2 != (OMX_U32)kPortIndexOutput) {
6838                    ALOGW("ignoring EventCmdComplete OMX_CommandPortEnable for port %u", data2);
6839                    return false;
6840                }
6841
6842                mCodec->mSentFormat = false;
6843
6844                if (mCodec->mTunneled) {
6845                    sp<AMessage> dummy = new AMessage(kWhatOutputBufferDrained, mCodec);
6846                    mCodec->sendFormatChange(dummy);
6847                }
6848
6849                ALOGV("[%s] Output port now reenabled.", mCodec->mComponentName.c_str());
6850
6851                if (mCodec->mExecutingState->active()) {
6852                    mCodec->mExecutingState->submitOutputBuffers();
6853                }
6854
6855                mCodec->changeState(mCodec->mExecutingState);
6856
6857                return true;
6858            }
6859
6860            return false;
6861        }
6862
6863        default:
6864            return false;
6865    }
6866}
6867
6868////////////////////////////////////////////////////////////////////////////////
6869
6870ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec)
6871    : BaseState(codec),
6872      mComponentNowIdle(false) {
6873}
6874
6875bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) {
6876    bool handled = false;
6877
6878    switch (msg->what()) {
6879        case kWhatFlush:
6880        {
6881            // Don't send me a flush request if you previously wanted me
6882            // to shutdown.
6883            ALOGW("Ignoring flush request in ExecutingToIdleState");
6884            break;
6885        }
6886
6887        case kWhatShutdown:
6888        {
6889            // We're already doing that...
6890
6891            handled = true;
6892            break;
6893        }
6894
6895        default:
6896            handled = BaseState::onMessageReceived(msg);
6897            break;
6898    }
6899
6900    return handled;
6901}
6902
6903void ACodec::ExecutingToIdleState::stateEntered() {
6904    ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
6905
6906    mComponentNowIdle = false;
6907    mCodec->mSentFormat = false;
6908}
6909
6910bool ACodec::ExecutingToIdleState::onOMXEvent(
6911        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
6912    switch (event) {
6913        case OMX_EventCmdComplete:
6914        {
6915            if (data1 != (OMX_U32)OMX_CommandStateSet
6916                    || data2 != (OMX_U32)OMX_StateIdle) {
6917                ALOGE("Unexpected command completion in ExecutingToIdleState: %s(%u) %s(%u)",
6918                        asString((OMX_COMMANDTYPE)data1), data1,
6919                        asString((OMX_STATETYPE)data2), data2);
6920                mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
6921                return true;
6922            }
6923
6924            mComponentNowIdle = true;
6925
6926            changeStateIfWeOwnAllBuffers();
6927
6928            return true;
6929        }
6930
6931        case OMX_EventPortSettingsChanged:
6932        case OMX_EventBufferFlag:
6933        {
6934            // We're shutting down and don't care about this anymore.
6935            return true;
6936        }
6937
6938        default:
6939            return BaseState::onOMXEvent(event, data1, data2);
6940    }
6941}
6942
6943void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
6944    if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) {
6945        status_t err = mCodec->mOMX->sendCommand(
6946                mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded);
6947        if (err == OK) {
6948            err = mCodec->freeBuffersOnPort(kPortIndexInput);
6949            status_t err2 = mCodec->freeBuffersOnPort(kPortIndexOutput);
6950            if (err == OK) {
6951                err = err2;
6952            }
6953        }
6954
6955        if ((mCodec->mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown)
6956                && mCodec->mNativeWindow != NULL) {
6957            // We push enough 1x1 blank buffers to ensure that one of
6958            // them has made it to the display.  This allows the OMX
6959            // component teardown to zero out any protected buffers
6960            // without the risk of scanning out one of those buffers.
6961            pushBlankBuffersToNativeWindow(mCodec->mNativeWindow.get());
6962        }
6963
6964        if (err != OK) {
6965            mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
6966            return;
6967        }
6968
6969        mCodec->changeState(mCodec->mIdleToLoadedState);
6970    }
6971}
6972
6973void ACodec::ExecutingToIdleState::onInputBufferFilled(
6974        const sp<AMessage> &msg) {
6975    BaseState::onInputBufferFilled(msg);
6976
6977    changeStateIfWeOwnAllBuffers();
6978}
6979
6980void ACodec::ExecutingToIdleState::onOutputBufferDrained(
6981        const sp<AMessage> &msg) {
6982    BaseState::onOutputBufferDrained(msg);
6983
6984    changeStateIfWeOwnAllBuffers();
6985}
6986
6987////////////////////////////////////////////////////////////////////////////////
6988
6989ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec)
6990    : BaseState(codec) {
6991}
6992
6993bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) {
6994    bool handled = false;
6995
6996    switch (msg->what()) {
6997        case kWhatShutdown:
6998        {
6999            // We're already doing that...
7000
7001            handled = true;
7002            break;
7003        }
7004
7005        case kWhatFlush:
7006        {
7007            // Don't send me a flush request if you previously wanted me
7008            // to shutdown.
7009            ALOGE("Got flush request in IdleToLoadedState");
7010            break;
7011        }
7012
7013        default:
7014            handled = BaseState::onMessageReceived(msg);
7015            break;
7016    }
7017
7018    return handled;
7019}
7020
7021void ACodec::IdleToLoadedState::stateEntered() {
7022    ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
7023}
7024
7025bool ACodec::IdleToLoadedState::onOMXEvent(
7026        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
7027    switch (event) {
7028        case OMX_EventCmdComplete:
7029        {
7030            if (data1 != (OMX_U32)OMX_CommandStateSet
7031                    || data2 != (OMX_U32)OMX_StateLoaded) {
7032                ALOGE("Unexpected command completion in IdleToLoadedState: %s(%u) %s(%u)",
7033                        asString((OMX_COMMANDTYPE)data1), data1,
7034                        asString((OMX_STATETYPE)data2), data2);
7035                mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
7036                return true;
7037            }
7038
7039            mCodec->changeState(mCodec->mLoadedState);
7040
7041            return true;
7042        }
7043
7044        default:
7045            return BaseState::onOMXEvent(event, data1, data2);
7046    }
7047}
7048
7049////////////////////////////////////////////////////////////////////////////////
7050
7051ACodec::FlushingState::FlushingState(ACodec *codec)
7052    : BaseState(codec) {
7053}
7054
7055void ACodec::FlushingState::stateEntered() {
7056    ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());
7057
7058    mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
7059}
7060
7061bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) {
7062    bool handled = false;
7063
7064    switch (msg->what()) {
7065        case kWhatShutdown:
7066        {
7067            mCodec->deferMessage(msg);
7068            break;
7069        }
7070
7071        case kWhatFlush:
7072        {
7073            // We're already doing this right now.
7074            handled = true;
7075            break;
7076        }
7077
7078        default:
7079            handled = BaseState::onMessageReceived(msg);
7080            break;
7081    }
7082
7083    return handled;
7084}
7085
7086bool ACodec::FlushingState::onOMXEvent(
7087        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
7088    ALOGV("[%s] FlushingState onOMXEvent(%u,%d)",
7089            mCodec->mComponentName.c_str(), event, (OMX_S32)data1);
7090
7091    switch (event) {
7092        case OMX_EventCmdComplete:
7093        {
7094            if (data1 != (OMX_U32)OMX_CommandFlush) {
7095                ALOGE("unexpected EventCmdComplete %s(%d) data2:%d in FlushingState",
7096                        asString((OMX_COMMANDTYPE)data1), data1, data2);
7097                mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
7098                return true;
7099            }
7100
7101            if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
7102                if (mFlushComplete[data2]) {
7103                    ALOGW("Flush already completed for %s port",
7104                            data2 == kPortIndexInput ? "input" : "output");
7105                    return true;
7106                }
7107                mFlushComplete[data2] = true;
7108
7109                if (mFlushComplete[kPortIndexInput] && mFlushComplete[kPortIndexOutput]) {
7110                    changeStateIfWeOwnAllBuffers();
7111                }
7112            } else if (data2 == OMX_ALL) {
7113                if (!mFlushComplete[kPortIndexInput] || !mFlushComplete[kPortIndexOutput]) {
7114                    ALOGW("received flush complete event for OMX_ALL before ports have been"
7115                            "flushed (%d/%d)",
7116                            mFlushComplete[kPortIndexInput], mFlushComplete[kPortIndexOutput]);
7117                    return false;
7118                }
7119
7120                changeStateIfWeOwnAllBuffers();
7121            } else {
7122                ALOGW("data2 not OMX_ALL but %u in EventCmdComplete CommandFlush", data2);
7123            }
7124
7125            return true;
7126        }
7127
7128        case OMX_EventPortSettingsChanged:
7129        {
7130            sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec);
7131            msg->setInt32("type", omx_message::EVENT);
7132            msg->setInt32("node", mCodec->mNode);
7133            msg->setInt32("event", event);
7134            msg->setInt32("data1", data1);
7135            msg->setInt32("data2", data2);
7136
7137            ALOGV("[%s] Deferring OMX_EventPortSettingsChanged",
7138                 mCodec->mComponentName.c_str());
7139
7140            mCodec->deferMessage(msg);
7141
7142            return true;
7143        }
7144
7145        default:
7146            return BaseState::onOMXEvent(event, data1, data2);
7147    }
7148
7149    return true;
7150}
7151
7152void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) {
7153    BaseState::onOutputBufferDrained(msg);
7154
7155    changeStateIfWeOwnAllBuffers();
7156}
7157
7158void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) {
7159    BaseState::onInputBufferFilled(msg);
7160
7161    changeStateIfWeOwnAllBuffers();
7162}
7163
7164void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() {
7165    if (mFlushComplete[kPortIndexInput]
7166            && mFlushComplete[kPortIndexOutput]
7167            && mCodec->allYourBuffersAreBelongToUs()) {
7168        // We now own all buffers except possibly those still queued with
7169        // the native window for rendering. Let's get those back as well.
7170        mCodec->waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs();
7171
7172        mCodec->mRenderTracker.clear(systemTime(CLOCK_MONOTONIC));
7173
7174        sp<AMessage> notify = mCodec->mNotify->dup();
7175        notify->setInt32("what", CodecBase::kWhatFlushCompleted);
7176        notify->post();
7177
7178        mCodec->mPortEOS[kPortIndexInput] =
7179            mCodec->mPortEOS[kPortIndexOutput] = false;
7180
7181        mCodec->mInputEOSResult = OK;
7182
7183        if (mCodec->mSkipCutBuffer != NULL) {
7184            mCodec->mSkipCutBuffer->clear();
7185        }
7186
7187        mCodec->changeState(mCodec->mExecutingState);
7188    }
7189}
7190
7191status_t ACodec::queryCapabilities(
7192        const AString &name, const AString &mime, bool isEncoder,
7193        sp<MediaCodecInfo::Capabilities> *caps) {
7194    (*caps).clear();
7195    const char *role = getComponentRole(isEncoder, mime.c_str());
7196    if (role == NULL) {
7197        return BAD_VALUE;
7198    }
7199
7200    OMXClient client;
7201    status_t err = client.connect();
7202    if (err != OK) {
7203        return err;
7204    }
7205
7206    sp<IOMX> omx = client.interface();
7207    sp<CodecObserver> observer = new CodecObserver;
7208    IOMX::node_id node = 0;
7209
7210    err = omx->allocateNode(name.c_str(), observer, NULL, &node);
7211    if (err != OK) {
7212        client.disconnect();
7213        return err;
7214    }
7215
7216    err = setComponentRole(omx, node, role);
7217    if (err != OK) {
7218        omx->freeNode(node);
7219        client.disconnect();
7220        return err;
7221    }
7222
7223    sp<MediaCodecInfo::CapabilitiesBuilder> builder = new MediaCodecInfo::CapabilitiesBuilder();
7224    bool isVideo = mime.startsWithIgnoreCase("video/");
7225
7226    if (isVideo) {
7227        OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
7228        InitOMXParams(&param);
7229        param.nPortIndex = isEncoder ? kPortIndexOutput : kPortIndexInput;
7230
7231        for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
7232            param.nProfileIndex = index;
7233            status_t err = omx->getParameter(
7234                    node, OMX_IndexParamVideoProfileLevelQuerySupported,
7235                    &param, sizeof(param));
7236            if (err != OK) {
7237                break;
7238            }
7239            builder->addProfileLevel(param.eProfile, param.eLevel);
7240
7241            if (index == kMaxIndicesToCheck) {
7242                ALOGW("[%s] stopping checking profiles after %u: %x/%x",
7243                        name.c_str(), index,
7244                        param.eProfile, param.eLevel);
7245            }
7246        }
7247
7248        // Color format query
7249        // return colors in the order reported by the OMX component
7250        // prefix "flexible" standard ones with the flexible equivalent
7251        OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat;
7252        InitOMXParams(&portFormat);
7253        portFormat.nPortIndex = isEncoder ? kPortIndexInput : kPortIndexOutput;
7254        Vector<uint32_t> supportedColors; // shadow copy to check for duplicates
7255        for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
7256            portFormat.nIndex = index;
7257            status_t err = omx->getParameter(
7258                    node, OMX_IndexParamVideoPortFormat,
7259                    &portFormat, sizeof(portFormat));
7260            if (err != OK) {
7261                break;
7262            }
7263
7264            OMX_U32 flexibleEquivalent;
7265            if (isFlexibleColorFormat(
7266                    omx, node, portFormat.eColorFormat, false /* usingNativeWindow */,
7267                    &flexibleEquivalent)) {
7268                bool marked = false;
7269                for (size_t i = 0; i < supportedColors.size(); ++i) {
7270                    if (supportedColors[i] == flexibleEquivalent) {
7271                        marked = true;
7272                        break;
7273                    }
7274                }
7275                if (!marked) {
7276                    supportedColors.push(flexibleEquivalent);
7277                    builder->addColorFormat(flexibleEquivalent);
7278                }
7279            }
7280            supportedColors.push(portFormat.eColorFormat);
7281            builder->addColorFormat(portFormat.eColorFormat);
7282
7283            if (index == kMaxIndicesToCheck) {
7284                ALOGW("[%s] stopping checking formats after %u: %s(%x)",
7285                        name.c_str(), index,
7286                        asString(portFormat.eColorFormat), portFormat.eColorFormat);
7287            }
7288        }
7289    } else if (mime.equalsIgnoreCase(MEDIA_MIMETYPE_AUDIO_AAC)) {
7290        // More audio codecs if they have profiles.
7291        OMX_AUDIO_PARAM_ANDROID_PROFILETYPE param;
7292        InitOMXParams(&param);
7293        param.nPortIndex = isEncoder ? kPortIndexOutput : kPortIndexInput;
7294        for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
7295            param.nProfileIndex = index;
7296            status_t err = omx->getParameter(
7297                    node, (OMX_INDEXTYPE)OMX_IndexParamAudioProfileQuerySupported,
7298                    &param, sizeof(param));
7299            if (err != OK) {
7300                break;
7301            }
7302            // For audio, level is ignored.
7303            builder->addProfileLevel(param.eProfile, 0 /* level */);
7304
7305            if (index == kMaxIndicesToCheck) {
7306                ALOGW("[%s] stopping checking profiles after %u: %x",
7307                        name.c_str(), index,
7308                        param.eProfile);
7309            }
7310        }
7311
7312        // NOTE: Without Android extensions, OMX does not provide a way to query
7313        // AAC profile support
7314        if (param.nProfileIndex == 0) {
7315            ALOGW("component %s doesn't support profile query.", name.c_str());
7316        }
7317    }
7318
7319    if (isVideo && !isEncoder) {
7320        native_handle_t *sidebandHandle = NULL;
7321        if (omx->configureVideoTunnelMode(
7322                node, kPortIndexOutput, OMX_TRUE, 0, &sidebandHandle) == OK) {
7323            // tunneled playback includes adaptive playback
7324            builder->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback
7325                    | MediaCodecInfo::Capabilities::kFlagSupportsTunneledPlayback);
7326        } else if (omx->storeMetaDataInBuffers(
7327                node, kPortIndexOutput, OMX_TRUE) == OK ||
7328            omx->prepareForAdaptivePlayback(
7329                node, kPortIndexOutput, OMX_TRUE,
7330                1280 /* width */, 720 /* height */) == OK) {
7331            builder->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback);
7332        }
7333    }
7334
7335    if (isVideo && isEncoder) {
7336        OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE params;
7337        InitOMXParams(&params);
7338        params.nPortIndex = kPortIndexOutput;
7339        // TODO: should we verify if fallback is supported?
7340        if (omx->getConfig(
7341                node, (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh,
7342                &params, sizeof(params)) == OK) {
7343            builder->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsIntraRefresh);
7344        }
7345    }
7346
7347    *caps = builder;
7348    omx->freeNode(node);
7349    client.disconnect();
7350    return OK;
7351}
7352
7353// These are supposed be equivalent to the logic in
7354// "audio_channel_out_mask_from_count".
7355//static
7356status_t ACodec::getOMXChannelMapping(size_t numChannels, OMX_AUDIO_CHANNELTYPE map[]) {
7357    switch (numChannels) {
7358        case 1:
7359            map[0] = OMX_AUDIO_ChannelCF;
7360            break;
7361        case 2:
7362            map[0] = OMX_AUDIO_ChannelLF;
7363            map[1] = OMX_AUDIO_ChannelRF;
7364            break;
7365        case 3:
7366            map[0] = OMX_AUDIO_ChannelLF;
7367            map[1] = OMX_AUDIO_ChannelRF;
7368            map[2] = OMX_AUDIO_ChannelCF;
7369            break;
7370        case 4:
7371            map[0] = OMX_AUDIO_ChannelLF;
7372            map[1] = OMX_AUDIO_ChannelRF;
7373            map[2] = OMX_AUDIO_ChannelLR;
7374            map[3] = OMX_AUDIO_ChannelRR;
7375            break;
7376        case 5:
7377            map[0] = OMX_AUDIO_ChannelLF;
7378            map[1] = OMX_AUDIO_ChannelRF;
7379            map[2] = OMX_AUDIO_ChannelCF;
7380            map[3] = OMX_AUDIO_ChannelLR;
7381            map[4] = OMX_AUDIO_ChannelRR;
7382            break;
7383        case 6:
7384            map[0] = OMX_AUDIO_ChannelLF;
7385            map[1] = OMX_AUDIO_ChannelRF;
7386            map[2] = OMX_AUDIO_ChannelCF;
7387            map[3] = OMX_AUDIO_ChannelLFE;
7388            map[4] = OMX_AUDIO_ChannelLR;
7389            map[5] = OMX_AUDIO_ChannelRR;
7390            break;
7391        case 7:
7392            map[0] = OMX_AUDIO_ChannelLF;
7393            map[1] = OMX_AUDIO_ChannelRF;
7394            map[2] = OMX_AUDIO_ChannelCF;
7395            map[3] = OMX_AUDIO_ChannelLFE;
7396            map[4] = OMX_AUDIO_ChannelLR;
7397            map[5] = OMX_AUDIO_ChannelRR;
7398            map[6] = OMX_AUDIO_ChannelCS;
7399            break;
7400        case 8:
7401            map[0] = OMX_AUDIO_ChannelLF;
7402            map[1] = OMX_AUDIO_ChannelRF;
7403            map[2] = OMX_AUDIO_ChannelCF;
7404            map[3] = OMX_AUDIO_ChannelLFE;
7405            map[4] = OMX_AUDIO_ChannelLR;
7406            map[5] = OMX_AUDIO_ChannelRR;
7407            map[6] = OMX_AUDIO_ChannelLS;
7408            map[7] = OMX_AUDIO_ChannelRS;
7409            break;
7410        default:
7411            return -EINVAL;
7412    }
7413
7414    return OK;
7415}
7416
7417}  // namespace android
7418