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