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