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