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