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