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