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