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