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