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