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