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