ACodec.cpp revision 201d8d400eb037547f4f476a838475b13a446007
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    ALOGI("setupVideoEncoder succeeded");
2861
2862    return err;
2863}
2864
2865status_t ACodec::setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode) {
2866    OMX_VIDEO_PARAM_INTRAREFRESHTYPE params;
2867    InitOMXParams(&params);
2868    params.nPortIndex = kPortIndexOutput;
2869
2870    params.eRefreshMode = static_cast<OMX_VIDEO_INTRAREFRESHTYPE>(mode);
2871
2872    if (params.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic ||
2873            params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) {
2874        int32_t mbs;
2875        if (!msg->findInt32("intra-refresh-CIR-mbs", &mbs)) {
2876            return INVALID_OPERATION;
2877        }
2878        params.nCirMBs = mbs;
2879    }
2880
2881    if (params.eRefreshMode == OMX_VIDEO_IntraRefreshAdaptive ||
2882            params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) {
2883        int32_t mbs;
2884        if (!msg->findInt32("intra-refresh-AIR-mbs", &mbs)) {
2885            return INVALID_OPERATION;
2886        }
2887        params.nAirMBs = mbs;
2888
2889        int32_t ref;
2890        if (!msg->findInt32("intra-refresh-AIR-ref", &ref)) {
2891            return INVALID_OPERATION;
2892        }
2893        params.nAirRef = ref;
2894    }
2895
2896    status_t err = mOMX->setParameter(
2897            mNode, OMX_IndexParamVideoIntraRefresh,
2898            &params, sizeof(params));
2899    return err;
2900}
2901
2902static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) {
2903    if (iFramesInterval < 0) {
2904        return 0xFFFFFFFF;
2905    } else if (iFramesInterval == 0) {
2906        return 0;
2907    }
2908    OMX_U32 ret = frameRate * iFramesInterval;
2909    return ret;
2910}
2911
2912static OMX_VIDEO_CONTROLRATETYPE getBitrateMode(const sp<AMessage> &msg) {
2913    int32_t tmp;
2914    if (!msg->findInt32("bitrate-mode", &tmp)) {
2915        return OMX_Video_ControlRateVariable;
2916    }
2917
2918    return static_cast<OMX_VIDEO_CONTROLRATETYPE>(tmp);
2919}
2920
2921status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) {
2922    int32_t bitrate, iFrameInterval;
2923    if (!msg->findInt32("bitrate", &bitrate)
2924            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
2925        return INVALID_OPERATION;
2926    }
2927
2928    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
2929
2930    float frameRate;
2931    if (!msg->findFloat("frame-rate", &frameRate)) {
2932        int32_t tmp;
2933        if (!msg->findInt32("frame-rate", &tmp)) {
2934            return INVALID_OPERATION;
2935        }
2936        frameRate = (float)tmp;
2937    }
2938
2939    OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type;
2940    InitOMXParams(&mpeg4type);
2941    mpeg4type.nPortIndex = kPortIndexOutput;
2942
2943    status_t err = mOMX->getParameter(
2944            mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
2945
2946    if (err != OK) {
2947        return err;
2948    }
2949
2950    mpeg4type.nSliceHeaderSpacing = 0;
2951    mpeg4type.bSVH = OMX_FALSE;
2952    mpeg4type.bGov = OMX_FALSE;
2953
2954    mpeg4type.nAllowedPictureTypes =
2955        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
2956
2957    mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
2958    if (mpeg4type.nPFrames == 0) {
2959        mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
2960    }
2961    mpeg4type.nBFrames = 0;
2962    mpeg4type.nIDCVLCThreshold = 0;
2963    mpeg4type.bACPred = OMX_TRUE;
2964    mpeg4type.nMaxPacketSize = 256;
2965    mpeg4type.nTimeIncRes = 1000;
2966    mpeg4type.nHeaderExtension = 0;
2967    mpeg4type.bReversibleVLC = OMX_FALSE;
2968
2969    int32_t profile;
2970    if (msg->findInt32("profile", &profile)) {
2971        int32_t level;
2972        if (!msg->findInt32("level", &level)) {
2973            return INVALID_OPERATION;
2974        }
2975
2976        err = verifySupportForProfileAndLevel(profile, level);
2977
2978        if (err != OK) {
2979            return err;
2980        }
2981
2982        mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile);
2983        mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level);
2984    }
2985
2986    err = mOMX->setParameter(
2987            mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
2988
2989    if (err != OK) {
2990        return err;
2991    }
2992
2993    err = configureBitrate(bitrate, bitrateMode);
2994
2995    if (err != OK) {
2996        return err;
2997    }
2998
2999    return setupErrorCorrectionParameters();
3000}
3001
3002status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) {
3003    int32_t bitrate, iFrameInterval;
3004    if (!msg->findInt32("bitrate", &bitrate)
3005            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
3006        return INVALID_OPERATION;
3007    }
3008
3009    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
3010
3011    float frameRate;
3012    if (!msg->findFloat("frame-rate", &frameRate)) {
3013        int32_t tmp;
3014        if (!msg->findInt32("frame-rate", &tmp)) {
3015            return INVALID_OPERATION;
3016        }
3017        frameRate = (float)tmp;
3018    }
3019
3020    OMX_VIDEO_PARAM_H263TYPE h263type;
3021    InitOMXParams(&h263type);
3022    h263type.nPortIndex = kPortIndexOutput;
3023
3024    status_t err = mOMX->getParameter(
3025            mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
3026
3027    if (err != OK) {
3028        return err;
3029    }
3030
3031    h263type.nAllowedPictureTypes =
3032        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
3033
3034    h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
3035    if (h263type.nPFrames == 0) {
3036        h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
3037    }
3038    h263type.nBFrames = 0;
3039
3040    int32_t profile;
3041    if (msg->findInt32("profile", &profile)) {
3042        int32_t level;
3043        if (!msg->findInt32("level", &level)) {
3044            return INVALID_OPERATION;
3045        }
3046
3047        err = verifySupportForProfileAndLevel(profile, level);
3048
3049        if (err != OK) {
3050            return err;
3051        }
3052
3053        h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile);
3054        h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level);
3055    }
3056
3057    h263type.bPLUSPTYPEAllowed = OMX_FALSE;
3058    h263type.bForceRoundingTypeToZero = OMX_FALSE;
3059    h263type.nPictureHeaderRepetition = 0;
3060    h263type.nGOBHeaderInterval = 0;
3061
3062    err = mOMX->setParameter(
3063            mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
3064
3065    if (err != OK) {
3066        return err;
3067    }
3068
3069    err = configureBitrate(bitrate, bitrateMode);
3070
3071    if (err != OK) {
3072        return err;
3073    }
3074
3075    return setupErrorCorrectionParameters();
3076}
3077
3078// static
3079int /* OMX_VIDEO_AVCLEVELTYPE */ ACodec::getAVCLevelFor(
3080        int width, int height, int rate, int bitrate,
3081        OMX_VIDEO_AVCPROFILETYPE profile) {
3082    // convert bitrate to main/baseline profile kbps equivalent
3083    switch (profile) {
3084        case OMX_VIDEO_AVCProfileHigh10:
3085            bitrate = divUp(bitrate, 3000); break;
3086        case OMX_VIDEO_AVCProfileHigh:
3087            bitrate = divUp(bitrate, 1250); break;
3088        default:
3089            bitrate = divUp(bitrate, 1000); break;
3090    }
3091
3092    // convert size and rate to MBs
3093    width = divUp(width, 16);
3094    height = divUp(height, 16);
3095    int mbs = width * height;
3096    rate *= mbs;
3097    int maxDimension = max(width, height);
3098
3099    static const int limits[][5] = {
3100        /*   MBps     MB   dim  bitrate        level */
3101        {    1485,    99,  28,     64, OMX_VIDEO_AVCLevel1  },
3102        {    1485,    99,  28,    128, OMX_VIDEO_AVCLevel1b },
3103        {    3000,   396,  56,    192, OMX_VIDEO_AVCLevel11 },
3104        {    6000,   396,  56,    384, OMX_VIDEO_AVCLevel12 },
3105        {   11880,   396,  56,    768, OMX_VIDEO_AVCLevel13 },
3106        {   11880,   396,  56,   2000, OMX_VIDEO_AVCLevel2  },
3107        {   19800,   792,  79,   4000, OMX_VIDEO_AVCLevel21 },
3108        {   20250,  1620, 113,   4000, OMX_VIDEO_AVCLevel22 },
3109        {   40500,  1620, 113,  10000, OMX_VIDEO_AVCLevel3  },
3110        {  108000,  3600, 169,  14000, OMX_VIDEO_AVCLevel31 },
3111        {  216000,  5120, 202,  20000, OMX_VIDEO_AVCLevel32 },
3112        {  245760,  8192, 256,  20000, OMX_VIDEO_AVCLevel4  },
3113        {  245760,  8192, 256,  50000, OMX_VIDEO_AVCLevel41 },
3114        {  522240,  8704, 263,  50000, OMX_VIDEO_AVCLevel42 },
3115        {  589824, 22080, 420, 135000, OMX_VIDEO_AVCLevel5  },
3116        {  983040, 36864, 543, 240000, OMX_VIDEO_AVCLevel51 },
3117        { 2073600, 36864, 543, 240000, OMX_VIDEO_AVCLevel52 },
3118    };
3119
3120    for (size_t i = 0; i < ARRAY_SIZE(limits); i++) {
3121        const int (&limit)[5] = limits[i];
3122        if (rate <= limit[0] && mbs <= limit[1] && maxDimension <= limit[2]
3123                && bitrate <= limit[3]) {
3124            return limit[4];
3125        }
3126    }
3127    return 0;
3128}
3129
3130status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) {
3131    int32_t bitrate, iFrameInterval;
3132    if (!msg->findInt32("bitrate", &bitrate)
3133            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
3134        return INVALID_OPERATION;
3135    }
3136
3137    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
3138
3139    float frameRate;
3140    if (!msg->findFloat("frame-rate", &frameRate)) {
3141        int32_t tmp;
3142        if (!msg->findInt32("frame-rate", &tmp)) {
3143            return INVALID_OPERATION;
3144        }
3145        frameRate = (float)tmp;
3146    }
3147
3148    status_t err = OK;
3149    int32_t intraRefreshMode = 0;
3150    if (msg->findInt32("intra-refresh-mode", &intraRefreshMode)) {
3151        err = setCyclicIntraMacroblockRefresh(msg, intraRefreshMode);
3152        if (err != OK) {
3153            ALOGE("Setting intra macroblock refresh mode (%d) failed: 0x%x",
3154                    err, intraRefreshMode);
3155            return err;
3156        }
3157    }
3158
3159    OMX_VIDEO_PARAM_AVCTYPE h264type;
3160    InitOMXParams(&h264type);
3161    h264type.nPortIndex = kPortIndexOutput;
3162
3163    err = mOMX->getParameter(
3164            mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
3165
3166    if (err != OK) {
3167        return err;
3168    }
3169
3170    h264type.nAllowedPictureTypes =
3171        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
3172
3173    int32_t profile;
3174    if (msg->findInt32("profile", &profile)) {
3175        int32_t level;
3176        if (!msg->findInt32("level", &level)) {
3177            return INVALID_OPERATION;
3178        }
3179
3180        err = verifySupportForProfileAndLevel(profile, level);
3181
3182        if (err != OK) {
3183            return err;
3184        }
3185
3186        h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile);
3187        h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level);
3188    }
3189
3190    // XXX
3191    if (h264type.eProfile != OMX_VIDEO_AVCProfileBaseline) {
3192        ALOGW("Use baseline profile instead of %d for AVC recording",
3193            h264type.eProfile);
3194        h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
3195    }
3196
3197    if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
3198        h264type.nSliceHeaderSpacing = 0;
3199        h264type.bUseHadamard = OMX_TRUE;
3200        h264type.nRefFrames = 1;
3201        h264type.nBFrames = 0;
3202        h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
3203        if (h264type.nPFrames == 0) {
3204            h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
3205        }
3206        h264type.nRefIdx10ActiveMinus1 = 0;
3207        h264type.nRefIdx11ActiveMinus1 = 0;
3208        h264type.bEntropyCodingCABAC = OMX_FALSE;
3209        h264type.bWeightedPPrediction = OMX_FALSE;
3210        h264type.bconstIpred = OMX_FALSE;
3211        h264type.bDirect8x8Inference = OMX_FALSE;
3212        h264type.bDirectSpatialTemporal = OMX_FALSE;
3213        h264type.nCabacInitIdc = 0;
3214    }
3215
3216    if (h264type.nBFrames != 0) {
3217        h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
3218    }
3219
3220    h264type.bEnableUEP = OMX_FALSE;
3221    h264type.bEnableFMO = OMX_FALSE;
3222    h264type.bEnableASO = OMX_FALSE;
3223    h264type.bEnableRS = OMX_FALSE;
3224    h264type.bFrameMBsOnly = OMX_TRUE;
3225    h264type.bMBAFF = OMX_FALSE;
3226    h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
3227
3228    err = mOMX->setParameter(
3229            mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
3230
3231    if (err != OK) {
3232        return err;
3233    }
3234
3235    return configureBitrate(bitrate, bitrateMode);
3236}
3237
3238status_t ACodec::setupHEVCEncoderParameters(const sp<AMessage> &msg) {
3239    int32_t bitrate, iFrameInterval;
3240    if (!msg->findInt32("bitrate", &bitrate)
3241            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
3242        return INVALID_OPERATION;
3243    }
3244
3245    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
3246
3247    float frameRate;
3248    if (!msg->findFloat("frame-rate", &frameRate)) {
3249        int32_t tmp;
3250        if (!msg->findInt32("frame-rate", &tmp)) {
3251            return INVALID_OPERATION;
3252        }
3253        frameRate = (float)tmp;
3254    }
3255
3256    OMX_VIDEO_PARAM_HEVCTYPE hevcType;
3257    InitOMXParams(&hevcType);
3258    hevcType.nPortIndex = kPortIndexOutput;
3259
3260    status_t err = OK;
3261    err = mOMX->getParameter(
3262            mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
3263    if (err != OK) {
3264        return err;
3265    }
3266
3267    int32_t profile;
3268    if (msg->findInt32("profile", &profile)) {
3269        int32_t level;
3270        if (!msg->findInt32("level", &level)) {
3271            return INVALID_OPERATION;
3272        }
3273
3274        err = verifySupportForProfileAndLevel(profile, level);
3275        if (err != OK) {
3276            return err;
3277        }
3278
3279        hevcType.eProfile = static_cast<OMX_VIDEO_HEVCPROFILETYPE>(profile);
3280        hevcType.eLevel = static_cast<OMX_VIDEO_HEVCLEVELTYPE>(level);
3281    }
3282
3283    // TODO: Need OMX structure definition for setting iFrameInterval
3284
3285    err = mOMX->setParameter(
3286            mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
3287    if (err != OK) {
3288        return err;
3289    }
3290
3291    return configureBitrate(bitrate, bitrateMode);
3292}
3293
3294status_t ACodec::setupVPXEncoderParameters(const sp<AMessage> &msg) {
3295    int32_t bitrate;
3296    int32_t iFrameInterval = 0;
3297    size_t tsLayers = 0;
3298    OMX_VIDEO_ANDROID_VPXTEMPORALLAYERPATTERNTYPE pattern =
3299        OMX_VIDEO_VPXTemporalLayerPatternNone;
3300    static const uint32_t kVp8LayerRateAlloction
3301        [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS]
3302        [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS] = {
3303        {100, 100, 100},  // 1 layer
3304        { 60, 100, 100},  // 2 layers {60%, 40%}
3305        { 40,  60, 100},  // 3 layers {40%, 20%, 40%}
3306    };
3307    if (!msg->findInt32("bitrate", &bitrate)) {
3308        return INVALID_OPERATION;
3309    }
3310    msg->findInt32("i-frame-interval", &iFrameInterval);
3311
3312    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
3313
3314    float frameRate;
3315    if (!msg->findFloat("frame-rate", &frameRate)) {
3316        int32_t tmp;
3317        if (!msg->findInt32("frame-rate", &tmp)) {
3318            return INVALID_OPERATION;
3319        }
3320        frameRate = (float)tmp;
3321    }
3322
3323    AString tsSchema;
3324    if (msg->findString("ts-schema", &tsSchema)) {
3325        if (tsSchema == "webrtc.vp8.1-layer") {
3326            pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
3327            tsLayers = 1;
3328        } else if (tsSchema == "webrtc.vp8.2-layer") {
3329            pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
3330            tsLayers = 2;
3331        } else if (tsSchema == "webrtc.vp8.3-layer") {
3332            pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
3333            tsLayers = 3;
3334        } else {
3335            ALOGW("Unsupported ts-schema [%s]", tsSchema.c_str());
3336        }
3337    }
3338
3339    OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type;
3340    InitOMXParams(&vp8type);
3341    vp8type.nPortIndex = kPortIndexOutput;
3342    status_t err = mOMX->getParameter(
3343            mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
3344            &vp8type, sizeof(vp8type));
3345
3346    if (err == OK) {
3347        if (iFrameInterval > 0) {
3348            vp8type.nKeyFrameInterval = setPFramesSpacing(iFrameInterval, frameRate);
3349        }
3350        vp8type.eTemporalPattern = pattern;
3351        vp8type.nTemporalLayerCount = tsLayers;
3352        if (tsLayers > 0) {
3353            for (size_t i = 0; i < OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS; i++) {
3354                vp8type.nTemporalLayerBitrateRatio[i] =
3355                    kVp8LayerRateAlloction[tsLayers - 1][i];
3356            }
3357        }
3358        if (bitrateMode == OMX_Video_ControlRateConstant) {
3359            vp8type.nMinQuantizer = 2;
3360            vp8type.nMaxQuantizer = 63;
3361        }
3362
3363        err = mOMX->setParameter(
3364                mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
3365                &vp8type, sizeof(vp8type));
3366        if (err != OK) {
3367            ALOGW("Extended VP8 parameters set failed: %d", err);
3368        }
3369    }
3370
3371    return configureBitrate(bitrate, bitrateMode);
3372}
3373
3374status_t ACodec::verifySupportForProfileAndLevel(
3375        int32_t profile, int32_t level) {
3376    OMX_VIDEO_PARAM_PROFILELEVELTYPE params;
3377    InitOMXParams(&params);
3378    params.nPortIndex = kPortIndexOutput;
3379
3380    for (params.nProfileIndex = 0;; ++params.nProfileIndex) {
3381        status_t err = mOMX->getParameter(
3382                mNode,
3383                OMX_IndexParamVideoProfileLevelQuerySupported,
3384                &params,
3385                sizeof(params));
3386
3387        if (err != OK) {
3388            return err;
3389        }
3390
3391        int32_t supportedProfile = static_cast<int32_t>(params.eProfile);
3392        int32_t supportedLevel = static_cast<int32_t>(params.eLevel);
3393
3394        if (profile == supportedProfile && level <= supportedLevel) {
3395            return OK;
3396        }
3397    }
3398}
3399
3400status_t ACodec::configureBitrate(
3401        int32_t bitrate, OMX_VIDEO_CONTROLRATETYPE bitrateMode) {
3402    OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
3403    InitOMXParams(&bitrateType);
3404    bitrateType.nPortIndex = kPortIndexOutput;
3405
3406    status_t err = mOMX->getParameter(
3407            mNode, OMX_IndexParamVideoBitrate,
3408            &bitrateType, sizeof(bitrateType));
3409
3410    if (err != OK) {
3411        return err;
3412    }
3413
3414    bitrateType.eControlRate = bitrateMode;
3415    bitrateType.nTargetBitrate = bitrate;
3416
3417    return mOMX->setParameter(
3418            mNode, OMX_IndexParamVideoBitrate,
3419            &bitrateType, sizeof(bitrateType));
3420}
3421
3422status_t ACodec::setupErrorCorrectionParameters() {
3423    OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
3424    InitOMXParams(&errorCorrectionType);
3425    errorCorrectionType.nPortIndex = kPortIndexOutput;
3426
3427    status_t err = mOMX->getParameter(
3428            mNode, OMX_IndexParamVideoErrorCorrection,
3429            &errorCorrectionType, sizeof(errorCorrectionType));
3430
3431    if (err != OK) {
3432        return OK;  // Optional feature. Ignore this failure
3433    }
3434
3435    errorCorrectionType.bEnableHEC = OMX_FALSE;
3436    errorCorrectionType.bEnableResync = OMX_TRUE;
3437    errorCorrectionType.nResynchMarkerSpacing = 256;
3438    errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
3439    errorCorrectionType.bEnableRVLC = OMX_FALSE;
3440
3441    return mOMX->setParameter(
3442            mNode, OMX_IndexParamVideoErrorCorrection,
3443            &errorCorrectionType, sizeof(errorCorrectionType));
3444}
3445
3446status_t ACodec::setVideoFormatOnPort(
3447        OMX_U32 portIndex,
3448        int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat,
3449        float frameRate) {
3450    OMX_PARAM_PORTDEFINITIONTYPE def;
3451    InitOMXParams(&def);
3452    def.nPortIndex = portIndex;
3453
3454    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
3455
3456    status_t err = mOMX->getParameter(
3457            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
3458    if (err != OK) {
3459        return err;
3460    }
3461
3462    if (portIndex == kPortIndexInput) {
3463        // XXX Need a (much) better heuristic to compute input buffer sizes.
3464        const size_t X = 64 * 1024;
3465        if (def.nBufferSize < X) {
3466            def.nBufferSize = X;
3467        }
3468    }
3469
3470    if (def.eDomain != OMX_PortDomainVideo) {
3471        ALOGE("expected video port, got %s(%d)", asString(def.eDomain), def.eDomain);
3472        return FAILED_TRANSACTION;
3473    }
3474
3475    video_def->nFrameWidth = width;
3476    video_def->nFrameHeight = height;
3477
3478    if (portIndex == kPortIndexInput) {
3479        video_def->eCompressionFormat = compressionFormat;
3480        video_def->eColorFormat = OMX_COLOR_FormatUnused;
3481        if (frameRate >= 0) {
3482            video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f);
3483        }
3484    }
3485
3486    err = mOMX->setParameter(
3487            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
3488
3489    return err;
3490}
3491
3492status_t ACodec::initNativeWindow() {
3493    if (mNativeWindow != NULL) {
3494        return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE);
3495    }
3496
3497    mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE);
3498    return OK;
3499}
3500
3501size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const {
3502    size_t n = 0;
3503
3504    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
3505        const BufferInfo &info = mBuffers[portIndex].itemAt(i);
3506
3507        if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) {
3508            ++n;
3509        }
3510    }
3511
3512    return n;
3513}
3514
3515size_t ACodec::countBuffersOwnedByNativeWindow() const {
3516    size_t n = 0;
3517
3518    for (size_t i = 0; i < mBuffers[kPortIndexOutput].size(); ++i) {
3519        const BufferInfo &info = mBuffers[kPortIndexOutput].itemAt(i);
3520
3521        if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
3522            ++n;
3523        }
3524    }
3525
3526    return n;
3527}
3528
3529void ACodec::waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs() {
3530    if (mNativeWindow == NULL) {
3531        return;
3532    }
3533
3534    while (countBuffersOwnedByNativeWindow() > mNumUndequeuedBuffers
3535            && dequeueBufferFromNativeWindow() != NULL) {
3536        // these buffers will be submitted as regular buffers; account for this
3537        if (mStoreMetaDataInOutputBuffers && mMetaDataBuffersToSubmit > 0) {
3538            --mMetaDataBuffersToSubmit;
3539        }
3540    }
3541}
3542
3543bool ACodec::allYourBuffersAreBelongToUs(
3544        OMX_U32 portIndex) {
3545    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
3546        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
3547
3548        if (info->mStatus != BufferInfo::OWNED_BY_US
3549                && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
3550            ALOGV("[%s] Buffer %u on port %u still has status %d",
3551                    mComponentName.c_str(),
3552                    info->mBufferID, portIndex, info->mStatus);
3553            return false;
3554        }
3555    }
3556
3557    return true;
3558}
3559
3560bool ACodec::allYourBuffersAreBelongToUs() {
3561    return allYourBuffersAreBelongToUs(kPortIndexInput)
3562        && allYourBuffersAreBelongToUs(kPortIndexOutput);
3563}
3564
3565void ACodec::deferMessage(const sp<AMessage> &msg) {
3566    mDeferredQueue.push_back(msg);
3567}
3568
3569void ACodec::processDeferredMessages() {
3570    List<sp<AMessage> > queue = mDeferredQueue;
3571    mDeferredQueue.clear();
3572
3573    List<sp<AMessage> >::iterator it = queue.begin();
3574    while (it != queue.end()) {
3575        onMessageReceived(*it++);
3576    }
3577}
3578
3579// static
3580bool ACodec::describeDefaultColorFormat(DescribeColorFormatParams &params) {
3581    MediaImage &image = params.sMediaImage;
3582    memset(&image, 0, sizeof(image));
3583
3584    image.mType = MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
3585    image.mNumPlanes = 0;
3586
3587    const OMX_COLOR_FORMATTYPE fmt = params.eColorFormat;
3588    image.mWidth = params.nFrameWidth;
3589    image.mHeight = params.nFrameHeight;
3590
3591    // only supporting YUV420
3592    if (fmt != OMX_COLOR_FormatYUV420Planar &&
3593        fmt != OMX_COLOR_FormatYUV420PackedPlanar &&
3594        fmt != OMX_COLOR_FormatYUV420SemiPlanar &&
3595        fmt != OMX_COLOR_FormatYUV420PackedSemiPlanar &&
3596        fmt != HAL_PIXEL_FORMAT_YV12) {
3597        ALOGW("do not know color format 0x%x = %d", fmt, fmt);
3598        return false;
3599    }
3600
3601    // TEMPORARY FIX for some vendors that advertise sliceHeight as 0
3602    if (params.nStride != 0 && params.nSliceHeight == 0) {
3603        ALOGW("using sliceHeight=%u instead of what codec advertised (=0)",
3604                params.nFrameHeight);
3605        params.nSliceHeight = params.nFrameHeight;
3606    }
3607
3608    // we need stride and slice-height to be non-zero
3609    if (params.nStride == 0 || params.nSliceHeight == 0) {
3610        ALOGW("cannot describe color format 0x%x = %d with stride=%u and sliceHeight=%u",
3611                fmt, fmt, params.nStride, params.nSliceHeight);
3612        return false;
3613    }
3614
3615    // set-up YUV format
3616    image.mType = MediaImage::MEDIA_IMAGE_TYPE_YUV;
3617    image.mNumPlanes = 3;
3618    image.mBitDepth = 8;
3619    image.mPlane[image.Y].mOffset = 0;
3620    image.mPlane[image.Y].mColInc = 1;
3621    image.mPlane[image.Y].mRowInc = params.nStride;
3622    image.mPlane[image.Y].mHorizSubsampling = 1;
3623    image.mPlane[image.Y].mVertSubsampling = 1;
3624
3625    switch ((int)fmt) {
3626        case HAL_PIXEL_FORMAT_YV12:
3627            if (params.bUsingNativeBuffers) {
3628                size_t ystride = align(params.nStride, 16);
3629                size_t cstride = align(params.nStride / 2, 16);
3630                image.mPlane[image.Y].mRowInc = ystride;
3631
3632                image.mPlane[image.V].mOffset = ystride * params.nSliceHeight;
3633                image.mPlane[image.V].mColInc = 1;
3634                image.mPlane[image.V].mRowInc = cstride;
3635                image.mPlane[image.V].mHorizSubsampling = 2;
3636                image.mPlane[image.V].mVertSubsampling = 2;
3637
3638                image.mPlane[image.U].mOffset = image.mPlane[image.V].mOffset
3639                        + (cstride * params.nSliceHeight / 2);
3640                image.mPlane[image.U].mColInc = 1;
3641                image.mPlane[image.U].mRowInc = cstride;
3642                image.mPlane[image.U].mHorizSubsampling = 2;
3643                image.mPlane[image.U].mVertSubsampling = 2;
3644                break;
3645            } else {
3646                // fall through as YV12 is used for YUV420Planar by some codecs
3647            }
3648
3649        case OMX_COLOR_FormatYUV420Planar:
3650        case OMX_COLOR_FormatYUV420PackedPlanar:
3651            image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight;
3652            image.mPlane[image.U].mColInc = 1;
3653            image.mPlane[image.U].mRowInc = params.nStride / 2;
3654            image.mPlane[image.U].mHorizSubsampling = 2;
3655            image.mPlane[image.U].mVertSubsampling = 2;
3656
3657            image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset
3658                    + (params.nStride * params.nSliceHeight / 4);
3659            image.mPlane[image.V].mColInc = 1;
3660            image.mPlane[image.V].mRowInc = params.nStride / 2;
3661            image.mPlane[image.V].mHorizSubsampling = 2;
3662            image.mPlane[image.V].mVertSubsampling = 2;
3663            break;
3664
3665        case OMX_COLOR_FormatYUV420SemiPlanar:
3666            // FIXME: NV21 for sw-encoder, NV12 for decoder and hw-encoder
3667        case OMX_COLOR_FormatYUV420PackedSemiPlanar:
3668            // NV12
3669            image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight;
3670            image.mPlane[image.U].mColInc = 2;
3671            image.mPlane[image.U].mRowInc = params.nStride;
3672            image.mPlane[image.U].mHorizSubsampling = 2;
3673            image.mPlane[image.U].mVertSubsampling = 2;
3674
3675            image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset + 1;
3676            image.mPlane[image.V].mColInc = 2;
3677            image.mPlane[image.V].mRowInc = params.nStride;
3678            image.mPlane[image.V].mHorizSubsampling = 2;
3679            image.mPlane[image.V].mVertSubsampling = 2;
3680            break;
3681
3682        default:
3683            TRESPASS();
3684    }
3685    return true;
3686}
3687
3688// static
3689bool ACodec::describeColorFormat(
3690        const sp<IOMX> &omx, IOMX::node_id node,
3691        DescribeColorFormatParams &describeParams)
3692{
3693    OMX_INDEXTYPE describeColorFormatIndex;
3694    if (omx->getExtensionIndex(
3695            node, "OMX.google.android.index.describeColorFormat",
3696            &describeColorFormatIndex) != OK ||
3697        omx->getParameter(
3698            node, describeColorFormatIndex,
3699            &describeParams, sizeof(describeParams)) != OK) {
3700        return describeDefaultColorFormat(describeParams);
3701    }
3702    return describeParams.sMediaImage.mType !=
3703            MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
3704}
3705
3706// static
3707bool ACodec::isFlexibleColorFormat(
3708         const sp<IOMX> &omx, IOMX::node_id node,
3709         uint32_t colorFormat, bool usingNativeBuffers, OMX_U32 *flexibleEquivalent) {
3710    DescribeColorFormatParams describeParams;
3711    InitOMXParams(&describeParams);
3712    describeParams.eColorFormat = (OMX_COLOR_FORMATTYPE)colorFormat;
3713    // reasonable dummy values
3714    describeParams.nFrameWidth = 128;
3715    describeParams.nFrameHeight = 128;
3716    describeParams.nStride = 128;
3717    describeParams.nSliceHeight = 128;
3718    describeParams.bUsingNativeBuffers = (OMX_BOOL)usingNativeBuffers;
3719
3720    CHECK(flexibleEquivalent != NULL);
3721
3722    if (!describeColorFormat(omx, node, describeParams)) {
3723        return false;
3724    }
3725
3726    const MediaImage &img = describeParams.sMediaImage;
3727    if (img.mType == MediaImage::MEDIA_IMAGE_TYPE_YUV) {
3728        if (img.mNumPlanes != 3 ||
3729            img.mPlane[img.Y].mHorizSubsampling != 1 ||
3730            img.mPlane[img.Y].mVertSubsampling != 1) {
3731            return false;
3732        }
3733
3734        // YUV 420
3735        if (img.mPlane[img.U].mHorizSubsampling == 2
3736                && img.mPlane[img.U].mVertSubsampling == 2
3737                && img.mPlane[img.V].mHorizSubsampling == 2
3738                && img.mPlane[img.V].mVertSubsampling == 2) {
3739            // possible flexible YUV420 format
3740            if (img.mBitDepth <= 8) {
3741               *flexibleEquivalent = OMX_COLOR_FormatYUV420Flexible;
3742               return true;
3743            }
3744        }
3745    }
3746    return false;
3747}
3748
3749status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> &notify) {
3750    const char *niceIndex = portIndex == kPortIndexInput ? "input" : "output";
3751    OMX_PARAM_PORTDEFINITIONTYPE def;
3752    InitOMXParams(&def);
3753    def.nPortIndex = portIndex;
3754
3755    status_t err = mOMX->getParameter(mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
3756    if (err != OK) {
3757        return err;
3758    }
3759
3760    if (def.eDir != (portIndex == kPortIndexOutput ? OMX_DirOutput : OMX_DirInput)) {
3761        ALOGE("unexpected dir: %s(%d) on %s port", asString(def.eDir), def.eDir, niceIndex);
3762        return BAD_VALUE;
3763    }
3764
3765    switch (def.eDomain) {
3766        case OMX_PortDomainVideo:
3767        {
3768            OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
3769            switch ((int)videoDef->eCompressionFormat) {
3770                case OMX_VIDEO_CodingUnused:
3771                {
3772                    CHECK(mIsEncoder ^ (portIndex == kPortIndexOutput));
3773                    notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW);
3774
3775                    notify->setInt32("stride", videoDef->nStride);
3776                    notify->setInt32("slice-height", videoDef->nSliceHeight);
3777                    notify->setInt32("color-format", videoDef->eColorFormat);
3778
3779                    if (mNativeWindow == NULL) {
3780                        DescribeColorFormatParams describeParams;
3781                        InitOMXParams(&describeParams);
3782                        describeParams.eColorFormat = videoDef->eColorFormat;
3783                        describeParams.nFrameWidth = videoDef->nFrameWidth;
3784                        describeParams.nFrameHeight = videoDef->nFrameHeight;
3785                        describeParams.nStride = videoDef->nStride;
3786                        describeParams.nSliceHeight = videoDef->nSliceHeight;
3787                        describeParams.bUsingNativeBuffers = OMX_FALSE;
3788
3789                        if (describeColorFormat(mOMX, mNode, describeParams)) {
3790                            notify->setBuffer(
3791                                    "image-data",
3792                                    ABuffer::CreateAsCopy(
3793                                            &describeParams.sMediaImage,
3794                                            sizeof(describeParams.sMediaImage)));
3795
3796                            MediaImage *img = &describeParams.sMediaImage;
3797                            ALOGV("[%s] MediaImage { F(%zux%zu) @%zu+%zu+%zu @%zu+%zu+%zu @%zu+%zu+%zu }",
3798                                    mComponentName.c_str(), img->mWidth, img->mHeight,
3799                                    img->mPlane[0].mOffset, img->mPlane[0].mColInc, img->mPlane[0].mRowInc,
3800                                    img->mPlane[1].mOffset, img->mPlane[1].mColInc, img->mPlane[1].mRowInc,
3801                                    img->mPlane[2].mOffset, img->mPlane[2].mColInc, img->mPlane[2].mRowInc);
3802                        }
3803                    }
3804
3805                    if (portIndex != kPortIndexOutput) {
3806                        // TODO: also get input crop
3807                        break;
3808                    }
3809
3810                    OMX_CONFIG_RECTTYPE rect;
3811                    InitOMXParams(&rect);
3812                    rect.nPortIndex = portIndex;
3813
3814                    if (mOMX->getConfig(
3815                                mNode,
3816                                (portIndex == kPortIndexOutput ?
3817                                        OMX_IndexConfigCommonOutputCrop :
3818                                        OMX_IndexConfigCommonInputCrop),
3819                                &rect, sizeof(rect)) != OK) {
3820                        rect.nLeft = 0;
3821                        rect.nTop = 0;
3822                        rect.nWidth = videoDef->nFrameWidth;
3823                        rect.nHeight = videoDef->nFrameHeight;
3824                    }
3825
3826                    if (rect.nLeft < 0 ||
3827                        rect.nTop < 0 ||
3828                        rect.nLeft + rect.nWidth > videoDef->nFrameWidth ||
3829                        rect.nTop + rect.nHeight > videoDef->nFrameHeight) {
3830                        ALOGE("Wrong cropped rect (%d, %d) - (%u, %u) vs. frame (%u, %u)",
3831                                rect.nLeft, rect.nTop,
3832                                rect.nLeft + rect.nWidth, rect.nTop + rect.nHeight,
3833                                videoDef->nFrameWidth, videoDef->nFrameHeight);
3834                        return BAD_VALUE;
3835                    }
3836
3837                    notify->setRect(
3838                            "crop",
3839                            rect.nLeft,
3840                            rect.nTop,
3841                            rect.nLeft + rect.nWidth - 1,
3842                            rect.nTop + rect.nHeight - 1);
3843
3844                    break;
3845                }
3846
3847                case OMX_VIDEO_CodingVP8:
3848                case OMX_VIDEO_CodingVP9:
3849                {
3850                    OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type;
3851                    InitOMXParams(&vp8type);
3852                    vp8type.nPortIndex = kPortIndexOutput;
3853                    status_t err = mOMX->getParameter(
3854                            mNode,
3855                            (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
3856                            &vp8type,
3857                            sizeof(vp8type));
3858
3859                    if (err == OK) {
3860                        AString tsSchema = "none";
3861                        if (vp8type.eTemporalPattern
3862                                == OMX_VIDEO_VPXTemporalLayerPatternWebRTC) {
3863                            switch (vp8type.nTemporalLayerCount) {
3864                                case 1:
3865                                {
3866                                    tsSchema = "webrtc.vp8.1-layer";
3867                                    break;
3868                                }
3869                                case 2:
3870                                {
3871                                    tsSchema = "webrtc.vp8.2-layer";
3872                                    break;
3873                                }
3874                                case 3:
3875                                {
3876                                    tsSchema = "webrtc.vp8.3-layer";
3877                                    break;
3878                                }
3879                                default:
3880                                {
3881                                    break;
3882                                }
3883                            }
3884                        }
3885                        notify->setString("ts-schema", tsSchema);
3886                    }
3887                    // Fall through to set up mime.
3888                }
3889
3890                default:
3891                {
3892                    if (mIsEncoder ^ (portIndex == kPortIndexOutput)) {
3893                        // should be CodingUnused
3894                        ALOGE("Raw port video compression format is %s(%d)",
3895                                asString(videoDef->eCompressionFormat),
3896                                videoDef->eCompressionFormat);
3897                        return BAD_VALUE;
3898                    }
3899                    AString mime;
3900                    if (GetMimeTypeForVideoCoding(
3901                        videoDef->eCompressionFormat, &mime) != OK) {
3902                        notify->setString("mime", "application/octet-stream");
3903                    } else {
3904                        notify->setString("mime", mime.c_str());
3905                    }
3906                    break;
3907                }
3908            }
3909            notify->setInt32("width", videoDef->nFrameWidth);
3910            notify->setInt32("height", videoDef->nFrameHeight);
3911            ALOGV("[%s] %s format is %s", mComponentName.c_str(),
3912                    portIndex == kPortIndexInput ? "input" : "output",
3913                    notify->debugString().c_str());
3914
3915            break;
3916        }
3917
3918        case OMX_PortDomainAudio:
3919        {
3920            OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
3921
3922            switch ((int)audioDef->eEncoding) {
3923                case OMX_AUDIO_CodingPCM:
3924                {
3925                    OMX_AUDIO_PARAM_PCMMODETYPE params;
3926                    InitOMXParams(&params);
3927                    params.nPortIndex = portIndex;
3928
3929                    err = mOMX->getParameter(
3930                            mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
3931                    if (err != OK) {
3932                        return err;
3933                    }
3934
3935                    if (params.nChannels <= 0
3936                            || (params.nChannels != 1 && !params.bInterleaved)
3937                            || params.nBitPerSample != 16u
3938                            || params.eNumData != OMX_NumericalDataSigned
3939                            || params.ePCMMode != OMX_AUDIO_PCMModeLinear) {
3940                        ALOGE("unsupported PCM port: %u channels%s, %u-bit, %s(%d), %s(%d) mode ",
3941                                params.nChannels,
3942                                params.bInterleaved ? " interleaved" : "",
3943                                params.nBitPerSample,
3944                                asString(params.eNumData), params.eNumData,
3945                                asString(params.ePCMMode), params.ePCMMode);
3946                        return FAILED_TRANSACTION;
3947                    }
3948
3949                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
3950                    notify->setInt32("channel-count", params.nChannels);
3951                    notify->setInt32("sample-rate", params.nSamplingRate);
3952
3953                    if (mChannelMaskPresent) {
3954                        notify->setInt32("channel-mask", mChannelMask);
3955                    }
3956                    break;
3957                }
3958
3959                case OMX_AUDIO_CodingAAC:
3960                {
3961                    OMX_AUDIO_PARAM_AACPROFILETYPE params;
3962                    InitOMXParams(&params);
3963                    params.nPortIndex = portIndex;
3964
3965                    err = mOMX->getParameter(
3966                            mNode, OMX_IndexParamAudioAac, &params, sizeof(params));
3967                    if (err != OK) {
3968                        return err;
3969                    }
3970
3971                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
3972                    notify->setInt32("channel-count", params.nChannels);
3973                    notify->setInt32("sample-rate", params.nSampleRate);
3974                    break;
3975                }
3976
3977                case OMX_AUDIO_CodingAMR:
3978                {
3979                    OMX_AUDIO_PARAM_AMRTYPE params;
3980                    InitOMXParams(&params);
3981                    params.nPortIndex = portIndex;
3982
3983                    err = mOMX->getParameter(
3984                            mNode, OMX_IndexParamAudioAmr, &params, sizeof(params));
3985                    if (err != OK) {
3986                        return err;
3987                    }
3988
3989                    notify->setInt32("channel-count", 1);
3990                    if (params.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0) {
3991                        notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_WB);
3992                        notify->setInt32("sample-rate", 16000);
3993                    } else {
3994                        notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_NB);
3995                        notify->setInt32("sample-rate", 8000);
3996                    }
3997                    break;
3998                }
3999
4000                case OMX_AUDIO_CodingFLAC:
4001                {
4002                    OMX_AUDIO_PARAM_FLACTYPE params;
4003                    InitOMXParams(&params);
4004                    params.nPortIndex = portIndex;
4005
4006                    err = mOMX->getParameter(
4007                            mNode, OMX_IndexParamAudioFlac, &params, sizeof(params));
4008                    if (err != OK) {
4009                        return err;
4010                    }
4011
4012                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_FLAC);
4013                    notify->setInt32("channel-count", params.nChannels);
4014                    notify->setInt32("sample-rate", params.nSampleRate);
4015                    break;
4016                }
4017
4018                case OMX_AUDIO_CodingMP3:
4019                {
4020                    OMX_AUDIO_PARAM_MP3TYPE params;
4021                    InitOMXParams(&params);
4022                    params.nPortIndex = portIndex;
4023
4024                    err = mOMX->getParameter(
4025                            mNode, OMX_IndexParamAudioMp3, &params, sizeof(params));
4026                    if (err != OK) {
4027                        return err;
4028                    }
4029
4030                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MPEG);
4031                    notify->setInt32("channel-count", params.nChannels);
4032                    notify->setInt32("sample-rate", params.nSampleRate);
4033                    break;
4034                }
4035
4036                case OMX_AUDIO_CodingVORBIS:
4037                {
4038                    OMX_AUDIO_PARAM_VORBISTYPE params;
4039                    InitOMXParams(&params);
4040                    params.nPortIndex = portIndex;
4041
4042                    err = mOMX->getParameter(
4043                            mNode, OMX_IndexParamAudioVorbis, &params, sizeof(params));
4044                    if (err != OK) {
4045                        return err;
4046                    }
4047
4048                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_VORBIS);
4049                    notify->setInt32("channel-count", params.nChannels);
4050                    notify->setInt32("sample-rate", params.nSampleRate);
4051                    break;
4052                }
4053
4054                case OMX_AUDIO_CodingAndroidAC3:
4055                {
4056                    OMX_AUDIO_PARAM_ANDROID_AC3TYPE params;
4057                    InitOMXParams(&params);
4058                    params.nPortIndex = portIndex;
4059
4060                    err = mOMX->getParameter(
4061                            mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
4062                            &params, sizeof(params));
4063                    if (err != OK) {
4064                        return err;
4065                    }
4066
4067                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AC3);
4068                    notify->setInt32("channel-count", params.nChannels);
4069                    notify->setInt32("sample-rate", params.nSampleRate);
4070                    break;
4071                }
4072
4073                case OMX_AUDIO_CodingAndroidEAC3:
4074                {
4075                    OMX_AUDIO_PARAM_ANDROID_EAC3TYPE params;
4076                    InitOMXParams(&params);
4077                    params.nPortIndex = portIndex;
4078
4079                    err = mOMX->getParameter(
4080                            mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
4081                            &params, sizeof(params));
4082                    if (err != OK) {
4083                        return err;
4084                    }
4085
4086                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_EAC3);
4087                    notify->setInt32("channel-count", params.nChannels);
4088                    notify->setInt32("sample-rate", params.nSampleRate);
4089                    break;
4090                }
4091
4092                case OMX_AUDIO_CodingAndroidOPUS:
4093                {
4094                    OMX_AUDIO_PARAM_ANDROID_OPUSTYPE params;
4095                    InitOMXParams(&params);
4096                    params.nPortIndex = portIndex;
4097
4098                    err = mOMX->getParameter(
4099                            mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus,
4100                            &params, sizeof(params));
4101                    if (err != OK) {
4102                        return err;
4103                    }
4104
4105                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_OPUS);
4106                    notify->setInt32("channel-count", params.nChannels);
4107                    notify->setInt32("sample-rate", params.nSampleRate);
4108                    break;
4109                }
4110
4111                case OMX_AUDIO_CodingG711:
4112                {
4113                    OMX_AUDIO_PARAM_PCMMODETYPE params;
4114                    InitOMXParams(&params);
4115                    params.nPortIndex = portIndex;
4116
4117                    err = mOMX->getParameter(
4118                            mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioPcm, &params, sizeof(params));
4119                    if (err != OK) {
4120                        return err;
4121                    }
4122
4123                    const char *mime = NULL;
4124                    if (params.ePCMMode == OMX_AUDIO_PCMModeMULaw) {
4125                        mime = MEDIA_MIMETYPE_AUDIO_G711_MLAW;
4126                    } else if (params.ePCMMode == OMX_AUDIO_PCMModeALaw) {
4127                        mime = MEDIA_MIMETYPE_AUDIO_G711_ALAW;
4128                    } else { // params.ePCMMode == OMX_AUDIO_PCMModeLinear
4129                        mime = MEDIA_MIMETYPE_AUDIO_RAW;
4130                    }
4131                    notify->setString("mime", mime);
4132                    notify->setInt32("channel-count", params.nChannels);
4133                    notify->setInt32("sample-rate", params.nSamplingRate);
4134                    break;
4135                }
4136
4137                case OMX_AUDIO_CodingGSMFR:
4138                {
4139                    OMX_AUDIO_PARAM_PCMMODETYPE params;
4140                    InitOMXParams(&params);
4141                    params.nPortIndex = portIndex;
4142
4143                    err = mOMX->getParameter(
4144                                mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
4145                    if (err != OK) {
4146                        return err;
4147                    }
4148
4149                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MSGSM);
4150                    notify->setInt32("channel-count", params.nChannels);
4151                    notify->setInt32("sample-rate", params.nSamplingRate);
4152                    break;
4153                }
4154
4155                default:
4156                    ALOGE("Unsupported audio coding: %s(%d)\n",
4157                            asString(audioDef->eEncoding), audioDef->eEncoding);
4158                    return BAD_TYPE;
4159            }
4160            break;
4161        }
4162
4163        default:
4164            ALOGE("Unsupported domain: %s(%d)", asString(def.eDomain), def.eDomain);
4165            return BAD_TYPE;
4166    }
4167
4168    return OK;
4169}
4170
4171void ACodec::sendFormatChange(const sp<AMessage> &reply) {
4172    sp<AMessage> notify = mBaseOutputFormat->dup();
4173    notify->setInt32("what", kWhatOutputFormatChanged);
4174
4175    if (getPortFormat(kPortIndexOutput, notify) != OK) {
4176        ALOGE("[%s] Failed to get port format to send format change", mComponentName.c_str());
4177        return;
4178    }
4179
4180    AString mime;
4181    CHECK(notify->findString("mime", &mime));
4182
4183    int32_t left, top, right, bottom;
4184    if (mime == MEDIA_MIMETYPE_VIDEO_RAW &&
4185        mNativeWindow != NULL &&
4186        notify->findRect("crop", &left, &top, &right, &bottom)) {
4187        // notify renderer of the crop change
4188        // NOTE: native window uses extended right-bottom coordinate
4189        reply->setRect("crop", left, top, right + 1, bottom + 1);
4190    } else if (mime == MEDIA_MIMETYPE_AUDIO_RAW &&
4191               (mEncoderDelay || mEncoderPadding)) {
4192        int32_t channelCount;
4193        CHECK(notify->findInt32("channel-count", &channelCount));
4194        size_t frameSize = channelCount * sizeof(int16_t);
4195        if (mSkipCutBuffer != NULL) {
4196            size_t prevbufsize = mSkipCutBuffer->size();
4197            if (prevbufsize != 0) {
4198                ALOGW("Replacing SkipCutBuffer holding %zu bytes", prevbufsize);
4199            }
4200        }
4201        mSkipCutBuffer = new SkipCutBuffer(
4202                mEncoderDelay * frameSize,
4203                mEncoderPadding * frameSize);
4204    }
4205
4206    notify->post();
4207
4208    mSentFormat = true;
4209}
4210
4211void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) {
4212    sp<AMessage> notify = mNotify->dup();
4213    notify->setInt32("what", CodecBase::kWhatError);
4214    ALOGE("signalError(omxError %#x, internalError %d)", error, internalError);
4215
4216    if (internalError == UNKNOWN_ERROR) { // find better error code
4217        const status_t omxStatus = statusFromOMXError(error);
4218        if (omxStatus != 0) {
4219            internalError = omxStatus;
4220        } else {
4221            ALOGW("Invalid OMX error %#x", error);
4222        }
4223    }
4224    notify->setInt32("err", internalError);
4225    notify->setInt32("actionCode", ACTION_CODE_FATAL); // could translate from OMX error.
4226    notify->post();
4227}
4228
4229////////////////////////////////////////////////////////////////////////////////
4230
4231ACodec::PortDescription::PortDescription() {
4232}
4233
4234status_t ACodec::requestIDRFrame() {
4235    if (!mIsEncoder) {
4236        return ERROR_UNSUPPORTED;
4237    }
4238
4239    OMX_CONFIG_INTRAREFRESHVOPTYPE params;
4240    InitOMXParams(&params);
4241
4242    params.nPortIndex = kPortIndexOutput;
4243    params.IntraRefreshVOP = OMX_TRUE;
4244
4245    return mOMX->setConfig(
4246            mNode,
4247            OMX_IndexConfigVideoIntraVOPRefresh,
4248            &params,
4249            sizeof(params));
4250}
4251
4252void ACodec::PortDescription::addBuffer(
4253        IOMX::buffer_id id, const sp<ABuffer> &buffer) {
4254    mBufferIDs.push_back(id);
4255    mBuffers.push_back(buffer);
4256}
4257
4258size_t ACodec::PortDescription::countBuffers() {
4259    return mBufferIDs.size();
4260}
4261
4262IOMX::buffer_id ACodec::PortDescription::bufferIDAt(size_t index) const {
4263    return mBufferIDs.itemAt(index);
4264}
4265
4266sp<ABuffer> ACodec::PortDescription::bufferAt(size_t index) const {
4267    return mBuffers.itemAt(index);
4268}
4269
4270////////////////////////////////////////////////////////////////////////////////
4271
4272ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
4273    : AState(parentState),
4274      mCodec(codec) {
4275}
4276
4277ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(
4278        OMX_U32 /* portIndex */) {
4279    return KEEP_BUFFERS;
4280}
4281
4282bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) {
4283    switch (msg->what()) {
4284        case kWhatInputBufferFilled:
4285        {
4286            onInputBufferFilled(msg);
4287            break;
4288        }
4289
4290        case kWhatOutputBufferDrained:
4291        {
4292            onOutputBufferDrained(msg);
4293            break;
4294        }
4295
4296        case ACodec::kWhatOMXMessage:
4297        {
4298            return onOMXMessage(msg);
4299        }
4300
4301        case ACodec::kWhatSetSurface:
4302        {
4303            sp<AReplyToken> replyID;
4304            CHECK(msg->senderAwaitsResponse(&replyID));
4305
4306            sp<RefBase> obj;
4307            CHECK(msg->findObject("surface", &obj));
4308
4309            status_t err =
4310                ADebug::isExperimentEnabled("legacy-setsurface") ? BAD_VALUE :
4311                        mCodec->handleSetSurface(static_cast<Surface *>(obj.get()));
4312
4313            sp<AMessage> response = new AMessage;
4314            response->setInt32("err", err);
4315            response->postReply(replyID);
4316            break;
4317        }
4318
4319        case ACodec::kWhatCreateInputSurface:
4320        case ACodec::kWhatSetInputSurface:
4321        case ACodec::kWhatSignalEndOfInputStream:
4322        {
4323            // This may result in an app illegal state exception.
4324            ALOGE("Message 0x%x was not handled", msg->what());
4325            mCodec->signalError(OMX_ErrorUndefined, INVALID_OPERATION);
4326            return true;
4327        }
4328
4329        case ACodec::kWhatOMXDied:
4330        {
4331            // This will result in kFlagSawMediaServerDie handling in MediaCodec.
4332            ALOGE("OMX/mediaserver died, signalling error!");
4333            mCodec->signalError(OMX_ErrorResourcesLost, DEAD_OBJECT);
4334            break;
4335        }
4336
4337        case ACodec::kWhatReleaseCodecInstance:
4338        {
4339            ALOGI("[%s] forcing the release of codec",
4340                    mCodec->mComponentName.c_str());
4341            status_t err = mCodec->mOMX->freeNode(mCodec->mNode);
4342            ALOGE_IF("[%s] failed to release codec instance: err=%d",
4343                       mCodec->mComponentName.c_str(), err);
4344            sp<AMessage> notify = mCodec->mNotify->dup();
4345            notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
4346            notify->post();
4347            break;
4348        }
4349
4350        default:
4351            return false;
4352    }
4353
4354    return true;
4355}
4356
4357bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) {
4358    int32_t type;
4359    CHECK(msg->findInt32("type", &type));
4360
4361    // there is a possibility that this is an outstanding message for a
4362    // codec that we have already destroyed
4363    if (mCodec->mNode == 0) {
4364        ALOGI("ignoring message as already freed component: %s",
4365                msg->debugString().c_str());
4366        return true;
4367    }
4368
4369    IOMX::node_id nodeID;
4370    CHECK(msg->findInt32("node", (int32_t*)&nodeID));
4371    if (nodeID != mCodec->mNode) {
4372        ALOGE("Unexpected message for nodeID: %u, should have been %u", nodeID, mCodec->mNode);
4373        return false;
4374    }
4375
4376    switch (type) {
4377        case omx_message::EVENT:
4378        {
4379            int32_t event, data1, data2;
4380            CHECK(msg->findInt32("event", &event));
4381            CHECK(msg->findInt32("data1", &data1));
4382            CHECK(msg->findInt32("data2", &data2));
4383
4384            if (event == OMX_EventCmdComplete
4385                    && data1 == OMX_CommandFlush
4386                    && data2 == (int32_t)OMX_ALL) {
4387                // Use of this notification is not consistent across
4388                // implementations. We'll drop this notification and rely
4389                // on flush-complete notifications on the individual port
4390                // indices instead.
4391
4392                return true;
4393            }
4394
4395            return onOMXEvent(
4396                    static_cast<OMX_EVENTTYPE>(event),
4397                    static_cast<OMX_U32>(data1),
4398                    static_cast<OMX_U32>(data2));
4399        }
4400
4401        case omx_message::EMPTY_BUFFER_DONE:
4402        {
4403            IOMX::buffer_id bufferID;
4404            CHECK(msg->findInt32("buffer", (int32_t*)&bufferID));
4405
4406            return onOMXEmptyBufferDone(bufferID);
4407        }
4408
4409        case omx_message::FILL_BUFFER_DONE:
4410        {
4411            IOMX::buffer_id bufferID;
4412            CHECK(msg->findInt32("buffer", (int32_t*)&bufferID));
4413
4414            int32_t rangeOffset, rangeLength, flags;
4415            int64_t timeUs;
4416
4417            CHECK(msg->findInt32("range_offset", &rangeOffset));
4418            CHECK(msg->findInt32("range_length", &rangeLength));
4419            CHECK(msg->findInt32("flags", &flags));
4420            CHECK(msg->findInt64("timestamp", &timeUs));
4421
4422            return onOMXFillBufferDone(
4423                    bufferID,
4424                    (size_t)rangeOffset, (size_t)rangeLength,
4425                    (OMX_U32)flags,
4426                    timeUs);
4427        }
4428
4429        default:
4430            ALOGE("Unexpected message type: %d", type);
4431            return false;
4432    }
4433}
4434
4435bool ACodec::BaseState::onOMXEvent(
4436        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
4437    if (event != OMX_EventError) {
4438        ALOGV("[%s] EVENT(%d, 0x%08x, 0x%08x)",
4439             mCodec->mComponentName.c_str(), event, data1, data2);
4440
4441        return false;
4442    }
4443
4444    ALOGE("[%s] ERROR(0x%08x)", mCodec->mComponentName.c_str(), data1);
4445
4446    // verify OMX component sends back an error we expect.
4447    OMX_ERRORTYPE omxError = (OMX_ERRORTYPE)data1;
4448    if (!isOMXError(omxError)) {
4449        ALOGW("Invalid OMX error %#x", omxError);
4450        omxError = OMX_ErrorUndefined;
4451    }
4452    mCodec->signalError(omxError);
4453
4454    return true;
4455}
4456
4457bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) {
4458    ALOGV("[%s] onOMXEmptyBufferDone %u",
4459         mCodec->mComponentName.c_str(), bufferID);
4460
4461    BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
4462    BufferInfo::Status status = BufferInfo::getSafeStatus(info);
4463    if (status != BufferInfo::OWNED_BY_COMPONENT) {
4464        ALOGE("Wrong ownership in EBD: %s(%d) buffer #%u", _asString(status), status, bufferID);
4465        mCodec->dumpBuffers(kPortIndexInput);
4466        return false;
4467    }
4468    info->mStatus = BufferInfo::OWNED_BY_US;
4469
4470    // We're in "store-metadata-in-buffers" mode, the underlying
4471    // OMX component had access to data that's implicitly refcounted
4472    // by this "MediaBuffer" object. Now that the OMX component has
4473    // told us that it's done with the input buffer, we can decrement
4474    // the mediaBuffer's reference count.
4475    info->mData->setMediaBufferBase(NULL);
4476
4477    PortMode mode = getPortMode(kPortIndexInput);
4478
4479    switch (mode) {
4480        case KEEP_BUFFERS:
4481            break;
4482
4483        case RESUBMIT_BUFFERS:
4484            postFillThisBuffer(info);
4485            break;
4486
4487        case FREE_BUFFERS:
4488        default:
4489            ALOGE("SHOULD NOT REACH HERE: cannot free empty output buffers");
4490            return false;
4491    }
4492
4493    return true;
4494}
4495
4496void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) {
4497    if (mCodec->mPortEOS[kPortIndexInput]) {
4498        return;
4499    }
4500
4501    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
4502
4503    sp<AMessage> notify = mCodec->mNotify->dup();
4504    notify->setInt32("what", CodecBase::kWhatFillThisBuffer);
4505    notify->setInt32("buffer-id", info->mBufferID);
4506
4507    info->mData->meta()->clear();
4508    notify->setBuffer("buffer", info->mData);
4509
4510    sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec);
4511    reply->setInt32("buffer-id", info->mBufferID);
4512
4513    notify->setMessage("reply", reply);
4514
4515    notify->post();
4516
4517    info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
4518}
4519
4520void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
4521    IOMX::buffer_id bufferID;
4522    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
4523    sp<ABuffer> buffer;
4524    int32_t err = OK;
4525    bool eos = false;
4526    PortMode mode = getPortMode(kPortIndexInput);
4527
4528    if (!msg->findBuffer("buffer", &buffer)) {
4529        /* these are unfilled buffers returned by client */
4530        CHECK(msg->findInt32("err", &err));
4531
4532        if (err == OK) {
4533            /* buffers with no errors are returned on MediaCodec.flush */
4534            mode = KEEP_BUFFERS;
4535        } else {
4536            ALOGV("[%s] saw error %d instead of an input buffer",
4537                 mCodec->mComponentName.c_str(), err);
4538            eos = true;
4539        }
4540
4541        buffer.clear();
4542    }
4543
4544    int32_t tmp;
4545    if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) {
4546        eos = true;
4547        err = ERROR_END_OF_STREAM;
4548    }
4549
4550    BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
4551    BufferInfo::Status status = BufferInfo::getSafeStatus(info);
4552    if (status != BufferInfo::OWNED_BY_UPSTREAM) {
4553        ALOGE("Wrong ownership in IBF: %s(%d) buffer #%u", _asString(status), status, bufferID);
4554        mCodec->dumpBuffers(kPortIndexInput);
4555        mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
4556        return;
4557    }
4558
4559    info->mStatus = BufferInfo::OWNED_BY_US;
4560
4561    switch (mode) {
4562        case KEEP_BUFFERS:
4563        {
4564            if (eos) {
4565                if (!mCodec->mPortEOS[kPortIndexInput]) {
4566                    mCodec->mPortEOS[kPortIndexInput] = true;
4567                    mCodec->mInputEOSResult = err;
4568                }
4569            }
4570            break;
4571        }
4572
4573        case RESUBMIT_BUFFERS:
4574        {
4575            if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) {
4576                int64_t timeUs;
4577                CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
4578
4579                OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
4580
4581                int32_t isCSD;
4582                if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) {
4583                    flags |= OMX_BUFFERFLAG_CODECCONFIG;
4584                }
4585
4586                if (eos) {
4587                    flags |= OMX_BUFFERFLAG_EOS;
4588                }
4589
4590                if (buffer != info->mData) {
4591                    ALOGV("[%s] Needs to copy input data for buffer %u. (%p != %p)",
4592                         mCodec->mComponentName.c_str(),
4593                         bufferID,
4594                         buffer.get(), info->mData.get());
4595
4596                    if (buffer->size() > info->mData->capacity()) {
4597                        ALOGE("data size (%zu) is greated than buffer capacity (%zu)",
4598                                buffer->size(),           // this is the data received
4599                                info->mData->capacity()); // this is out buffer size
4600                        mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
4601                        return;
4602                    }
4603                    memcpy(info->mData->data(), buffer->data(), buffer->size());
4604                }
4605
4606                if (flags & OMX_BUFFERFLAG_CODECCONFIG) {
4607                    ALOGV("[%s] calling emptyBuffer %u w/ codec specific data",
4608                         mCodec->mComponentName.c_str(), bufferID);
4609                } else if (flags & OMX_BUFFERFLAG_EOS) {
4610                    ALOGV("[%s] calling emptyBuffer %u w/ EOS",
4611                         mCodec->mComponentName.c_str(), bufferID);
4612                } else {
4613#if TRACK_BUFFER_TIMING
4614                    ALOGI("[%s] calling emptyBuffer %u w/ time %lld us",
4615                         mCodec->mComponentName.c_str(), bufferID, (long long)timeUs);
4616#else
4617                    ALOGV("[%s] calling emptyBuffer %u w/ time %lld us",
4618                         mCodec->mComponentName.c_str(), bufferID, (long long)timeUs);
4619#endif
4620                }
4621
4622#if TRACK_BUFFER_TIMING
4623                ACodec::BufferStats stats;
4624                stats.mEmptyBufferTimeUs = ALooper::GetNowUs();
4625                stats.mFillBufferDoneTimeUs = -1ll;
4626                mCodec->mBufferStats.add(timeUs, stats);
4627#endif
4628
4629                if (mCodec->mStoreMetaDataInOutputBuffers) {
4630                    // try to submit an output buffer for each input buffer
4631                    PortMode outputMode = getPortMode(kPortIndexOutput);
4632
4633                    ALOGV("MetaDataBuffersToSubmit=%u portMode=%s",
4634                            mCodec->mMetaDataBuffersToSubmit,
4635                            (outputMode == FREE_BUFFERS ? "FREE" :
4636                             outputMode == KEEP_BUFFERS ? "KEEP" : "RESUBMIT"));
4637                    if (outputMode == RESUBMIT_BUFFERS) {
4638                        mCodec->submitOutputMetaDataBuffer();
4639                    }
4640                }
4641                status_t err2 = mCodec->mOMX->emptyBuffer(
4642                    mCodec->mNode,
4643                    bufferID,
4644                    0,
4645                    buffer->size(),
4646                    flags,
4647                    timeUs);
4648                if (err2 != OK) {
4649                    mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err2));
4650                    return;
4651                }
4652                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4653
4654                if (!eos && err == OK) {
4655                    getMoreInputDataIfPossible();
4656                } else {
4657                    ALOGV("[%s] Signalled EOS (%d) on the input port",
4658                         mCodec->mComponentName.c_str(), err);
4659
4660                    mCodec->mPortEOS[kPortIndexInput] = true;
4661                    mCodec->mInputEOSResult = err;
4662                }
4663            } else if (!mCodec->mPortEOS[kPortIndexInput]) {
4664                if (err != OK && err != ERROR_END_OF_STREAM) {
4665                    ALOGV("[%s] Signalling EOS on the input port due to error %d",
4666                         mCodec->mComponentName.c_str(), err);
4667                } else {
4668                    ALOGV("[%s] Signalling EOS on the input port",
4669                         mCodec->mComponentName.c_str());
4670                }
4671
4672                ALOGV("[%s] calling emptyBuffer %u signalling EOS",
4673                     mCodec->mComponentName.c_str(), bufferID);
4674
4675                status_t err2 = mCodec->mOMX->emptyBuffer(
4676                        mCodec->mNode,
4677                        bufferID,
4678                        0,
4679                        0,
4680                        OMX_BUFFERFLAG_EOS,
4681                        0);
4682                if (err2 != OK) {
4683                    mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err2));
4684                    return;
4685                }
4686                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4687
4688                mCodec->mPortEOS[kPortIndexInput] = true;
4689                mCodec->mInputEOSResult = err;
4690            }
4691            break;
4692        }
4693
4694        case FREE_BUFFERS:
4695            break;
4696
4697        default:
4698            ALOGE("invalid port mode: %d", mode);
4699            break;
4700    }
4701}
4702
4703void ACodec::BaseState::getMoreInputDataIfPossible() {
4704    if (mCodec->mPortEOS[kPortIndexInput]) {
4705        return;
4706    }
4707
4708    BufferInfo *eligible = NULL;
4709
4710    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
4711        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
4712
4713#if 0
4714        if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) {
4715            // There's already a "read" pending.
4716            return;
4717        }
4718#endif
4719
4720        if (info->mStatus == BufferInfo::OWNED_BY_US) {
4721            eligible = info;
4722        }
4723    }
4724
4725    if (eligible == NULL) {
4726        return;
4727    }
4728
4729    postFillThisBuffer(eligible);
4730}
4731
4732bool ACodec::BaseState::onOMXFillBufferDone(
4733        IOMX::buffer_id bufferID,
4734        size_t rangeOffset, size_t rangeLength,
4735        OMX_U32 flags,
4736        int64_t timeUs) {
4737    ALOGV("[%s] onOMXFillBufferDone %u time %" PRId64 " us, flags = 0x%08x",
4738         mCodec->mComponentName.c_str(), bufferID, timeUs, flags);
4739
4740    ssize_t index;
4741    status_t err= OK;
4742
4743#if TRACK_BUFFER_TIMING
4744    index = mCodec->mBufferStats.indexOfKey(timeUs);
4745    if (index >= 0) {
4746        ACodec::BufferStats *stats = &mCodec->mBufferStats.editValueAt(index);
4747        stats->mFillBufferDoneTimeUs = ALooper::GetNowUs();
4748
4749        ALOGI("frame PTS %lld: %lld",
4750                timeUs,
4751                stats->mFillBufferDoneTimeUs - stats->mEmptyBufferTimeUs);
4752
4753        mCodec->mBufferStats.removeItemsAt(index);
4754        stats = NULL;
4755    }
4756#endif
4757
4758    BufferInfo *info =
4759        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
4760    BufferInfo::Status status = BufferInfo::getSafeStatus(info);
4761    if (status != BufferInfo::OWNED_BY_COMPONENT) {
4762        ALOGE("Wrong ownership in FBD: %s(%d) buffer #%u", _asString(status), status, bufferID);
4763        mCodec->dumpBuffers(kPortIndexOutput);
4764        mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
4765        return true;
4766    }
4767
4768    info->mDequeuedAt = ++mCodec->mDequeueCounter;
4769    info->mStatus = BufferInfo::OWNED_BY_US;
4770
4771    PortMode mode = getPortMode(kPortIndexOutput);
4772
4773    switch (mode) {
4774        case KEEP_BUFFERS:
4775            break;
4776
4777        case RESUBMIT_BUFFERS:
4778        {
4779            if (rangeLength == 0 && (!(flags & OMX_BUFFERFLAG_EOS)
4780                    || mCodec->mPortEOS[kPortIndexOutput])) {
4781                ALOGV("[%s] calling fillBuffer %u",
4782                     mCodec->mComponentName.c_str(), info->mBufferID);
4783
4784                err = mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID);
4785                if (err != OK) {
4786                    mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
4787                    return true;
4788                }
4789
4790                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4791                break;
4792            }
4793
4794            sp<AMessage> reply =
4795                new AMessage(kWhatOutputBufferDrained, mCodec);
4796
4797            if (!mCodec->mSentFormat && rangeLength > 0) {
4798                mCodec->sendFormatChange(reply);
4799            }
4800
4801            if (mCodec->mUseMetadataOnEncoderOutput) {
4802                native_handle_t* handle =
4803                        *(native_handle_t**)(info->mData->data() + 4);
4804                info->mData->meta()->setPointer("handle", handle);
4805                info->mData->meta()->setInt32("rangeOffset", rangeOffset);
4806                info->mData->meta()->setInt32("rangeLength", rangeLength);
4807            } else {
4808                info->mData->setRange(rangeOffset, rangeLength);
4809            }
4810#if 0
4811            if (mCodec->mNativeWindow == NULL) {
4812                if (IsIDR(info->mData)) {
4813                    ALOGI("IDR frame");
4814                }
4815            }
4816#endif
4817
4818            if (mCodec->mSkipCutBuffer != NULL) {
4819                mCodec->mSkipCutBuffer->submit(info->mData);
4820            }
4821            info->mData->meta()->setInt64("timeUs", timeUs);
4822
4823            sp<AMessage> notify = mCodec->mNotify->dup();
4824            notify->setInt32("what", CodecBase::kWhatDrainThisBuffer);
4825            notify->setInt32("buffer-id", info->mBufferID);
4826            notify->setBuffer("buffer", info->mData);
4827            notify->setInt32("flags", flags);
4828
4829            reply->setInt32("buffer-id", info->mBufferID);
4830
4831            notify->setMessage("reply", reply);
4832
4833            notify->post();
4834
4835            info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;
4836
4837            if (flags & OMX_BUFFERFLAG_EOS) {
4838                ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str());
4839
4840                sp<AMessage> notify = mCodec->mNotify->dup();
4841                notify->setInt32("what", CodecBase::kWhatEOS);
4842                notify->setInt32("err", mCodec->mInputEOSResult);
4843                notify->post();
4844
4845                mCodec->mPortEOS[kPortIndexOutput] = true;
4846            }
4847            break;
4848        }
4849
4850        case FREE_BUFFERS:
4851            err = mCodec->freeBuffer(kPortIndexOutput, index);
4852            if (err != OK) {
4853                mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
4854                return true;
4855            }
4856            break;
4857
4858        default:
4859            ALOGE("Invalid port mode: %d", mode);
4860            return false;
4861    }
4862
4863    return true;
4864}
4865
4866void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
4867    IOMX::buffer_id bufferID;
4868    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
4869    ssize_t index;
4870    BufferInfo *info = mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
4871    BufferInfo::Status status = BufferInfo::getSafeStatus(info);
4872    if (status != BufferInfo::OWNED_BY_DOWNSTREAM) {
4873        ALOGE("Wrong ownership in OBD: %s(%d) buffer #%u", _asString(status), status, bufferID);
4874        mCodec->dumpBuffers(kPortIndexOutput);
4875        mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
4876        return;
4877    }
4878
4879    android_native_rect_t crop;
4880    if (msg->findRect("crop", &crop.left, &crop.top, &crop.right, &crop.bottom)) {
4881        status_t err = native_window_set_crop(mCodec->mNativeWindow.get(), &crop);
4882        ALOGW_IF(err != NO_ERROR, "failed to set crop: %d", err);
4883    }
4884
4885    int32_t render;
4886    if (mCodec->mNativeWindow != NULL
4887            && msg->findInt32("render", &render) && render != 0
4888            && info->mData != NULL && info->mData->size() != 0) {
4889        ATRACE_NAME("render");
4890        // The client wants this buffer to be rendered.
4891
4892        int64_t timestampNs = 0;
4893        if (!msg->findInt64("timestampNs", &timestampNs)) {
4894            // TODO: it seems like we should use the timestamp
4895            // in the (media)buffer as it potentially came from
4896            // an input surface, but we did not propagate it prior to
4897            // API 20.  Perhaps check for target SDK version.
4898#if 0
4899            if (info->mData->meta()->findInt64("timeUs", &timestampNs)) {
4900                ALOGV("using buffer PTS of %" PRId64, timestampNs);
4901                timestampNs *= 1000;
4902            }
4903#endif
4904        }
4905
4906        status_t err;
4907        err = native_window_set_buffers_timestamp(mCodec->mNativeWindow.get(), timestampNs);
4908        ALOGW_IF(err != NO_ERROR, "failed to set buffer timestamp: %d", err);
4909
4910        err = mCodec->mNativeWindow->queueBuffer(
4911                    mCodec->mNativeWindow.get(), info->mGraphicBuffer.get(), -1);
4912        if (err == OK) {
4913            info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
4914        } else {
4915            mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
4916            info->mStatus = BufferInfo::OWNED_BY_US;
4917        }
4918    } else {
4919        if (mCodec->mNativeWindow != NULL &&
4920            (info->mData == NULL || info->mData->size() != 0)) {
4921            ATRACE_NAME("frame-drop");
4922        }
4923        info->mStatus = BufferInfo::OWNED_BY_US;
4924    }
4925
4926    PortMode mode = getPortMode(kPortIndexOutput);
4927
4928    switch (mode) {
4929        case KEEP_BUFFERS:
4930        {
4931            // XXX fishy, revisit!!! What about the FREE_BUFFERS case below?
4932
4933            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
4934                // We cannot resubmit the buffer we just rendered, dequeue
4935                // the spare instead.
4936
4937                info = mCodec->dequeueBufferFromNativeWindow();
4938            }
4939            break;
4940        }
4941
4942        case RESUBMIT_BUFFERS:
4943        {
4944            if (!mCodec->mPortEOS[kPortIndexOutput]) {
4945                if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
4946                    // We cannot resubmit the buffer we just rendered, dequeue
4947                    // the spare instead.
4948
4949                    info = mCodec->dequeueBufferFromNativeWindow();
4950                }
4951
4952                if (info != NULL) {
4953                    ALOGV("[%s] calling fillBuffer %u",
4954                         mCodec->mComponentName.c_str(), info->mBufferID);
4955                    status_t err = mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID);
4956                    if (err == OK) {
4957                        info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4958                    } else {
4959                        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
4960                    }
4961                }
4962            }
4963            break;
4964        }
4965
4966        case FREE_BUFFERS:
4967        {
4968            status_t err = mCodec->freeBuffer(kPortIndexOutput, index);
4969            if (err != OK) {
4970                mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
4971            }
4972            break;
4973        }
4974
4975        default:
4976            ALOGE("Invalid port mode: %d", mode);
4977            return;
4978    }
4979}
4980
4981////////////////////////////////////////////////////////////////////////////////
4982
4983ACodec::UninitializedState::UninitializedState(ACodec *codec)
4984    : BaseState(codec) {
4985}
4986
4987void ACodec::UninitializedState::stateEntered() {
4988    ALOGV("Now uninitialized");
4989
4990    if (mDeathNotifier != NULL) {
4991        IInterface::asBinder(mCodec->mOMX)->unlinkToDeath(mDeathNotifier);
4992        mDeathNotifier.clear();
4993    }
4994
4995    mCodec->mNativeWindow.clear();
4996    mCodec->mNode = 0;
4997    mCodec->mOMX.clear();
4998    mCodec->mQuirks = 0;
4999    mCodec->mFlags = 0;
5000    mCodec->mUseMetadataOnEncoderOutput = 0;
5001    mCodec->mComponentName.clear();
5002}
5003
5004bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
5005    bool handled = false;
5006
5007    switch (msg->what()) {
5008        case ACodec::kWhatSetup:
5009        {
5010            onSetup(msg);
5011
5012            handled = true;
5013            break;
5014        }
5015
5016        case ACodec::kWhatAllocateComponent:
5017        {
5018            onAllocateComponent(msg);
5019            handled = true;
5020            break;
5021        }
5022
5023        case ACodec::kWhatShutdown:
5024        {
5025            int32_t keepComponentAllocated;
5026            CHECK(msg->findInt32(
5027                        "keepComponentAllocated", &keepComponentAllocated));
5028            ALOGW_IF(keepComponentAllocated,
5029                     "cannot keep component allocated on shutdown in Uninitialized state");
5030
5031            sp<AMessage> notify = mCodec->mNotify->dup();
5032            notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
5033            notify->post();
5034
5035            handled = true;
5036            break;
5037        }
5038
5039        case ACodec::kWhatFlush:
5040        {
5041            sp<AMessage> notify = mCodec->mNotify->dup();
5042            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
5043            notify->post();
5044
5045            handled = true;
5046            break;
5047        }
5048
5049        case ACodec::kWhatReleaseCodecInstance:
5050        {
5051            // nothing to do, as we have already signaled shutdown
5052            handled = true;
5053            break;
5054        }
5055
5056        default:
5057            return BaseState::onMessageReceived(msg);
5058    }
5059
5060    return handled;
5061}
5062
5063void ACodec::UninitializedState::onSetup(
5064        const sp<AMessage> &msg) {
5065    if (onAllocateComponent(msg)
5066            && mCodec->mLoadedState->onConfigureComponent(msg)) {
5067        mCodec->mLoadedState->onStart();
5068    }
5069}
5070
5071bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
5072    ALOGV("onAllocateComponent");
5073
5074    CHECK(mCodec->mNode == 0);
5075
5076    OMXClient client;
5077    if (client.connect() != OK) {
5078        mCodec->signalError(OMX_ErrorUndefined, NO_INIT);
5079        return false;
5080    }
5081
5082    sp<IOMX> omx = client.interface();
5083
5084    sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec);
5085
5086    mDeathNotifier = new DeathNotifier(notify);
5087    if (IInterface::asBinder(omx)->linkToDeath(mDeathNotifier) != OK) {
5088        // This was a local binder, if it dies so do we, we won't care
5089        // about any notifications in the afterlife.
5090        mDeathNotifier.clear();
5091    }
5092
5093    Vector<OMXCodec::CodecNameAndQuirks> matchingCodecs;
5094
5095    AString mime;
5096
5097    AString componentName;
5098    uint32_t quirks = 0;
5099    int32_t encoder = false;
5100    if (msg->findString("componentName", &componentName)) {
5101        ssize_t index = matchingCodecs.add();
5102        OMXCodec::CodecNameAndQuirks *entry = &matchingCodecs.editItemAt(index);
5103        entry->mName = String8(componentName.c_str());
5104
5105        if (!OMXCodec::findCodecQuirks(
5106                    componentName.c_str(), &entry->mQuirks)) {
5107            entry->mQuirks = 0;
5108        }
5109    } else {
5110        CHECK(msg->findString("mime", &mime));
5111
5112        if (!msg->findInt32("encoder", &encoder)) {
5113            encoder = false;
5114        }
5115
5116        OMXCodec::findMatchingCodecs(
5117                mime.c_str(),
5118                encoder, // createEncoder
5119                NULL,  // matchComponentName
5120                0,     // flags
5121                &matchingCodecs);
5122    }
5123
5124    sp<CodecObserver> observer = new CodecObserver;
5125    IOMX::node_id node = 0;
5126
5127    status_t err = NAME_NOT_FOUND;
5128    for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
5129            ++matchIndex) {
5130        componentName = matchingCodecs.itemAt(matchIndex).mName.string();
5131        quirks = matchingCodecs.itemAt(matchIndex).mQuirks;
5132
5133        pid_t tid = gettid();
5134        int prevPriority = androidGetThreadPriority(tid);
5135        androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
5136        err = omx->allocateNode(componentName.c_str(), observer, &node);
5137        androidSetThreadPriority(tid, prevPriority);
5138
5139        if (err == OK) {
5140            break;
5141        } else {
5142            ALOGW("Allocating component '%s' failed, try next one.", componentName.c_str());
5143        }
5144
5145        node = 0;
5146    }
5147
5148    if (node == 0) {
5149        if (!mime.empty()) {
5150            ALOGE("Unable to instantiate a %scoder for type '%s' with err %#x.",
5151                    encoder ? "en" : "de", mime.c_str(), err);
5152        } else {
5153            ALOGE("Unable to instantiate codec '%s' with err %#x.", componentName.c_str(), err);
5154        }
5155
5156        mCodec->signalError((OMX_ERRORTYPE)err, makeNoSideEffectStatus(err));
5157        return false;
5158    }
5159
5160    notify = new AMessage(kWhatOMXMessage, mCodec);
5161    observer->setNotificationMessage(notify);
5162
5163    mCodec->mComponentName = componentName;
5164    mCodec->mFlags = 0;
5165
5166    if (componentName.endsWith(".secure")) {
5167        mCodec->mFlags |= kFlagIsSecure;
5168        mCodec->mFlags |= kFlagIsGrallocUsageProtected;
5169        mCodec->mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
5170    }
5171
5172    mCodec->mQuirks = quirks;
5173    mCodec->mOMX = omx;
5174    mCodec->mNode = node;
5175
5176    {
5177        sp<AMessage> notify = mCodec->mNotify->dup();
5178        notify->setInt32("what", CodecBase::kWhatComponentAllocated);
5179        notify->setString("componentName", mCodec->mComponentName.c_str());
5180        notify->post();
5181    }
5182
5183    mCodec->changeState(mCodec->mLoadedState);
5184
5185    return true;
5186}
5187
5188////////////////////////////////////////////////////////////////////////////////
5189
5190ACodec::LoadedState::LoadedState(ACodec *codec)
5191    : BaseState(codec) {
5192}
5193
5194void ACodec::LoadedState::stateEntered() {
5195    ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
5196
5197    mCodec->mPortEOS[kPortIndexInput] =
5198        mCodec->mPortEOS[kPortIndexOutput] = false;
5199
5200    mCodec->mInputEOSResult = OK;
5201
5202    mCodec->mDequeueCounter = 0;
5203    mCodec->mMetaDataBuffersToSubmit = 0;
5204    mCodec->mRepeatFrameDelayUs = -1ll;
5205    mCodec->mInputFormat.clear();
5206    mCodec->mOutputFormat.clear();
5207    mCodec->mBaseOutputFormat.clear();
5208
5209    if (mCodec->mShutdownInProgress) {
5210        bool keepComponentAllocated = mCodec->mKeepComponentAllocated;
5211
5212        mCodec->mShutdownInProgress = false;
5213        mCodec->mKeepComponentAllocated = false;
5214
5215        onShutdown(keepComponentAllocated);
5216    }
5217    mCodec->mExplicitShutdown = false;
5218
5219    mCodec->processDeferredMessages();
5220}
5221
5222void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) {
5223    if (!keepComponentAllocated) {
5224        (void)mCodec->mOMX->freeNode(mCodec->mNode);
5225
5226        mCodec->changeState(mCodec->mUninitializedState);
5227    }
5228
5229    if (mCodec->mExplicitShutdown) {
5230        sp<AMessage> notify = mCodec->mNotify->dup();
5231        notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
5232        notify->post();
5233        mCodec->mExplicitShutdown = false;
5234    }
5235}
5236
5237bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) {
5238    bool handled = false;
5239
5240    switch (msg->what()) {
5241        case ACodec::kWhatConfigureComponent:
5242        {
5243            onConfigureComponent(msg);
5244            handled = true;
5245            break;
5246        }
5247
5248        case ACodec::kWhatCreateInputSurface:
5249        {
5250            onCreateInputSurface(msg);
5251            handled = true;
5252            break;
5253        }
5254
5255        case ACodec::kWhatSetInputSurface:
5256        {
5257            onSetInputSurface(msg);
5258            handled = true;
5259            break;
5260        }
5261
5262        case ACodec::kWhatStart:
5263        {
5264            onStart();
5265            handled = true;
5266            break;
5267        }
5268
5269        case ACodec::kWhatShutdown:
5270        {
5271            int32_t keepComponentAllocated;
5272            CHECK(msg->findInt32(
5273                        "keepComponentAllocated", &keepComponentAllocated));
5274
5275            mCodec->mExplicitShutdown = true;
5276            onShutdown(keepComponentAllocated);
5277
5278            handled = true;
5279            break;
5280        }
5281
5282        case ACodec::kWhatFlush:
5283        {
5284            sp<AMessage> notify = mCodec->mNotify->dup();
5285            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
5286            notify->post();
5287
5288            handled = true;
5289            break;
5290        }
5291
5292        default:
5293            return BaseState::onMessageReceived(msg);
5294    }
5295
5296    return handled;
5297}
5298
5299bool ACodec::LoadedState::onConfigureComponent(
5300        const sp<AMessage> &msg) {
5301    ALOGV("onConfigureComponent");
5302
5303    CHECK(mCodec->mNode != 0);
5304
5305    status_t err = OK;
5306    AString mime;
5307    if (!msg->findString("mime", &mime)) {
5308        err = BAD_VALUE;
5309    } else {
5310        err = mCodec->configureCodec(mime.c_str(), msg);
5311    }
5312    if (err != OK) {
5313        ALOGE("[%s] configureCodec returning error %d",
5314              mCodec->mComponentName.c_str(), err);
5315
5316        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5317        return false;
5318    }
5319
5320    {
5321        sp<AMessage> notify = mCodec->mNotify->dup();
5322        notify->setInt32("what", CodecBase::kWhatComponentConfigured);
5323        notify->setMessage("input-format", mCodec->mInputFormat);
5324        notify->setMessage("output-format", mCodec->mOutputFormat);
5325        notify->post();
5326    }
5327
5328    return true;
5329}
5330
5331status_t ACodec::LoadedState::setupInputSurface() {
5332    status_t err = OK;
5333
5334    if (mCodec->mRepeatFrameDelayUs > 0ll) {
5335        err = mCodec->mOMX->setInternalOption(
5336                mCodec->mNode,
5337                kPortIndexInput,
5338                IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY,
5339                &mCodec->mRepeatFrameDelayUs,
5340                sizeof(mCodec->mRepeatFrameDelayUs));
5341
5342        if (err != OK) {
5343            ALOGE("[%s] Unable to configure option to repeat previous "
5344                  "frames (err %d)",
5345                  mCodec->mComponentName.c_str(),
5346                  err);
5347            return err;
5348        }
5349    }
5350
5351    if (mCodec->mMaxPtsGapUs > 0ll) {
5352        err = mCodec->mOMX->setInternalOption(
5353                mCodec->mNode,
5354                kPortIndexInput,
5355                IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP,
5356                &mCodec->mMaxPtsGapUs,
5357                sizeof(mCodec->mMaxPtsGapUs));
5358
5359        if (err != OK) {
5360            ALOGE("[%s] Unable to configure max timestamp gap (err %d)",
5361                    mCodec->mComponentName.c_str(),
5362                    err);
5363            return err;
5364        }
5365    }
5366
5367    if (mCodec->mMaxFps > 0) {
5368        err = mCodec->mOMX->setInternalOption(
5369                mCodec->mNode,
5370                kPortIndexInput,
5371                IOMX::INTERNAL_OPTION_MAX_FPS,
5372                &mCodec->mMaxFps,
5373                sizeof(mCodec->mMaxFps));
5374
5375        if (err != OK) {
5376            ALOGE("[%s] Unable to configure max fps (err %d)",
5377                    mCodec->mComponentName.c_str(),
5378                    err);
5379            return err;
5380        }
5381    }
5382
5383    if (mCodec->mTimePerCaptureUs > 0ll
5384            && mCodec->mTimePerFrameUs > 0ll) {
5385        int64_t timeLapse[2];
5386        timeLapse[0] = mCodec->mTimePerFrameUs;
5387        timeLapse[1] = mCodec->mTimePerCaptureUs;
5388        err = mCodec->mOMX->setInternalOption(
5389                mCodec->mNode,
5390                kPortIndexInput,
5391                IOMX::INTERNAL_OPTION_TIME_LAPSE,
5392                &timeLapse[0],
5393                sizeof(timeLapse));
5394
5395        if (err != OK) {
5396            ALOGE("[%s] Unable to configure time lapse (err %d)",
5397                    mCodec->mComponentName.c_str(),
5398                    err);
5399            return err;
5400        }
5401    }
5402
5403    if (mCodec->mCreateInputBuffersSuspended) {
5404        bool suspend = true;
5405        err = mCodec->mOMX->setInternalOption(
5406                mCodec->mNode,
5407                kPortIndexInput,
5408                IOMX::INTERNAL_OPTION_SUSPEND,
5409                &suspend,
5410                sizeof(suspend));
5411
5412        if (err != OK) {
5413            ALOGE("[%s] Unable to configure option to suspend (err %d)",
5414                  mCodec->mComponentName.c_str(),
5415                  err);
5416            return err;
5417        }
5418    }
5419
5420    return OK;
5421}
5422
5423void ACodec::LoadedState::onCreateInputSurface(
5424        const sp<AMessage> & /* msg */) {
5425    ALOGV("onCreateInputSurface");
5426
5427    sp<AMessage> notify = mCodec->mNotify->dup();
5428    notify->setInt32("what", CodecBase::kWhatInputSurfaceCreated);
5429
5430    sp<IGraphicBufferProducer> bufferProducer;
5431    status_t err = mCodec->mOMX->createInputSurface(
5432            mCodec->mNode, kPortIndexInput, &bufferProducer);
5433
5434    if (err == OK) {
5435        err = setupInputSurface();
5436    }
5437
5438    if (err == OK) {
5439        notify->setObject("input-surface",
5440                new BufferProducerWrapper(bufferProducer));
5441    } else {
5442        // Can't use mCodec->signalError() here -- MediaCodec won't forward
5443        // the error through because it's in the "configured" state.  We
5444        // send a kWhatInputSurfaceCreated with an error value instead.
5445        ALOGE("[%s] onCreateInputSurface returning error %d",
5446                mCodec->mComponentName.c_str(), err);
5447        notify->setInt32("err", err);
5448    }
5449    notify->post();
5450}
5451
5452void ACodec::LoadedState::onSetInputSurface(
5453        const sp<AMessage> &msg) {
5454    ALOGV("onSetInputSurface");
5455
5456    sp<AMessage> notify = mCodec->mNotify->dup();
5457    notify->setInt32("what", CodecBase::kWhatInputSurfaceAccepted);
5458
5459    sp<RefBase> obj;
5460    CHECK(msg->findObject("input-surface", &obj));
5461    sp<PersistentSurface> surface = static_cast<PersistentSurface *>(obj.get());
5462
5463    status_t err = mCodec->mOMX->setInputSurface(
5464            mCodec->mNode, kPortIndexInput, surface->getBufferConsumer());
5465
5466    if (err == OK) {
5467        err = setupInputSurface();
5468    }
5469
5470    if (err != OK) {
5471        // Can't use mCodec->signalError() here -- MediaCodec won't forward
5472        // the error through because it's in the "configured" state.  We
5473        // send a kWhatInputSurfaceAccepted with an error value instead.
5474        ALOGE("[%s] onSetInputSurface returning error %d",
5475                mCodec->mComponentName.c_str(), err);
5476        notify->setInt32("err", err);
5477    }
5478    notify->post();
5479}
5480
5481void ACodec::LoadedState::onStart() {
5482    ALOGV("onStart");
5483
5484    status_t err = mCodec->mOMX->sendCommand(mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle);
5485    if (err != OK) {
5486        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5487    } else {
5488        mCodec->changeState(mCodec->mLoadedToIdleState);
5489    }
5490}
5491
5492////////////////////////////////////////////////////////////////////////////////
5493
5494ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec)
5495    : BaseState(codec) {
5496}
5497
5498void ACodec::LoadedToIdleState::stateEntered() {
5499    ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
5500
5501    status_t err;
5502    if ((err = allocateBuffers()) != OK) {
5503        ALOGE("Failed to allocate buffers after transitioning to IDLE state "
5504             "(error 0x%08x)",
5505             err);
5506
5507        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5508
5509        mCodec->changeState(mCodec->mLoadedState);
5510    }
5511}
5512
5513status_t ACodec::LoadedToIdleState::allocateBuffers() {
5514    status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput);
5515
5516    if (err != OK) {
5517        return err;
5518    }
5519
5520    return mCodec->allocateBuffersOnPort(kPortIndexOutput);
5521}
5522
5523bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
5524    switch (msg->what()) {
5525        case kWhatSetParameters:
5526        case kWhatShutdown:
5527        {
5528            mCodec->deferMessage(msg);
5529            return true;
5530        }
5531
5532        case kWhatSignalEndOfInputStream:
5533        {
5534            mCodec->onSignalEndOfInputStream();
5535            return true;
5536        }
5537
5538        case kWhatResume:
5539        {
5540            // We'll be active soon enough.
5541            return true;
5542        }
5543
5544        case kWhatFlush:
5545        {
5546            // We haven't even started yet, so we're flushed alright...
5547            sp<AMessage> notify = mCodec->mNotify->dup();
5548            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
5549            notify->post();
5550            return true;
5551        }
5552
5553        default:
5554            return BaseState::onMessageReceived(msg);
5555    }
5556}
5557
5558bool ACodec::LoadedToIdleState::onOMXEvent(
5559        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5560    switch (event) {
5561        case OMX_EventCmdComplete:
5562        {
5563            status_t err = OK;
5564            if (data1 != (OMX_U32)OMX_CommandStateSet
5565                    || data2 != (OMX_U32)OMX_StateIdle) {
5566                ALOGE("Unexpected command completion in LoadedToIdleState: %s(%u) %s(%u)",
5567                        asString((OMX_COMMANDTYPE)data1), data1,
5568                        asString((OMX_STATETYPE)data2), data2);
5569                err = FAILED_TRANSACTION;
5570            }
5571
5572            if (err == OK) {
5573                err = mCodec->mOMX->sendCommand(
5574                    mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting);
5575            }
5576
5577            if (err != OK) {
5578                mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5579            } else {
5580                mCodec->changeState(mCodec->mIdleToExecutingState);
5581            }
5582
5583            return true;
5584        }
5585
5586        default:
5587            return BaseState::onOMXEvent(event, data1, data2);
5588    }
5589}
5590
5591////////////////////////////////////////////////////////////////////////////////
5592
5593ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec)
5594    : BaseState(codec) {
5595}
5596
5597void ACodec::IdleToExecutingState::stateEntered() {
5598    ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
5599}
5600
5601bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
5602    switch (msg->what()) {
5603        case kWhatSetParameters:
5604        case kWhatShutdown:
5605        {
5606            mCodec->deferMessage(msg);
5607            return true;
5608        }
5609
5610        case kWhatResume:
5611        {
5612            // We'll be active soon enough.
5613            return true;
5614        }
5615
5616        case kWhatFlush:
5617        {
5618            // We haven't even started yet, so we're flushed alright...
5619            sp<AMessage> notify = mCodec->mNotify->dup();
5620            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
5621            notify->post();
5622
5623            return true;
5624        }
5625
5626        case kWhatSignalEndOfInputStream:
5627        {
5628            mCodec->onSignalEndOfInputStream();
5629            return true;
5630        }
5631
5632        default:
5633            return BaseState::onMessageReceived(msg);
5634    }
5635}
5636
5637bool ACodec::IdleToExecutingState::onOMXEvent(
5638        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5639    switch (event) {
5640        case OMX_EventCmdComplete:
5641        {
5642            if (data1 != (OMX_U32)OMX_CommandStateSet
5643                    || data2 != (OMX_U32)OMX_StateExecuting) {
5644                ALOGE("Unexpected command completion in IdleToExecutingState: %s(%u) %s(%u)",
5645                        asString((OMX_COMMANDTYPE)data1), data1,
5646                        asString((OMX_STATETYPE)data2), data2);
5647                mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
5648                return true;
5649            }
5650
5651            mCodec->mExecutingState->resume();
5652            mCodec->changeState(mCodec->mExecutingState);
5653
5654            return true;
5655        }
5656
5657        default:
5658            return BaseState::onOMXEvent(event, data1, data2);
5659    }
5660}
5661
5662////////////////////////////////////////////////////////////////////////////////
5663
5664ACodec::ExecutingState::ExecutingState(ACodec *codec)
5665    : BaseState(codec),
5666      mActive(false) {
5667}
5668
5669ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode(
5670        OMX_U32 /* portIndex */) {
5671    return RESUBMIT_BUFFERS;
5672}
5673
5674void ACodec::ExecutingState::submitOutputMetaBuffers() {
5675    // submit as many buffers as there are input buffers with the codec
5676    // in case we are in port reconfiguring
5677    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
5678        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
5679
5680        if (info->mStatus == BufferInfo::OWNED_BY_COMPONENT) {
5681            if (mCodec->submitOutputMetaDataBuffer() != OK)
5682                break;
5683        }
5684    }
5685
5686    // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
5687    mCodec->signalSubmitOutputMetaDataBufferIfEOS_workaround();
5688}
5689
5690void ACodec::ExecutingState::submitRegularOutputBuffers() {
5691    bool failed = false;
5692    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
5693        BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
5694
5695        if (mCodec->mNativeWindow != NULL) {
5696            if (info->mStatus != BufferInfo::OWNED_BY_US
5697                    && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
5698                ALOGE("buffers should be owned by us or the surface");
5699                failed = true;
5700                break;
5701            }
5702
5703            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
5704                continue;
5705            }
5706        } else {
5707            if (info->mStatus != BufferInfo::OWNED_BY_US) {
5708                ALOGE("buffers should be owned by us");
5709                failed = true;
5710                break;
5711            }
5712        }
5713
5714        ALOGV("[%s] calling fillBuffer %u", mCodec->mComponentName.c_str(), info->mBufferID);
5715
5716        status_t err = mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID);
5717        if (err != OK) {
5718            failed = true;
5719            break;
5720        }
5721
5722        info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
5723    }
5724
5725    if (failed) {
5726        mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
5727    }
5728}
5729
5730void ACodec::ExecutingState::submitOutputBuffers() {
5731    submitRegularOutputBuffers();
5732    if (mCodec->mStoreMetaDataInOutputBuffers) {
5733        submitOutputMetaBuffers();
5734    }
5735}
5736
5737void ACodec::ExecutingState::resume() {
5738    if (mActive) {
5739        ALOGV("[%s] We're already active, no need to resume.", mCodec->mComponentName.c_str());
5740        return;
5741    }
5742
5743    submitOutputBuffers();
5744
5745    // Post all available input buffers
5746    if (mCodec->mBuffers[kPortIndexInput].size() == 0u) {
5747        ALOGW("[%s] we don't have any input buffers to resume", mCodec->mComponentName.c_str());
5748    }
5749
5750    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); i++) {
5751        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
5752        if (info->mStatus == BufferInfo::OWNED_BY_US) {
5753            postFillThisBuffer(info);
5754        }
5755    }
5756
5757    mActive = true;
5758}
5759
5760void ACodec::ExecutingState::stateEntered() {
5761    ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
5762
5763    mCodec->processDeferredMessages();
5764}
5765
5766bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) {
5767    bool handled = false;
5768
5769    switch (msg->what()) {
5770        case kWhatShutdown:
5771        {
5772            int32_t keepComponentAllocated;
5773            CHECK(msg->findInt32(
5774                        "keepComponentAllocated", &keepComponentAllocated));
5775
5776            mCodec->mShutdownInProgress = true;
5777            mCodec->mExplicitShutdown = true;
5778            mCodec->mKeepComponentAllocated = keepComponentAllocated;
5779
5780            mActive = false;
5781
5782            status_t err = mCodec->mOMX->sendCommand(
5783                    mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle);
5784            if (err != OK) {
5785                if (keepComponentAllocated) {
5786                    mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
5787                }
5788                // TODO: do some recovery here.
5789            } else {
5790                mCodec->changeState(mCodec->mExecutingToIdleState);
5791            }
5792
5793            handled = true;
5794            break;
5795        }
5796
5797        case kWhatFlush:
5798        {
5799            ALOGV("[%s] ExecutingState flushing now "
5800                 "(codec owns %zu/%zu input, %zu/%zu output).",
5801                    mCodec->mComponentName.c_str(),
5802                    mCodec->countBuffersOwnedByComponent(kPortIndexInput),
5803                    mCodec->mBuffers[kPortIndexInput].size(),
5804                    mCodec->countBuffersOwnedByComponent(kPortIndexOutput),
5805                    mCodec->mBuffers[kPortIndexOutput].size());
5806
5807            mActive = false;
5808
5809            status_t err = mCodec->mOMX->sendCommand(mCodec->mNode, OMX_CommandFlush, OMX_ALL);
5810            if (err != OK) {
5811                mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
5812            } else {
5813                mCodec->changeState(mCodec->mFlushingState);
5814            }
5815
5816            handled = true;
5817            break;
5818        }
5819
5820        case kWhatResume:
5821        {
5822            resume();
5823
5824            handled = true;
5825            break;
5826        }
5827
5828        case kWhatRequestIDRFrame:
5829        {
5830            status_t err = mCodec->requestIDRFrame();
5831            if (err != OK) {
5832                ALOGW("Requesting an IDR frame failed.");
5833            }
5834
5835            handled = true;
5836            break;
5837        }
5838
5839        case kWhatSetParameters:
5840        {
5841            sp<AMessage> params;
5842            CHECK(msg->findMessage("params", &params));
5843
5844            status_t err = mCodec->setParameters(params);
5845
5846            sp<AMessage> reply;
5847            if (msg->findMessage("reply", &reply)) {
5848                reply->setInt32("err", err);
5849                reply->post();
5850            }
5851
5852            handled = true;
5853            break;
5854        }
5855
5856        case ACodec::kWhatSignalEndOfInputStream:
5857        {
5858            mCodec->onSignalEndOfInputStream();
5859            handled = true;
5860            break;
5861        }
5862
5863        // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
5864        case kWhatSubmitOutputMetaDataBufferIfEOS:
5865        {
5866            if (mCodec->mPortEOS[kPortIndexInput] &&
5867                    !mCodec->mPortEOS[kPortIndexOutput]) {
5868                status_t err = mCodec->submitOutputMetaDataBuffer();
5869                if (err == OK) {
5870                    mCodec->signalSubmitOutputMetaDataBufferIfEOS_workaround();
5871                }
5872            }
5873            return true;
5874        }
5875
5876        default:
5877            handled = BaseState::onMessageReceived(msg);
5878            break;
5879    }
5880
5881    return handled;
5882}
5883
5884status_t ACodec::setParameters(const sp<AMessage> &params) {
5885    int32_t videoBitrate;
5886    if (params->findInt32("video-bitrate", &videoBitrate)) {
5887        OMX_VIDEO_CONFIG_BITRATETYPE configParams;
5888        InitOMXParams(&configParams);
5889        configParams.nPortIndex = kPortIndexOutput;
5890        configParams.nEncodeBitrate = videoBitrate;
5891
5892        status_t err = mOMX->setConfig(
5893                mNode,
5894                OMX_IndexConfigVideoBitrate,
5895                &configParams,
5896                sizeof(configParams));
5897
5898        if (err != OK) {
5899            ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d",
5900                   videoBitrate, err);
5901
5902            return err;
5903        }
5904    }
5905
5906    int64_t skipFramesBeforeUs;
5907    if (params->findInt64("skip-frames-before", &skipFramesBeforeUs)) {
5908        status_t err =
5909            mOMX->setInternalOption(
5910                     mNode,
5911                     kPortIndexInput,
5912                     IOMX::INTERNAL_OPTION_START_TIME,
5913                     &skipFramesBeforeUs,
5914                     sizeof(skipFramesBeforeUs));
5915
5916        if (err != OK) {
5917            ALOGE("Failed to set parameter 'skip-frames-before' (err %d)", err);
5918            return err;
5919        }
5920    }
5921
5922    int32_t dropInputFrames;
5923    if (params->findInt32("drop-input-frames", &dropInputFrames)) {
5924        bool suspend = dropInputFrames != 0;
5925
5926        status_t err =
5927            mOMX->setInternalOption(
5928                     mNode,
5929                     kPortIndexInput,
5930                     IOMX::INTERNAL_OPTION_SUSPEND,
5931                     &suspend,
5932                     sizeof(suspend));
5933
5934        if (err != OK) {
5935            ALOGE("Failed to set parameter 'drop-input-frames' (err %d)", err);
5936            return err;
5937        }
5938    }
5939
5940    int32_t dummy;
5941    if (params->findInt32("request-sync", &dummy)) {
5942        status_t err = requestIDRFrame();
5943
5944        if (err != OK) {
5945            ALOGE("Requesting a sync frame failed w/ err %d", err);
5946            return err;
5947        }
5948    }
5949
5950    float rate;
5951    if (params->findFloat("operating-rate", &rate) && rate > 0) {
5952        status_t err = setOperatingRate(rate, mIsVideo);
5953        if (err != OK) {
5954            ALOGE("Failed to set parameter 'operating-rate' (err %d)", err);
5955            return err;
5956        }
5957    }
5958
5959    return OK;
5960}
5961
5962void ACodec::onSignalEndOfInputStream() {
5963    sp<AMessage> notify = mNotify->dup();
5964    notify->setInt32("what", CodecBase::kWhatSignaledInputEOS);
5965
5966    status_t err = mOMX->signalEndOfInputStream(mNode);
5967    if (err != OK) {
5968        notify->setInt32("err", err);
5969    }
5970    notify->post();
5971}
5972
5973bool ACodec::ExecutingState::onOMXEvent(
5974        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5975    switch (event) {
5976        case OMX_EventPortSettingsChanged:
5977        {
5978            CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
5979
5980            if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
5981                mCodec->mMetaDataBuffersToSubmit = 0;
5982                CHECK_EQ(mCodec->mOMX->sendCommand(
5983                            mCodec->mNode,
5984                            OMX_CommandPortDisable, kPortIndexOutput),
5985                         (status_t)OK);
5986
5987                mCodec->freeOutputBuffersNotOwnedByComponent();
5988
5989                mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
5990            } else if (data2 == OMX_IndexConfigCommonOutputCrop) {
5991                mCodec->mSentFormat = false;
5992            } else {
5993                ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08x",
5994                     mCodec->mComponentName.c_str(), data2);
5995            }
5996
5997            return true;
5998        }
5999
6000        case OMX_EventBufferFlag:
6001        {
6002            return true;
6003        }
6004
6005        default:
6006            return BaseState::onOMXEvent(event, data1, data2);
6007    }
6008}
6009
6010////////////////////////////////////////////////////////////////////////////////
6011
6012ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState(
6013        ACodec *codec)
6014    : BaseState(codec) {
6015}
6016
6017ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode(
6018        OMX_U32 portIndex) {
6019    if (portIndex == kPortIndexOutput) {
6020        return FREE_BUFFERS;
6021    }
6022
6023    CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput);
6024
6025    return RESUBMIT_BUFFERS;
6026}
6027
6028bool ACodec::OutputPortSettingsChangedState::onMessageReceived(
6029        const sp<AMessage> &msg) {
6030    bool handled = false;
6031
6032    switch (msg->what()) {
6033        case kWhatFlush:
6034        case kWhatShutdown:
6035        case kWhatResume:
6036        case kWhatSetParameters:
6037        {
6038            if (msg->what() == kWhatResume) {
6039                ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
6040            }
6041
6042            mCodec->deferMessage(msg);
6043            handled = true;
6044            break;
6045        }
6046
6047        default:
6048            handled = BaseState::onMessageReceived(msg);
6049            break;
6050    }
6051
6052    return handled;
6053}
6054
6055void ACodec::OutputPortSettingsChangedState::stateEntered() {
6056    ALOGV("[%s] Now handling output port settings change",
6057         mCodec->mComponentName.c_str());
6058}
6059
6060bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
6061        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
6062    switch (event) {
6063        case OMX_EventCmdComplete:
6064        {
6065            if (data1 == (OMX_U32)OMX_CommandPortDisable) {
6066                if (data2 != (OMX_U32)kPortIndexOutput) {
6067                    ALOGW("ignoring EventCmdComplete CommandPortDisable for port %u", data2);
6068                    return false;
6069                }
6070
6071                ALOGV("[%s] Output port now disabled.", mCodec->mComponentName.c_str());
6072
6073                status_t err = OK;
6074                if (!mCodec->mBuffers[kPortIndexOutput].isEmpty()) {
6075                    ALOGE("disabled port should be empty, but has %zu buffers",
6076                            mCodec->mBuffers[kPortIndexOutput].size());
6077                    err = FAILED_TRANSACTION;
6078                } else {
6079                    mCodec->mDealer[kPortIndexOutput].clear();
6080                }
6081
6082                if (err == OK) {
6083                    err = mCodec->mOMX->sendCommand(
6084                            mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput);
6085                }
6086
6087                if (err == OK) {
6088                    err = mCodec->allocateBuffersOnPort(kPortIndexOutput);
6089                    ALOGE_IF(err != OK, "Failed to allocate output port buffers after port "
6090                            "reconfiguration: (%d)", err);
6091                }
6092
6093                if (err != OK) {
6094                    mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6095
6096                    // This is technically not correct, but appears to be
6097                    // the only way to free the component instance.
6098                    // Controlled transitioning from excecuting->idle
6099                    // and idle->loaded seem impossible probably because
6100                    // the output port never finishes re-enabling.
6101                    mCodec->mShutdownInProgress = true;
6102                    mCodec->mKeepComponentAllocated = false;
6103                    mCodec->changeState(mCodec->mLoadedState);
6104                }
6105
6106                return true;
6107            } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
6108                if (data2 != (OMX_U32)kPortIndexOutput) {
6109                    ALOGW("ignoring EventCmdComplete OMX_CommandPortEnable for port %u", data2);
6110                    return false;
6111                }
6112
6113                mCodec->mSentFormat = false;
6114
6115                ALOGV("[%s] Output port now reenabled.", mCodec->mComponentName.c_str());
6116
6117                if (mCodec->mExecutingState->active()) {
6118                    mCodec->mExecutingState->submitOutputBuffers();
6119                }
6120
6121                mCodec->changeState(mCodec->mExecutingState);
6122
6123                return true;
6124            }
6125
6126            return false;
6127        }
6128
6129        default:
6130            return false;
6131    }
6132}
6133
6134////////////////////////////////////////////////////////////////////////////////
6135
6136ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec)
6137    : BaseState(codec),
6138      mComponentNowIdle(false) {
6139}
6140
6141bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) {
6142    bool handled = false;
6143
6144    switch (msg->what()) {
6145        case kWhatFlush:
6146        {
6147            // Don't send me a flush request if you previously wanted me
6148            // to shutdown.
6149            ALOGW("Ignoring flush request in ExecutingToIdleState");
6150            break;
6151        }
6152
6153        case kWhatShutdown:
6154        {
6155            // We're already doing that...
6156
6157            handled = true;
6158            break;
6159        }
6160
6161        default:
6162            handled = BaseState::onMessageReceived(msg);
6163            break;
6164    }
6165
6166    return handled;
6167}
6168
6169void ACodec::ExecutingToIdleState::stateEntered() {
6170    ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
6171
6172    mComponentNowIdle = false;
6173    mCodec->mSentFormat = false;
6174}
6175
6176bool ACodec::ExecutingToIdleState::onOMXEvent(
6177        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
6178    switch (event) {
6179        case OMX_EventCmdComplete:
6180        {
6181            if (data1 != (OMX_U32)OMX_CommandStateSet
6182                    || data2 != (OMX_U32)OMX_StateIdle) {
6183                ALOGE("Unexpected command completion in ExecutingToIdleState: %s(%u) %s(%u)",
6184                        asString((OMX_COMMANDTYPE)data1), data1,
6185                        asString((OMX_STATETYPE)data2), data2);
6186                mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
6187                return true;
6188            }
6189
6190            mComponentNowIdle = true;
6191
6192            changeStateIfWeOwnAllBuffers();
6193
6194            return true;
6195        }
6196
6197        case OMX_EventPortSettingsChanged:
6198        case OMX_EventBufferFlag:
6199        {
6200            // We're shutting down and don't care about this anymore.
6201            return true;
6202        }
6203
6204        default:
6205            return BaseState::onOMXEvent(event, data1, data2);
6206    }
6207}
6208
6209void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
6210    if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) {
6211        status_t err = mCodec->mOMX->sendCommand(
6212                mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded);
6213        if (err == OK) {
6214            err = mCodec->freeBuffersOnPort(kPortIndexInput);
6215            status_t err2 = mCodec->freeBuffersOnPort(kPortIndexOutput);
6216            if (err == OK) {
6217                err = err2;
6218            }
6219        }
6220
6221        if ((mCodec->mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown)
6222                && mCodec->mNativeWindow != NULL) {
6223            // We push enough 1x1 blank buffers to ensure that one of
6224            // them has made it to the display.  This allows the OMX
6225            // component teardown to zero out any protected buffers
6226            // without the risk of scanning out one of those buffers.
6227            pushBlankBuffersToNativeWindow(mCodec->mNativeWindow.get());
6228        }
6229
6230        if (err != OK) {
6231            mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
6232            return;
6233        }
6234
6235        mCodec->changeState(mCodec->mIdleToLoadedState);
6236    }
6237}
6238
6239void ACodec::ExecutingToIdleState::onInputBufferFilled(
6240        const sp<AMessage> &msg) {
6241    BaseState::onInputBufferFilled(msg);
6242
6243    changeStateIfWeOwnAllBuffers();
6244}
6245
6246void ACodec::ExecutingToIdleState::onOutputBufferDrained(
6247        const sp<AMessage> &msg) {
6248    BaseState::onOutputBufferDrained(msg);
6249
6250    changeStateIfWeOwnAllBuffers();
6251}
6252
6253////////////////////////////////////////////////////////////////////////////////
6254
6255ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec)
6256    : BaseState(codec) {
6257}
6258
6259bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) {
6260    bool handled = false;
6261
6262    switch (msg->what()) {
6263        case kWhatShutdown:
6264        {
6265            // We're already doing that...
6266
6267            handled = true;
6268            break;
6269        }
6270
6271        case kWhatFlush:
6272        {
6273            // Don't send me a flush request if you previously wanted me
6274            // to shutdown.
6275            ALOGE("Got flush request in IdleToLoadedState");
6276            break;
6277        }
6278
6279        default:
6280            handled = BaseState::onMessageReceived(msg);
6281            break;
6282    }
6283
6284    return handled;
6285}
6286
6287void ACodec::IdleToLoadedState::stateEntered() {
6288    ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
6289}
6290
6291bool ACodec::IdleToLoadedState::onOMXEvent(
6292        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
6293    switch (event) {
6294        case OMX_EventCmdComplete:
6295        {
6296            if (data1 != (OMX_U32)OMX_CommandStateSet
6297                    || data2 != (OMX_U32)OMX_StateLoaded) {
6298                ALOGE("Unexpected command completion in IdleToLoadedState: %s(%u) %s(%u)",
6299                        asString((OMX_COMMANDTYPE)data1), data1,
6300                        asString((OMX_STATETYPE)data2), data2);
6301                mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
6302                return true;
6303            }
6304
6305            mCodec->changeState(mCodec->mLoadedState);
6306
6307            return true;
6308        }
6309
6310        default:
6311            return BaseState::onOMXEvent(event, data1, data2);
6312    }
6313}
6314
6315////////////////////////////////////////////////////////////////////////////////
6316
6317ACodec::FlushingState::FlushingState(ACodec *codec)
6318    : BaseState(codec) {
6319}
6320
6321void ACodec::FlushingState::stateEntered() {
6322    ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());
6323
6324    mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
6325}
6326
6327bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) {
6328    bool handled = false;
6329
6330    switch (msg->what()) {
6331        case kWhatShutdown:
6332        {
6333            mCodec->deferMessage(msg);
6334            break;
6335        }
6336
6337        case kWhatFlush:
6338        {
6339            // We're already doing this right now.
6340            handled = true;
6341            break;
6342        }
6343
6344        default:
6345            handled = BaseState::onMessageReceived(msg);
6346            break;
6347    }
6348
6349    return handled;
6350}
6351
6352bool ACodec::FlushingState::onOMXEvent(
6353        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
6354    ALOGV("[%s] FlushingState onOMXEvent(%u,%d)",
6355            mCodec->mComponentName.c_str(), event, (OMX_S32)data1);
6356
6357    switch (event) {
6358        case OMX_EventCmdComplete:
6359        {
6360            if (data1 != (OMX_U32)OMX_CommandFlush) {
6361                ALOGE("unexpected EventCmdComplete %s(%d) data2:%d in FlushingState",
6362                        asString((OMX_COMMANDTYPE)data1), data1, data2);
6363                mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
6364                return true;
6365            }
6366
6367            if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
6368                if (mFlushComplete[data2]) {
6369                    ALOGW("Flush already completed for %s port",
6370                            data2 == kPortIndexInput ? "input" : "output");
6371                    return true;
6372                }
6373                mFlushComplete[data2] = true;
6374
6375                if (mFlushComplete[kPortIndexInput] && mFlushComplete[kPortIndexOutput]) {
6376                    changeStateIfWeOwnAllBuffers();
6377                }
6378            } else if (data2 == OMX_ALL) {
6379                if (!mFlushComplete[kPortIndexInput] || !mFlushComplete[kPortIndexOutput]) {
6380                    ALOGW("received flush complete event for OMX_ALL before ports have been"
6381                            "flushed (%d/%d)",
6382                            mFlushComplete[kPortIndexInput], mFlushComplete[kPortIndexOutput]);
6383                    return false;
6384                }
6385
6386                changeStateIfWeOwnAllBuffers();
6387            } else {
6388                ALOGW("data2 not OMX_ALL but %u in EventCmdComplete CommandFlush", data2);
6389            }
6390
6391            return true;
6392        }
6393
6394        case OMX_EventPortSettingsChanged:
6395        {
6396            sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec);
6397            msg->setInt32("type", omx_message::EVENT);
6398            msg->setInt32("node", mCodec->mNode);
6399            msg->setInt32("event", event);
6400            msg->setInt32("data1", data1);
6401            msg->setInt32("data2", data2);
6402
6403            ALOGV("[%s] Deferring OMX_EventPortSettingsChanged",
6404                 mCodec->mComponentName.c_str());
6405
6406            mCodec->deferMessage(msg);
6407
6408            return true;
6409        }
6410
6411        default:
6412            return BaseState::onOMXEvent(event, data1, data2);
6413    }
6414
6415    return true;
6416}
6417
6418void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) {
6419    BaseState::onOutputBufferDrained(msg);
6420
6421    changeStateIfWeOwnAllBuffers();
6422}
6423
6424void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) {
6425    BaseState::onInputBufferFilled(msg);
6426
6427    changeStateIfWeOwnAllBuffers();
6428}
6429
6430void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() {
6431    if (mFlushComplete[kPortIndexInput]
6432            && mFlushComplete[kPortIndexOutput]
6433            && mCodec->allYourBuffersAreBelongToUs()) {
6434        // We now own all buffers except possibly those still queued with
6435        // the native window for rendering. Let's get those back as well.
6436        mCodec->waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs();
6437
6438        sp<AMessage> notify = mCodec->mNotify->dup();
6439        notify->setInt32("what", CodecBase::kWhatFlushCompleted);
6440        notify->post();
6441
6442        mCodec->mPortEOS[kPortIndexInput] =
6443            mCodec->mPortEOS[kPortIndexOutput] = false;
6444
6445        mCodec->mInputEOSResult = OK;
6446
6447        if (mCodec->mSkipCutBuffer != NULL) {
6448            mCodec->mSkipCutBuffer->clear();
6449        }
6450
6451        mCodec->changeState(mCodec->mExecutingState);
6452    }
6453}
6454
6455}  // namespace android
6456