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