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