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