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