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