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