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