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