ACodec.cpp revision 78b01639c08fe5e7e9c1be5e9dc5de560f1383f9
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    int32_t frameRateInt;
2228    float frameRateFloat;
2229    if (!msg->findFloat("frame-rate", &frameRateFloat)) {
2230        if (!msg->findInt32("frame-rate", &frameRateInt)) {
2231            frameRateInt = -1;
2232        }
2233        frameRateFloat = (float)frameRateInt;
2234    }
2235
2236    err = setVideoFormatOnPort(
2237            kPortIndexInput, width, height, compressionFormat, frameRateFloat);
2238
2239    if (err != OK) {
2240        return err;
2241    }
2242
2243    err = setVideoFormatOnPort(
2244            kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused);
2245
2246    if (err != OK) {
2247        return err;
2248    }
2249
2250    return OK;
2251}
2252
2253status_t ACodec::setupVideoEncoder(const char *mime, const sp<AMessage> &msg) {
2254    int32_t tmp;
2255    if (!msg->findInt32("color-format", &tmp)) {
2256        return INVALID_OPERATION;
2257    }
2258
2259    OMX_COLOR_FORMATTYPE colorFormat =
2260        static_cast<OMX_COLOR_FORMATTYPE>(tmp);
2261
2262    status_t err = setVideoPortFormatType(
2263            kPortIndexInput, OMX_VIDEO_CodingUnused, colorFormat);
2264
2265    if (err != OK) {
2266        ALOGE("[%s] does not support color format %d",
2267              mComponentName.c_str(), colorFormat);
2268
2269        return err;
2270    }
2271
2272    /* Input port configuration */
2273
2274    OMX_PARAM_PORTDEFINITIONTYPE def;
2275    InitOMXParams(&def);
2276
2277    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
2278
2279    def.nPortIndex = kPortIndexInput;
2280
2281    err = mOMX->getParameter(
2282            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2283
2284    if (err != OK) {
2285        return err;
2286    }
2287
2288    int32_t width, height, bitrate;
2289    if (!msg->findInt32("width", &width)
2290            || !msg->findInt32("height", &height)
2291            || !msg->findInt32("bitrate", &bitrate)) {
2292        return INVALID_OPERATION;
2293    }
2294
2295    video_def->nFrameWidth = width;
2296    video_def->nFrameHeight = height;
2297
2298    int32_t stride;
2299    if (!msg->findInt32("stride", &stride)) {
2300        stride = width;
2301    }
2302
2303    video_def->nStride = stride;
2304
2305    int32_t sliceHeight;
2306    if (!msg->findInt32("slice-height", &sliceHeight)) {
2307        sliceHeight = height;
2308    }
2309
2310    video_def->nSliceHeight = sliceHeight;
2311
2312    def.nBufferSize = (video_def->nStride * video_def->nSliceHeight * 3) / 2;
2313
2314    float frameRate;
2315    if (!msg->findFloat("frame-rate", &frameRate)) {
2316        int32_t tmp;
2317        if (!msg->findInt32("frame-rate", &tmp)) {
2318            return INVALID_OPERATION;
2319        }
2320        frameRate = (float)tmp;
2321        mTimePerFrameUs = (int64_t) (1000000.0f / frameRate);
2322    }
2323
2324    video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f);
2325    video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
2326    // this is redundant as it was already set up in setVideoPortFormatType
2327    // FIXME for now skip this only for flexible YUV formats
2328    if (colorFormat != OMX_COLOR_FormatYUV420Flexible) {
2329        video_def->eColorFormat = colorFormat;
2330    }
2331
2332    err = mOMX->setParameter(
2333            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2334
2335    if (err != OK) {
2336        ALOGE("[%s] failed to set input port definition parameters.",
2337              mComponentName.c_str());
2338
2339        return err;
2340    }
2341
2342    /* Output port configuration */
2343
2344    OMX_VIDEO_CODINGTYPE compressionFormat;
2345    err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
2346
2347    if (err != OK) {
2348        return err;
2349    }
2350
2351    err = setVideoPortFormatType(
2352            kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused);
2353
2354    if (err != OK) {
2355        ALOGE("[%s] does not support compression format %d",
2356             mComponentName.c_str(), compressionFormat);
2357
2358        return err;
2359    }
2360
2361    def.nPortIndex = kPortIndexOutput;
2362
2363    err = mOMX->getParameter(
2364            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2365
2366    if (err != OK) {
2367        return err;
2368    }
2369
2370    video_def->nFrameWidth = width;
2371    video_def->nFrameHeight = height;
2372    video_def->xFramerate = 0;
2373    video_def->nBitrate = bitrate;
2374    video_def->eCompressionFormat = compressionFormat;
2375    video_def->eColorFormat = OMX_COLOR_FormatUnused;
2376
2377    err = mOMX->setParameter(
2378            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2379
2380    if (err != OK) {
2381        ALOGE("[%s] failed to set output port definition parameters.",
2382              mComponentName.c_str());
2383
2384        return err;
2385    }
2386
2387    switch (compressionFormat) {
2388        case OMX_VIDEO_CodingMPEG4:
2389            err = setupMPEG4EncoderParameters(msg);
2390            break;
2391
2392        case OMX_VIDEO_CodingH263:
2393            err = setupH263EncoderParameters(msg);
2394            break;
2395
2396        case OMX_VIDEO_CodingAVC:
2397            err = setupAVCEncoderParameters(msg);
2398            break;
2399
2400        case OMX_VIDEO_CodingHEVC:
2401            err = setupHEVCEncoderParameters(msg);
2402            break;
2403
2404        case OMX_VIDEO_CodingVP8:
2405        case OMX_VIDEO_CodingVP9:
2406            err = setupVPXEncoderParameters(msg);
2407            break;
2408
2409        default:
2410            break;
2411    }
2412
2413    ALOGI("setupVideoEncoder succeeded");
2414
2415    return err;
2416}
2417
2418status_t ACodec::setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode) {
2419    OMX_VIDEO_PARAM_INTRAREFRESHTYPE params;
2420    InitOMXParams(&params);
2421    params.nPortIndex = kPortIndexOutput;
2422
2423    params.eRefreshMode = static_cast<OMX_VIDEO_INTRAREFRESHTYPE>(mode);
2424
2425    if (params.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic ||
2426            params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) {
2427        int32_t mbs;
2428        if (!msg->findInt32("intra-refresh-CIR-mbs", &mbs)) {
2429            return INVALID_OPERATION;
2430        }
2431        params.nCirMBs = mbs;
2432    }
2433
2434    if (params.eRefreshMode == OMX_VIDEO_IntraRefreshAdaptive ||
2435            params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) {
2436        int32_t mbs;
2437        if (!msg->findInt32("intra-refresh-AIR-mbs", &mbs)) {
2438            return INVALID_OPERATION;
2439        }
2440        params.nAirMBs = mbs;
2441
2442        int32_t ref;
2443        if (!msg->findInt32("intra-refresh-AIR-ref", &ref)) {
2444            return INVALID_OPERATION;
2445        }
2446        params.nAirRef = ref;
2447    }
2448
2449    status_t err = mOMX->setParameter(
2450            mNode, OMX_IndexParamVideoIntraRefresh,
2451            &params, sizeof(params));
2452    return err;
2453}
2454
2455static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) {
2456    if (iFramesInterval < 0) {
2457        return 0xFFFFFFFF;
2458    } else if (iFramesInterval == 0) {
2459        return 0;
2460    }
2461    OMX_U32 ret = frameRate * iFramesInterval;
2462    return ret;
2463}
2464
2465static OMX_VIDEO_CONTROLRATETYPE getBitrateMode(const sp<AMessage> &msg) {
2466    int32_t tmp;
2467    if (!msg->findInt32("bitrate-mode", &tmp)) {
2468        return OMX_Video_ControlRateVariable;
2469    }
2470
2471    return static_cast<OMX_VIDEO_CONTROLRATETYPE>(tmp);
2472}
2473
2474status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) {
2475    int32_t bitrate, iFrameInterval;
2476    if (!msg->findInt32("bitrate", &bitrate)
2477            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
2478        return INVALID_OPERATION;
2479    }
2480
2481    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
2482
2483    float frameRate;
2484    if (!msg->findFloat("frame-rate", &frameRate)) {
2485        int32_t tmp;
2486        if (!msg->findInt32("frame-rate", &tmp)) {
2487            return INVALID_OPERATION;
2488        }
2489        frameRate = (float)tmp;
2490    }
2491
2492    OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type;
2493    InitOMXParams(&mpeg4type);
2494    mpeg4type.nPortIndex = kPortIndexOutput;
2495
2496    status_t err = mOMX->getParameter(
2497            mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
2498
2499    if (err != OK) {
2500        return err;
2501    }
2502
2503    mpeg4type.nSliceHeaderSpacing = 0;
2504    mpeg4type.bSVH = OMX_FALSE;
2505    mpeg4type.bGov = OMX_FALSE;
2506
2507    mpeg4type.nAllowedPictureTypes =
2508        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
2509
2510    mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
2511    if (mpeg4type.nPFrames == 0) {
2512        mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
2513    }
2514    mpeg4type.nBFrames = 0;
2515    mpeg4type.nIDCVLCThreshold = 0;
2516    mpeg4type.bACPred = OMX_TRUE;
2517    mpeg4type.nMaxPacketSize = 256;
2518    mpeg4type.nTimeIncRes = 1000;
2519    mpeg4type.nHeaderExtension = 0;
2520    mpeg4type.bReversibleVLC = OMX_FALSE;
2521
2522    int32_t profile;
2523    if (msg->findInt32("profile", &profile)) {
2524        int32_t level;
2525        if (!msg->findInt32("level", &level)) {
2526            return INVALID_OPERATION;
2527        }
2528
2529        err = verifySupportForProfileAndLevel(profile, level);
2530
2531        if (err != OK) {
2532            return err;
2533        }
2534
2535        mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile);
2536        mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level);
2537    }
2538
2539    err = mOMX->setParameter(
2540            mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
2541
2542    if (err != OK) {
2543        return err;
2544    }
2545
2546    err = configureBitrate(bitrate, bitrateMode);
2547
2548    if (err != OK) {
2549        return err;
2550    }
2551
2552    return setupErrorCorrectionParameters();
2553}
2554
2555status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) {
2556    int32_t bitrate, iFrameInterval;
2557    if (!msg->findInt32("bitrate", &bitrate)
2558            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
2559        return INVALID_OPERATION;
2560    }
2561
2562    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
2563
2564    float frameRate;
2565    if (!msg->findFloat("frame-rate", &frameRate)) {
2566        int32_t tmp;
2567        if (!msg->findInt32("frame-rate", &tmp)) {
2568            return INVALID_OPERATION;
2569        }
2570        frameRate = (float)tmp;
2571    }
2572
2573    OMX_VIDEO_PARAM_H263TYPE h263type;
2574    InitOMXParams(&h263type);
2575    h263type.nPortIndex = kPortIndexOutput;
2576
2577    status_t err = mOMX->getParameter(
2578            mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
2579
2580    if (err != OK) {
2581        return err;
2582    }
2583
2584    h263type.nAllowedPictureTypes =
2585        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
2586
2587    h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
2588    if (h263type.nPFrames == 0) {
2589        h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
2590    }
2591    h263type.nBFrames = 0;
2592
2593    int32_t profile;
2594    if (msg->findInt32("profile", &profile)) {
2595        int32_t level;
2596        if (!msg->findInt32("level", &level)) {
2597            return INVALID_OPERATION;
2598        }
2599
2600        err = verifySupportForProfileAndLevel(profile, level);
2601
2602        if (err != OK) {
2603            return err;
2604        }
2605
2606        h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile);
2607        h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level);
2608    }
2609
2610    h263type.bPLUSPTYPEAllowed = OMX_FALSE;
2611    h263type.bForceRoundingTypeToZero = OMX_FALSE;
2612    h263type.nPictureHeaderRepetition = 0;
2613    h263type.nGOBHeaderInterval = 0;
2614
2615    err = mOMX->setParameter(
2616            mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
2617
2618    if (err != OK) {
2619        return err;
2620    }
2621
2622    err = configureBitrate(bitrate, bitrateMode);
2623
2624    if (err != OK) {
2625        return err;
2626    }
2627
2628    return setupErrorCorrectionParameters();
2629}
2630
2631// static
2632int /* OMX_VIDEO_AVCLEVELTYPE */ ACodec::getAVCLevelFor(
2633        int width, int height, int rate, int bitrate,
2634        OMX_VIDEO_AVCPROFILETYPE profile) {
2635    // convert bitrate to main/baseline profile kbps equivalent
2636    switch (profile) {
2637        case OMX_VIDEO_AVCProfileHigh10:
2638            bitrate = divUp(bitrate, 3000); break;
2639        case OMX_VIDEO_AVCProfileHigh:
2640            bitrate = divUp(bitrate, 1250); break;
2641        default:
2642            bitrate = divUp(bitrate, 1000); break;
2643    }
2644
2645    // convert size and rate to MBs
2646    width = divUp(width, 16);
2647    height = divUp(height, 16);
2648    int mbs = width * height;
2649    rate *= mbs;
2650    int maxDimension = max(width, height);
2651
2652    static const int limits[][5] = {
2653        /*   MBps     MB   dim  bitrate        level */
2654        {    1485,    99,  28,     64, OMX_VIDEO_AVCLevel1  },
2655        {    1485,    99,  28,    128, OMX_VIDEO_AVCLevel1b },
2656        {    3000,   396,  56,    192, OMX_VIDEO_AVCLevel11 },
2657        {    6000,   396,  56,    384, OMX_VIDEO_AVCLevel12 },
2658        {   11880,   396,  56,    768, OMX_VIDEO_AVCLevel13 },
2659        {   11880,   396,  56,   2000, OMX_VIDEO_AVCLevel2  },
2660        {   19800,   792,  79,   4000, OMX_VIDEO_AVCLevel21 },
2661        {   20250,  1620, 113,   4000, OMX_VIDEO_AVCLevel22 },
2662        {   40500,  1620, 113,  10000, OMX_VIDEO_AVCLevel3  },
2663        {  108000,  3600, 169,  14000, OMX_VIDEO_AVCLevel31 },
2664        {  216000,  5120, 202,  20000, OMX_VIDEO_AVCLevel32 },
2665        {  245760,  8192, 256,  20000, OMX_VIDEO_AVCLevel4  },
2666        {  245760,  8192, 256,  50000, OMX_VIDEO_AVCLevel41 },
2667        {  522240,  8704, 263,  50000, OMX_VIDEO_AVCLevel42 },
2668        {  589824, 22080, 420, 135000, OMX_VIDEO_AVCLevel5  },
2669        {  983040, 36864, 543, 240000, OMX_VIDEO_AVCLevel51 },
2670        { 2073600, 36864, 543, 240000, OMX_VIDEO_AVCLevel52 },
2671    };
2672
2673    for (size_t i = 0; i < ARRAY_SIZE(limits); i++) {
2674        const int (&limit)[5] = limits[i];
2675        if (rate <= limit[0] && mbs <= limit[1] && maxDimension <= limit[2]
2676                && bitrate <= limit[3]) {
2677            return limit[4];
2678        }
2679    }
2680    return 0;
2681}
2682
2683status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) {
2684    int32_t bitrate, iFrameInterval;
2685    if (!msg->findInt32("bitrate", &bitrate)
2686            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
2687        return INVALID_OPERATION;
2688    }
2689
2690    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
2691
2692    float frameRate;
2693    if (!msg->findFloat("frame-rate", &frameRate)) {
2694        int32_t tmp;
2695        if (!msg->findInt32("frame-rate", &tmp)) {
2696            return INVALID_OPERATION;
2697        }
2698        frameRate = (float)tmp;
2699    }
2700
2701    status_t err = OK;
2702    int32_t intraRefreshMode = 0;
2703    if (msg->findInt32("intra-refresh-mode", &intraRefreshMode)) {
2704        err = setCyclicIntraMacroblockRefresh(msg, intraRefreshMode);
2705        if (err != OK) {
2706            ALOGE("Setting intra macroblock refresh mode (%d) failed: 0x%x",
2707                    err, intraRefreshMode);
2708            return err;
2709        }
2710    }
2711
2712    OMX_VIDEO_PARAM_AVCTYPE h264type;
2713    InitOMXParams(&h264type);
2714    h264type.nPortIndex = kPortIndexOutput;
2715
2716    err = mOMX->getParameter(
2717            mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
2718
2719    if (err != OK) {
2720        return err;
2721    }
2722
2723    h264type.nAllowedPictureTypes =
2724        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
2725
2726    int32_t profile;
2727    if (msg->findInt32("profile", &profile)) {
2728        int32_t level;
2729        if (!msg->findInt32("level", &level)) {
2730            return INVALID_OPERATION;
2731        }
2732
2733        err = verifySupportForProfileAndLevel(profile, level);
2734
2735        if (err != OK) {
2736            return err;
2737        }
2738
2739        h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile);
2740        h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level);
2741    }
2742
2743    // XXX
2744    if (h264type.eProfile != OMX_VIDEO_AVCProfileBaseline) {
2745        ALOGW("Use baseline profile instead of %d for AVC recording",
2746            h264type.eProfile);
2747        h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
2748    }
2749
2750    if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
2751        h264type.nSliceHeaderSpacing = 0;
2752        h264type.bUseHadamard = OMX_TRUE;
2753        h264type.nRefFrames = 1;
2754        h264type.nBFrames = 0;
2755        h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
2756        if (h264type.nPFrames == 0) {
2757            h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
2758        }
2759        h264type.nRefIdx10ActiveMinus1 = 0;
2760        h264type.nRefIdx11ActiveMinus1 = 0;
2761        h264type.bEntropyCodingCABAC = OMX_FALSE;
2762        h264type.bWeightedPPrediction = OMX_FALSE;
2763        h264type.bconstIpred = OMX_FALSE;
2764        h264type.bDirect8x8Inference = OMX_FALSE;
2765        h264type.bDirectSpatialTemporal = OMX_FALSE;
2766        h264type.nCabacInitIdc = 0;
2767    }
2768
2769    if (h264type.nBFrames != 0) {
2770        h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
2771    }
2772
2773    h264type.bEnableUEP = OMX_FALSE;
2774    h264type.bEnableFMO = OMX_FALSE;
2775    h264type.bEnableASO = OMX_FALSE;
2776    h264type.bEnableRS = OMX_FALSE;
2777    h264type.bFrameMBsOnly = OMX_TRUE;
2778    h264type.bMBAFF = OMX_FALSE;
2779    h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
2780
2781    err = mOMX->setParameter(
2782            mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
2783
2784    if (err != OK) {
2785        return err;
2786    }
2787
2788    return configureBitrate(bitrate, bitrateMode);
2789}
2790
2791status_t ACodec::setupHEVCEncoderParameters(const sp<AMessage> &msg) {
2792    int32_t bitrate, iFrameInterval;
2793    if (!msg->findInt32("bitrate", &bitrate)
2794            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
2795        return INVALID_OPERATION;
2796    }
2797
2798    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
2799
2800    float frameRate;
2801    if (!msg->findFloat("frame-rate", &frameRate)) {
2802        int32_t tmp;
2803        if (!msg->findInt32("frame-rate", &tmp)) {
2804            return INVALID_OPERATION;
2805        }
2806        frameRate = (float)tmp;
2807    }
2808
2809    OMX_VIDEO_PARAM_HEVCTYPE hevcType;
2810    InitOMXParams(&hevcType);
2811    hevcType.nPortIndex = kPortIndexOutput;
2812
2813    status_t err = OK;
2814    err = mOMX->getParameter(
2815            mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
2816    if (err != OK) {
2817        return err;
2818    }
2819
2820    int32_t profile;
2821    if (msg->findInt32("profile", &profile)) {
2822        int32_t level;
2823        if (!msg->findInt32("level", &level)) {
2824            return INVALID_OPERATION;
2825        }
2826
2827        err = verifySupportForProfileAndLevel(profile, level);
2828        if (err != OK) {
2829            return err;
2830        }
2831
2832        hevcType.eProfile = static_cast<OMX_VIDEO_HEVCPROFILETYPE>(profile);
2833        hevcType.eLevel = static_cast<OMX_VIDEO_HEVCLEVELTYPE>(level);
2834    }
2835
2836    // TODO: Need OMX structure definition for setting iFrameInterval
2837
2838    err = mOMX->setParameter(
2839            mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
2840    if (err != OK) {
2841        return err;
2842    }
2843
2844    return configureBitrate(bitrate, bitrateMode);
2845}
2846
2847status_t ACodec::setupVPXEncoderParameters(const sp<AMessage> &msg) {
2848    int32_t bitrate;
2849    int32_t iFrameInterval = 0;
2850    size_t tsLayers = 0;
2851    OMX_VIDEO_ANDROID_VPXTEMPORALLAYERPATTERNTYPE pattern =
2852        OMX_VIDEO_VPXTemporalLayerPatternNone;
2853    static const uint32_t kVp8LayerRateAlloction
2854        [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS]
2855        [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS] = {
2856        {100, 100, 100},  // 1 layer
2857        { 60, 100, 100},  // 2 layers {60%, 40%}
2858        { 40,  60, 100},  // 3 layers {40%, 20%, 40%}
2859    };
2860    if (!msg->findInt32("bitrate", &bitrate)) {
2861        return INVALID_OPERATION;
2862    }
2863    msg->findInt32("i-frame-interval", &iFrameInterval);
2864
2865    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
2866
2867    float frameRate;
2868    if (!msg->findFloat("frame-rate", &frameRate)) {
2869        int32_t tmp;
2870        if (!msg->findInt32("frame-rate", &tmp)) {
2871            return INVALID_OPERATION;
2872        }
2873        frameRate = (float)tmp;
2874    }
2875
2876    AString tsSchema;
2877    if (msg->findString("ts-schema", &tsSchema)) {
2878        if (tsSchema == "webrtc.vp8.1-layer") {
2879            pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
2880            tsLayers = 1;
2881        } else if (tsSchema == "webrtc.vp8.2-layer") {
2882            pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
2883            tsLayers = 2;
2884        } else if (tsSchema == "webrtc.vp8.3-layer") {
2885            pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
2886            tsLayers = 3;
2887        } else {
2888            ALOGW("Unsupported ts-schema [%s]", tsSchema.c_str());
2889        }
2890    }
2891
2892    OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type;
2893    InitOMXParams(&vp8type);
2894    vp8type.nPortIndex = kPortIndexOutput;
2895    status_t err = mOMX->getParameter(
2896            mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
2897            &vp8type, sizeof(vp8type));
2898
2899    if (err == OK) {
2900        if (iFrameInterval > 0) {
2901            vp8type.nKeyFrameInterval = setPFramesSpacing(iFrameInterval, frameRate);
2902        }
2903        vp8type.eTemporalPattern = pattern;
2904        vp8type.nTemporalLayerCount = tsLayers;
2905        if (tsLayers > 0) {
2906            for (size_t i = 0; i < OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS; i++) {
2907                vp8type.nTemporalLayerBitrateRatio[i] =
2908                    kVp8LayerRateAlloction[tsLayers - 1][i];
2909            }
2910        }
2911        if (bitrateMode == OMX_Video_ControlRateConstant) {
2912            vp8type.nMinQuantizer = 2;
2913            vp8type.nMaxQuantizer = 63;
2914        }
2915
2916        err = mOMX->setParameter(
2917                mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
2918                &vp8type, sizeof(vp8type));
2919        if (err != OK) {
2920            ALOGW("Extended VP8 parameters set failed: %d", err);
2921        }
2922    }
2923
2924    return configureBitrate(bitrate, bitrateMode);
2925}
2926
2927status_t ACodec::verifySupportForProfileAndLevel(
2928        int32_t profile, int32_t level) {
2929    OMX_VIDEO_PARAM_PROFILELEVELTYPE params;
2930    InitOMXParams(&params);
2931    params.nPortIndex = kPortIndexOutput;
2932
2933    for (params.nProfileIndex = 0;; ++params.nProfileIndex) {
2934        status_t err = mOMX->getParameter(
2935                mNode,
2936                OMX_IndexParamVideoProfileLevelQuerySupported,
2937                &params,
2938                sizeof(params));
2939
2940        if (err != OK) {
2941            return err;
2942        }
2943
2944        int32_t supportedProfile = static_cast<int32_t>(params.eProfile);
2945        int32_t supportedLevel = static_cast<int32_t>(params.eLevel);
2946
2947        if (profile == supportedProfile && level <= supportedLevel) {
2948            return OK;
2949        }
2950    }
2951}
2952
2953status_t ACodec::configureBitrate(
2954        int32_t bitrate, OMX_VIDEO_CONTROLRATETYPE bitrateMode) {
2955    OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
2956    InitOMXParams(&bitrateType);
2957    bitrateType.nPortIndex = kPortIndexOutput;
2958
2959    status_t err = mOMX->getParameter(
2960            mNode, OMX_IndexParamVideoBitrate,
2961            &bitrateType, sizeof(bitrateType));
2962
2963    if (err != OK) {
2964        return err;
2965    }
2966
2967    bitrateType.eControlRate = bitrateMode;
2968    bitrateType.nTargetBitrate = bitrate;
2969
2970    return mOMX->setParameter(
2971            mNode, OMX_IndexParamVideoBitrate,
2972            &bitrateType, sizeof(bitrateType));
2973}
2974
2975status_t ACodec::setupErrorCorrectionParameters() {
2976    OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
2977    InitOMXParams(&errorCorrectionType);
2978    errorCorrectionType.nPortIndex = kPortIndexOutput;
2979
2980    status_t err = mOMX->getParameter(
2981            mNode, OMX_IndexParamVideoErrorCorrection,
2982            &errorCorrectionType, sizeof(errorCorrectionType));
2983
2984    if (err != OK) {
2985        return OK;  // Optional feature. Ignore this failure
2986    }
2987
2988    errorCorrectionType.bEnableHEC = OMX_FALSE;
2989    errorCorrectionType.bEnableResync = OMX_TRUE;
2990    errorCorrectionType.nResynchMarkerSpacing = 256;
2991    errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
2992    errorCorrectionType.bEnableRVLC = OMX_FALSE;
2993
2994    return mOMX->setParameter(
2995            mNode, OMX_IndexParamVideoErrorCorrection,
2996            &errorCorrectionType, sizeof(errorCorrectionType));
2997}
2998
2999status_t ACodec::setVideoFormatOnPort(
3000        OMX_U32 portIndex,
3001        int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat,
3002        float frameRate) {
3003    OMX_PARAM_PORTDEFINITIONTYPE def;
3004    InitOMXParams(&def);
3005    def.nPortIndex = portIndex;
3006
3007    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
3008
3009    status_t err = mOMX->getParameter(
3010            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
3011
3012    CHECK_EQ(err, (status_t)OK);
3013
3014    if (portIndex == kPortIndexInput) {
3015        // XXX Need a (much) better heuristic to compute input buffer sizes.
3016        const size_t X = 64 * 1024;
3017        if (def.nBufferSize < X) {
3018            def.nBufferSize = X;
3019        }
3020    }
3021
3022    CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
3023
3024    video_def->nFrameWidth = width;
3025    video_def->nFrameHeight = height;
3026
3027    if (portIndex == kPortIndexInput) {
3028        video_def->eCompressionFormat = compressionFormat;
3029        video_def->eColorFormat = OMX_COLOR_FormatUnused;
3030        if (frameRate >= 0) {
3031            video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f);
3032        }
3033    }
3034
3035    err = mOMX->setParameter(
3036            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
3037
3038    return err;
3039}
3040
3041status_t ACodec::initNativeWindow() {
3042    if (mNativeWindow != NULL) {
3043        return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE);
3044    }
3045
3046    mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE);
3047    return OK;
3048}
3049
3050size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const {
3051    size_t n = 0;
3052
3053    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
3054        const BufferInfo &info = mBuffers[portIndex].itemAt(i);
3055
3056        if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) {
3057            ++n;
3058        }
3059    }
3060
3061    return n;
3062}
3063
3064size_t ACodec::countBuffersOwnedByNativeWindow() const {
3065    size_t n = 0;
3066
3067    for (size_t i = 0; i < mBuffers[kPortIndexOutput].size(); ++i) {
3068        const BufferInfo &info = mBuffers[kPortIndexOutput].itemAt(i);
3069
3070        if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
3071            ++n;
3072        }
3073    }
3074
3075    return n;
3076}
3077
3078void ACodec::waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs() {
3079    if (mNativeWindow == NULL) {
3080        return;
3081    }
3082
3083    while (countBuffersOwnedByNativeWindow() > mNumUndequeuedBuffers
3084            && dequeueBufferFromNativeWindow() != NULL) {
3085        // these buffers will be submitted as regular buffers; account for this
3086        if (mStoreMetaDataInOutputBuffers && mMetaDataBuffersToSubmit > 0) {
3087            --mMetaDataBuffersToSubmit;
3088        }
3089    }
3090}
3091
3092bool ACodec::allYourBuffersAreBelongToUs(
3093        OMX_U32 portIndex) {
3094    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
3095        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
3096
3097        if (info->mStatus != BufferInfo::OWNED_BY_US
3098                && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
3099            ALOGV("[%s] Buffer %u on port %u still has status %d",
3100                    mComponentName.c_str(),
3101                    info->mBufferID, portIndex, info->mStatus);
3102            return false;
3103        }
3104    }
3105
3106    return true;
3107}
3108
3109bool ACodec::allYourBuffersAreBelongToUs() {
3110    return allYourBuffersAreBelongToUs(kPortIndexInput)
3111        && allYourBuffersAreBelongToUs(kPortIndexOutput);
3112}
3113
3114void ACodec::deferMessage(const sp<AMessage> &msg) {
3115    bool wasEmptyBefore = mDeferredQueue.empty();
3116    mDeferredQueue.push_back(msg);
3117}
3118
3119void ACodec::processDeferredMessages() {
3120    List<sp<AMessage> > queue = mDeferredQueue;
3121    mDeferredQueue.clear();
3122
3123    List<sp<AMessage> >::iterator it = queue.begin();
3124    while (it != queue.end()) {
3125        onMessageReceived(*it++);
3126    }
3127}
3128
3129// static
3130bool ACodec::describeDefaultColorFormat(DescribeColorFormatParams &params) {
3131    MediaImage &image = params.sMediaImage;
3132    memset(&image, 0, sizeof(image));
3133
3134    image.mType = MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
3135    image.mNumPlanes = 0;
3136
3137    const OMX_COLOR_FORMATTYPE fmt = params.eColorFormat;
3138    image.mWidth = params.nFrameWidth;
3139    image.mHeight = params.nFrameHeight;
3140
3141    // only supporting YUV420
3142    if (fmt != OMX_COLOR_FormatYUV420Planar &&
3143        fmt != OMX_COLOR_FormatYUV420PackedPlanar &&
3144        fmt != OMX_COLOR_FormatYUV420SemiPlanar &&
3145        fmt != OMX_COLOR_FormatYUV420PackedSemiPlanar) {
3146        ALOGW("do not know color format 0x%x = %d", fmt, fmt);
3147        return false;
3148    }
3149
3150    // TEMPORARY FIX for some vendors that advertise sliceHeight as 0
3151    if (params.nStride != 0 && params.nSliceHeight == 0) {
3152        ALOGW("using sliceHeight=%u instead of what codec advertised (=0)",
3153                params.nFrameHeight);
3154        params.nSliceHeight = params.nFrameHeight;
3155    }
3156
3157    // we need stride and slice-height to be non-zero
3158    if (params.nStride == 0 || params.nSliceHeight == 0) {
3159        ALOGW("cannot describe color format 0x%x = %d with stride=%u and sliceHeight=%u",
3160                fmt, fmt, params.nStride, params.nSliceHeight);
3161        return false;
3162    }
3163
3164    // set-up YUV format
3165    image.mType = MediaImage::MEDIA_IMAGE_TYPE_YUV;
3166    image.mNumPlanes = 3;
3167    image.mBitDepth = 8;
3168    image.mPlane[image.Y].mOffset = 0;
3169    image.mPlane[image.Y].mColInc = 1;
3170    image.mPlane[image.Y].mRowInc = params.nStride;
3171    image.mPlane[image.Y].mHorizSubsampling = 1;
3172    image.mPlane[image.Y].mVertSubsampling = 1;
3173
3174    switch (fmt) {
3175        case OMX_COLOR_FormatYUV420Planar: // used for YV12
3176        case OMX_COLOR_FormatYUV420PackedPlanar:
3177            image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight;
3178            image.mPlane[image.U].mColInc = 1;
3179            image.mPlane[image.U].mRowInc = params.nStride / 2;
3180            image.mPlane[image.U].mHorizSubsampling = 2;
3181            image.mPlane[image.U].mVertSubsampling = 2;
3182
3183            image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset
3184                    + (params.nStride * params.nSliceHeight / 4);
3185            image.mPlane[image.V].mColInc = 1;
3186            image.mPlane[image.V].mRowInc = params.nStride / 2;
3187            image.mPlane[image.V].mHorizSubsampling = 2;
3188            image.mPlane[image.V].mVertSubsampling = 2;
3189            break;
3190
3191        case OMX_COLOR_FormatYUV420SemiPlanar:
3192            // FIXME: NV21 for sw-encoder, NV12 for decoder and hw-encoder
3193        case OMX_COLOR_FormatYUV420PackedSemiPlanar:
3194            // NV12
3195            image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight;
3196            image.mPlane[image.U].mColInc = 2;
3197            image.mPlane[image.U].mRowInc = params.nStride;
3198            image.mPlane[image.U].mHorizSubsampling = 2;
3199            image.mPlane[image.U].mVertSubsampling = 2;
3200
3201            image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset + 1;
3202            image.mPlane[image.V].mColInc = 2;
3203            image.mPlane[image.V].mRowInc = params.nStride;
3204            image.mPlane[image.V].mHorizSubsampling = 2;
3205            image.mPlane[image.V].mVertSubsampling = 2;
3206            break;
3207
3208        default:
3209            TRESPASS();
3210    }
3211    return true;
3212}
3213
3214// static
3215bool ACodec::describeColorFormat(
3216        const sp<IOMX> &omx, IOMX::node_id node,
3217        DescribeColorFormatParams &describeParams)
3218{
3219    OMX_INDEXTYPE describeColorFormatIndex;
3220    if (omx->getExtensionIndex(
3221            node, "OMX.google.android.index.describeColorFormat",
3222            &describeColorFormatIndex) != OK ||
3223        omx->getParameter(
3224            node, describeColorFormatIndex,
3225            &describeParams, sizeof(describeParams)) != OK) {
3226        return describeDefaultColorFormat(describeParams);
3227    }
3228    return describeParams.sMediaImage.mType !=
3229            MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
3230}
3231
3232// static
3233bool ACodec::isFlexibleColorFormat(
3234         const sp<IOMX> &omx, IOMX::node_id node,
3235         uint32_t colorFormat, OMX_U32 *flexibleEquivalent) {
3236    DescribeColorFormatParams describeParams;
3237    InitOMXParams(&describeParams);
3238    describeParams.eColorFormat = (OMX_COLOR_FORMATTYPE)colorFormat;
3239    // reasonable dummy values
3240    describeParams.nFrameWidth = 128;
3241    describeParams.nFrameHeight = 128;
3242    describeParams.nStride = 128;
3243    describeParams.nSliceHeight = 128;
3244
3245    CHECK(flexibleEquivalent != NULL);
3246
3247    if (!describeColorFormat(omx, node, describeParams)) {
3248        return false;
3249    }
3250
3251    const MediaImage &img = describeParams.sMediaImage;
3252    if (img.mType == MediaImage::MEDIA_IMAGE_TYPE_YUV) {
3253        if (img.mNumPlanes != 3 ||
3254            img.mPlane[img.Y].mHorizSubsampling != 1 ||
3255            img.mPlane[img.Y].mVertSubsampling != 1) {
3256            return false;
3257        }
3258
3259        // YUV 420
3260        if (img.mPlane[img.U].mHorizSubsampling == 2
3261                && img.mPlane[img.U].mVertSubsampling == 2
3262                && img.mPlane[img.V].mHorizSubsampling == 2
3263                && img.mPlane[img.V].mVertSubsampling == 2) {
3264            // possible flexible YUV420 format
3265            if (img.mBitDepth <= 8) {
3266               *flexibleEquivalent = OMX_COLOR_FormatYUV420Flexible;
3267               return true;
3268            }
3269        }
3270    }
3271    return false;
3272}
3273
3274status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> &notify) {
3275    // TODO: catch errors an return them instead of using CHECK
3276    OMX_PARAM_PORTDEFINITIONTYPE def;
3277    InitOMXParams(&def);
3278    def.nPortIndex = portIndex;
3279
3280    CHECK_EQ(mOMX->getParameter(
3281                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)),
3282             (status_t)OK);
3283
3284    CHECK_EQ((int)def.eDir,
3285            (int)(portIndex == kPortIndexOutput ? OMX_DirOutput : OMX_DirInput));
3286
3287    switch (def.eDomain) {
3288        case OMX_PortDomainVideo:
3289        {
3290            OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
3291            switch ((int)videoDef->eCompressionFormat) {
3292                case OMX_VIDEO_CodingUnused:
3293                {
3294                    CHECK(mIsEncoder ^ (portIndex == kPortIndexOutput));
3295                    notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW);
3296
3297                    notify->setInt32("stride", videoDef->nStride);
3298                    notify->setInt32("slice-height", videoDef->nSliceHeight);
3299                    notify->setInt32("color-format", videoDef->eColorFormat);
3300
3301                    DescribeColorFormatParams describeParams;
3302                    InitOMXParams(&describeParams);
3303                    describeParams.eColorFormat = videoDef->eColorFormat;
3304                    describeParams.nFrameWidth = videoDef->nFrameWidth;
3305                    describeParams.nFrameHeight = videoDef->nFrameHeight;
3306                    describeParams.nStride = videoDef->nStride;
3307                    describeParams.nSliceHeight = videoDef->nSliceHeight;
3308
3309                    if (describeColorFormat(mOMX, mNode, describeParams)) {
3310                        notify->setBuffer(
3311                                "image-data",
3312                                ABuffer::CreateAsCopy(
3313                                        &describeParams.sMediaImage,
3314                                        sizeof(describeParams.sMediaImage)));
3315                    }
3316
3317                    if (portIndex != kPortIndexOutput) {
3318                        // TODO: also get input crop
3319                        break;
3320                    }
3321
3322                    OMX_CONFIG_RECTTYPE rect;
3323                    InitOMXParams(&rect);
3324                    rect.nPortIndex = portIndex;
3325
3326                    if (mOMX->getConfig(
3327                                mNode,
3328                                (portIndex == kPortIndexOutput ?
3329                                        OMX_IndexConfigCommonOutputCrop :
3330                                        OMX_IndexConfigCommonInputCrop),
3331                                &rect, sizeof(rect)) != OK) {
3332                        rect.nLeft = 0;
3333                        rect.nTop = 0;
3334                        rect.nWidth = videoDef->nFrameWidth;
3335                        rect.nHeight = videoDef->nFrameHeight;
3336                    }
3337
3338                    CHECK_GE(rect.nLeft, 0);
3339                    CHECK_GE(rect.nTop, 0);
3340                    CHECK_GE(rect.nWidth, 0u);
3341                    CHECK_GE(rect.nHeight, 0u);
3342                    CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth);
3343                    CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight);
3344
3345                    notify->setRect(
3346                            "crop",
3347                            rect.nLeft,
3348                            rect.nTop,
3349                            rect.nLeft + rect.nWidth - 1,
3350                            rect.nTop + rect.nHeight - 1);
3351
3352                    break;
3353                }
3354
3355                case OMX_VIDEO_CodingVP8:
3356                case OMX_VIDEO_CodingVP9:
3357                {
3358                    OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type;
3359                    InitOMXParams(&vp8type);
3360                    vp8type.nPortIndex = kPortIndexOutput;
3361                    status_t err = mOMX->getParameter(
3362                            mNode,
3363                            (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
3364                            &vp8type,
3365                            sizeof(vp8type));
3366
3367                    if (err == OK) {
3368                        AString tsSchema = "none";
3369                        if (vp8type.eTemporalPattern
3370                                == OMX_VIDEO_VPXTemporalLayerPatternWebRTC) {
3371                            switch (vp8type.nTemporalLayerCount) {
3372                                case 1:
3373                                {
3374                                    tsSchema = "webrtc.vp8.1-layer";
3375                                    break;
3376                                }
3377                                case 2:
3378                                {
3379                                    tsSchema = "webrtc.vp8.2-layer";
3380                                    break;
3381                                }
3382                                case 3:
3383                                {
3384                                    tsSchema = "webrtc.vp8.3-layer";
3385                                    break;
3386                                }
3387                                default:
3388                                {
3389                                    break;
3390                                }
3391                            }
3392                        }
3393                        notify->setString("ts-schema", tsSchema);
3394                    }
3395                    // Fall through to set up mime.
3396                }
3397
3398                default:
3399                {
3400                    CHECK(mIsEncoder ^ (portIndex == kPortIndexInput));
3401                    AString mime;
3402                    if (GetMimeTypeForVideoCoding(
3403                        videoDef->eCompressionFormat, &mime) != OK) {
3404                        notify->setString("mime", "application/octet-stream");
3405                    } else {
3406                        notify->setString("mime", mime.c_str());
3407                    }
3408                    break;
3409                }
3410            }
3411
3412            notify->setInt32("width", videoDef->nFrameWidth);
3413            notify->setInt32("height", videoDef->nFrameHeight);
3414            break;
3415        }
3416
3417        case OMX_PortDomainAudio:
3418        {
3419            OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
3420
3421            switch ((int)audioDef->eEncoding) {
3422                case OMX_AUDIO_CodingPCM:
3423                {
3424                    OMX_AUDIO_PARAM_PCMMODETYPE params;
3425                    InitOMXParams(&params);
3426                    params.nPortIndex = portIndex;
3427
3428                    CHECK_EQ(mOMX->getParameter(
3429                                mNode, OMX_IndexParamAudioPcm,
3430                                &params, sizeof(params)),
3431                             (status_t)OK);
3432
3433                    CHECK_GT(params.nChannels, 0);
3434                    CHECK(params.nChannels == 1 || params.bInterleaved);
3435                    CHECK_EQ(params.nBitPerSample, 16u);
3436
3437                    CHECK_EQ((int)params.eNumData,
3438                             (int)OMX_NumericalDataSigned);
3439
3440                    CHECK_EQ((int)params.ePCMMode,
3441                             (int)OMX_AUDIO_PCMModeLinear);
3442
3443                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
3444                    notify->setInt32("channel-count", params.nChannels);
3445                    notify->setInt32("sample-rate", params.nSamplingRate);
3446
3447                    if (mChannelMaskPresent) {
3448                        notify->setInt32("channel-mask", mChannelMask);
3449                    }
3450                    break;
3451                }
3452
3453                case OMX_AUDIO_CodingAAC:
3454                {
3455                    OMX_AUDIO_PARAM_AACPROFILETYPE params;
3456                    InitOMXParams(&params);
3457                    params.nPortIndex = portIndex;
3458
3459                    CHECK_EQ(mOMX->getParameter(
3460                                mNode, OMX_IndexParamAudioAac,
3461                                &params, sizeof(params)),
3462                             (status_t)OK);
3463
3464                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
3465                    notify->setInt32("channel-count", params.nChannels);
3466                    notify->setInt32("sample-rate", params.nSampleRate);
3467                    break;
3468                }
3469
3470                case OMX_AUDIO_CodingAMR:
3471                {
3472                    OMX_AUDIO_PARAM_AMRTYPE params;
3473                    InitOMXParams(&params);
3474                    params.nPortIndex = portIndex;
3475
3476                    CHECK_EQ(mOMX->getParameter(
3477                                mNode, OMX_IndexParamAudioAmr,
3478                                &params, sizeof(params)),
3479                             (status_t)OK);
3480
3481                    notify->setInt32("channel-count", 1);
3482                    if (params.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0) {
3483                        notify->setString(
3484                                "mime", MEDIA_MIMETYPE_AUDIO_AMR_WB);
3485
3486                        notify->setInt32("sample-rate", 16000);
3487                    } else {
3488                        notify->setString(
3489                                "mime", MEDIA_MIMETYPE_AUDIO_AMR_NB);
3490
3491                        notify->setInt32("sample-rate", 8000);
3492                    }
3493                    break;
3494                }
3495
3496                case OMX_AUDIO_CodingFLAC:
3497                {
3498                    OMX_AUDIO_PARAM_FLACTYPE params;
3499                    InitOMXParams(&params);
3500                    params.nPortIndex = portIndex;
3501
3502                    CHECK_EQ(mOMX->getParameter(
3503                                mNode, OMX_IndexParamAudioFlac,
3504                                &params, sizeof(params)),
3505                             (status_t)OK);
3506
3507                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_FLAC);
3508                    notify->setInt32("channel-count", params.nChannels);
3509                    notify->setInt32("sample-rate", params.nSampleRate);
3510                    break;
3511                }
3512
3513                case OMX_AUDIO_CodingMP3:
3514                {
3515                    OMX_AUDIO_PARAM_MP3TYPE params;
3516                    InitOMXParams(&params);
3517                    params.nPortIndex = portIndex;
3518
3519                    CHECK_EQ(mOMX->getParameter(
3520                                mNode, OMX_IndexParamAudioMp3,
3521                                &params, sizeof(params)),
3522                             (status_t)OK);
3523
3524                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MPEG);
3525                    notify->setInt32("channel-count", params.nChannels);
3526                    notify->setInt32("sample-rate", params.nSampleRate);
3527                    break;
3528                }
3529
3530                case OMX_AUDIO_CodingVORBIS:
3531                {
3532                    OMX_AUDIO_PARAM_VORBISTYPE params;
3533                    InitOMXParams(&params);
3534                    params.nPortIndex = portIndex;
3535
3536                    CHECK_EQ(mOMX->getParameter(
3537                                mNode, OMX_IndexParamAudioVorbis,
3538                                &params, sizeof(params)),
3539                             (status_t)OK);
3540
3541                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_VORBIS);
3542                    notify->setInt32("channel-count", params.nChannels);
3543                    notify->setInt32("sample-rate", params.nSampleRate);
3544                    break;
3545                }
3546
3547                case OMX_AUDIO_CodingAndroidAC3:
3548                {
3549                    OMX_AUDIO_PARAM_ANDROID_AC3TYPE params;
3550                    InitOMXParams(&params);
3551                    params.nPortIndex = portIndex;
3552
3553                    CHECK_EQ((status_t)OK, mOMX->getParameter(
3554                            mNode,
3555                            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
3556                            &params,
3557                            sizeof(params)));
3558
3559                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AC3);
3560                    notify->setInt32("channel-count", params.nChannels);
3561                    notify->setInt32("sample-rate", params.nSampleRate);
3562                    break;
3563                }
3564
3565                case OMX_AUDIO_CodingAndroidEAC3:
3566                {
3567                    OMX_AUDIO_PARAM_ANDROID_EAC3TYPE params;
3568                    InitOMXParams(&params);
3569                    params.nPortIndex = portIndex;
3570
3571                    CHECK_EQ((status_t)OK, mOMX->getParameter(
3572                            mNode,
3573                            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
3574                            &params,
3575                            sizeof(params)));
3576
3577                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_EAC3);
3578                    notify->setInt32("channel-count", params.nChannels);
3579                    notify->setInt32("sample-rate", params.nSampleRate);
3580                    break;
3581                }
3582
3583                case OMX_AUDIO_CodingAndroidOPUS:
3584                {
3585                    OMX_AUDIO_PARAM_ANDROID_OPUSTYPE params;
3586                    InitOMXParams(&params);
3587                    params.nPortIndex = portIndex;
3588
3589                    CHECK_EQ((status_t)OK, mOMX->getParameter(
3590                            mNode,
3591                            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus,
3592                            &params,
3593                            sizeof(params)));
3594
3595                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_OPUS);
3596                    notify->setInt32("channel-count", params.nChannels);
3597                    notify->setInt32("sample-rate", params.nSampleRate);
3598                    break;
3599                }
3600
3601                case OMX_AUDIO_CodingG711:
3602                {
3603                    OMX_AUDIO_PARAM_PCMMODETYPE params;
3604                    InitOMXParams(&params);
3605                    params.nPortIndex = portIndex;
3606
3607                    CHECK_EQ((status_t)OK, mOMX->getParameter(
3608                            mNode,
3609                            (OMX_INDEXTYPE)OMX_IndexParamAudioPcm,
3610                            &params,
3611                            sizeof(params)));
3612
3613                    const char *mime = NULL;
3614                    if (params.ePCMMode == OMX_AUDIO_PCMModeMULaw) {
3615                        mime = MEDIA_MIMETYPE_AUDIO_G711_MLAW;
3616                    } else if (params.ePCMMode == OMX_AUDIO_PCMModeALaw) {
3617                        mime = MEDIA_MIMETYPE_AUDIO_G711_ALAW;
3618                    } else { // params.ePCMMode == OMX_AUDIO_PCMModeLinear
3619                        mime = MEDIA_MIMETYPE_AUDIO_RAW;
3620                    }
3621                    notify->setString("mime", mime);
3622                    notify->setInt32("channel-count", params.nChannels);
3623                    notify->setInt32("sample-rate", params.nSamplingRate);
3624                    break;
3625                }
3626
3627                default:
3628                    ALOGE("UNKNOWN AUDIO CODING: %d\n", audioDef->eEncoding);
3629                    TRESPASS();
3630            }
3631            break;
3632        }
3633
3634        default:
3635            TRESPASS();
3636    }
3637
3638    return OK;
3639}
3640
3641void ACodec::sendFormatChange(const sp<AMessage> &reply) {
3642    sp<AMessage> notify = mBaseOutputFormat->dup();
3643    notify->setInt32("what", kWhatOutputFormatChanged);
3644
3645    CHECK_EQ(getPortFormat(kPortIndexOutput, notify), (status_t)OK);
3646
3647    AString mime;
3648    CHECK(notify->findString("mime", &mime));
3649
3650    int32_t left, top, right, bottom;
3651    if (mime == MEDIA_MIMETYPE_VIDEO_RAW &&
3652        mNativeWindow != NULL &&
3653        notify->findRect("crop", &left, &top, &right, &bottom)) {
3654        // notify renderer of the crop change
3655        // NOTE: native window uses extended right-bottom coordinate
3656        reply->setRect("crop", left, top, right + 1, bottom + 1);
3657    } else if (mime == MEDIA_MIMETYPE_AUDIO_RAW &&
3658               (mEncoderDelay || mEncoderPadding)) {
3659        int32_t channelCount;
3660        CHECK(notify->findInt32("channel-count", &channelCount));
3661        size_t frameSize = channelCount * sizeof(int16_t);
3662        if (mSkipCutBuffer != NULL) {
3663            size_t prevbufsize = mSkipCutBuffer->size();
3664            if (prevbufsize != 0) {
3665                ALOGW("Replacing SkipCutBuffer holding %d "
3666                      "bytes",
3667                      prevbufsize);
3668            }
3669        }
3670        mSkipCutBuffer = new SkipCutBuffer(
3671                mEncoderDelay * frameSize,
3672                mEncoderPadding * frameSize);
3673    }
3674
3675    notify->post();
3676
3677    mSentFormat = true;
3678}
3679
3680void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) {
3681    sp<AMessage> notify = mNotify->dup();
3682    notify->setInt32("what", CodecBase::kWhatError);
3683    ALOGE("signalError(omxError %#x, internalError %d)", error, internalError);
3684
3685    if (internalError == UNKNOWN_ERROR) { // find better error code
3686        const status_t omxStatus = statusFromOMXError(error);
3687        if (omxStatus != 0) {
3688            internalError = omxStatus;
3689        } else {
3690            ALOGW("Invalid OMX error %#x", error);
3691        }
3692    }
3693    notify->setInt32("err", internalError);
3694    notify->setInt32("actionCode", ACTION_CODE_FATAL); // could translate from OMX error.
3695    notify->post();
3696}
3697
3698status_t ACodec::pushBlankBuffersToNativeWindow() {
3699    status_t err = NO_ERROR;
3700    ANativeWindowBuffer* anb = NULL;
3701    int numBufs = 0;
3702    int minUndequeuedBufs = 0;
3703
3704    // We need to reconnect to the ANativeWindow as a CPU client to ensure that
3705    // no frames get dropped by SurfaceFlinger assuming that these are video
3706    // frames.
3707    err = native_window_api_disconnect(mNativeWindow.get(),
3708            NATIVE_WINDOW_API_MEDIA);
3709    if (err != NO_ERROR) {
3710        ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
3711                strerror(-err), -err);
3712        return err;
3713    }
3714
3715    err = native_window_api_connect(mNativeWindow.get(),
3716            NATIVE_WINDOW_API_CPU);
3717    if (err != NO_ERROR) {
3718        ALOGE("error pushing blank frames: api_connect failed: %s (%d)",
3719                strerror(-err), -err);
3720        return err;
3721    }
3722
3723    err = native_window_set_buffers_geometry(mNativeWindow.get(), 1, 1,
3724            HAL_PIXEL_FORMAT_RGBX_8888);
3725    if (err != NO_ERROR) {
3726        ALOGE("error pushing blank frames: set_buffers_geometry failed: %s (%d)",
3727                strerror(-err), -err);
3728        goto error;
3729    }
3730
3731    err = native_window_set_scaling_mode(mNativeWindow.get(),
3732                NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
3733    if (err != NO_ERROR) {
3734        ALOGE("error pushing blank_frames: set_scaling_mode failed: %s (%d)",
3735              strerror(-err), -err);
3736        goto error;
3737    }
3738
3739    err = native_window_set_usage(mNativeWindow.get(),
3740            GRALLOC_USAGE_SW_WRITE_OFTEN);
3741    if (err != NO_ERROR) {
3742        ALOGE("error pushing blank frames: set_usage failed: %s (%d)",
3743                strerror(-err), -err);
3744        goto error;
3745    }
3746
3747    err = mNativeWindow->query(mNativeWindow.get(),
3748            NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs);
3749    if (err != NO_ERROR) {
3750        ALOGE("error pushing blank frames: MIN_UNDEQUEUED_BUFFERS query "
3751                "failed: %s (%d)", strerror(-err), -err);
3752        goto error;
3753    }
3754
3755    numBufs = minUndequeuedBufs + 1;
3756    err = native_window_set_buffer_count(mNativeWindow.get(), numBufs);
3757    if (err != NO_ERROR) {
3758        ALOGE("error pushing blank frames: set_buffer_count failed: %s (%d)",
3759                strerror(-err), -err);
3760        goto error;
3761    }
3762
3763    // We  push numBufs + 1 buffers to ensure that we've drawn into the same
3764    // buffer twice.  This should guarantee that the buffer has been displayed
3765    // on the screen and then been replaced, so an previous video frames are
3766    // guaranteed NOT to be currently displayed.
3767    for (int i = 0; i < numBufs + 1; i++) {
3768        int fenceFd = -1;
3769        err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &anb);
3770        if (err != NO_ERROR) {
3771            ALOGE("error pushing blank frames: dequeueBuffer failed: %s (%d)",
3772                    strerror(-err), -err);
3773            goto error;
3774        }
3775
3776        sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
3777
3778        // Fill the buffer with the a 1x1 checkerboard pattern ;)
3779        uint32_t* img = NULL;
3780        err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
3781        if (err != NO_ERROR) {
3782            ALOGE("error pushing blank frames: lock failed: %s (%d)",
3783                    strerror(-err), -err);
3784            goto error;
3785        }
3786
3787        *img = 0;
3788
3789        err = buf->unlock();
3790        if (err != NO_ERROR) {
3791            ALOGE("error pushing blank frames: unlock failed: %s (%d)",
3792                    strerror(-err), -err);
3793            goto error;
3794        }
3795
3796        err = mNativeWindow->queueBuffer(mNativeWindow.get(),
3797                buf->getNativeBuffer(), -1);
3798        if (err != NO_ERROR) {
3799            ALOGE("error pushing blank frames: queueBuffer failed: %s (%d)",
3800                    strerror(-err), -err);
3801            goto error;
3802        }
3803
3804        anb = NULL;
3805    }
3806
3807error:
3808
3809    if (err != NO_ERROR) {
3810        // Clean up after an error.
3811        if (anb != NULL) {
3812            mNativeWindow->cancelBuffer(mNativeWindow.get(), anb, -1);
3813        }
3814
3815        native_window_api_disconnect(mNativeWindow.get(),
3816                NATIVE_WINDOW_API_CPU);
3817        native_window_api_connect(mNativeWindow.get(),
3818                NATIVE_WINDOW_API_MEDIA);
3819
3820        return err;
3821    } else {
3822        // Clean up after success.
3823        err = native_window_api_disconnect(mNativeWindow.get(),
3824                NATIVE_WINDOW_API_CPU);
3825        if (err != NO_ERROR) {
3826            ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
3827                    strerror(-err), -err);
3828            return err;
3829        }
3830
3831        err = native_window_api_connect(mNativeWindow.get(),
3832                NATIVE_WINDOW_API_MEDIA);
3833        if (err != NO_ERROR) {
3834            ALOGE("error pushing blank frames: api_connect failed: %s (%d)",
3835                    strerror(-err), -err);
3836            return err;
3837        }
3838
3839        return NO_ERROR;
3840    }
3841}
3842
3843////////////////////////////////////////////////////////////////////////////////
3844
3845ACodec::PortDescription::PortDescription() {
3846}
3847
3848status_t ACodec::requestIDRFrame() {
3849    if (!mIsEncoder) {
3850        return ERROR_UNSUPPORTED;
3851    }
3852
3853    OMX_CONFIG_INTRAREFRESHVOPTYPE params;
3854    InitOMXParams(&params);
3855
3856    params.nPortIndex = kPortIndexOutput;
3857    params.IntraRefreshVOP = OMX_TRUE;
3858
3859    return mOMX->setConfig(
3860            mNode,
3861            OMX_IndexConfigVideoIntraVOPRefresh,
3862            &params,
3863            sizeof(params));
3864}
3865
3866void ACodec::PortDescription::addBuffer(
3867        IOMX::buffer_id id, const sp<ABuffer> &buffer) {
3868    mBufferIDs.push_back(id);
3869    mBuffers.push_back(buffer);
3870}
3871
3872size_t ACodec::PortDescription::countBuffers() {
3873    return mBufferIDs.size();
3874}
3875
3876IOMX::buffer_id ACodec::PortDescription::bufferIDAt(size_t index) const {
3877    return mBufferIDs.itemAt(index);
3878}
3879
3880sp<ABuffer> ACodec::PortDescription::bufferAt(size_t index) const {
3881    return mBuffers.itemAt(index);
3882}
3883
3884////////////////////////////////////////////////////////////////////////////////
3885
3886ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
3887    : AState(parentState),
3888      mCodec(codec) {
3889}
3890
3891ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(
3892        OMX_U32 /* portIndex */) {
3893    return KEEP_BUFFERS;
3894}
3895
3896bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) {
3897    switch (msg->what()) {
3898        case kWhatInputBufferFilled:
3899        {
3900            onInputBufferFilled(msg);
3901            break;
3902        }
3903
3904        case kWhatOutputBufferDrained:
3905        {
3906            onOutputBufferDrained(msg);
3907            break;
3908        }
3909
3910        case ACodec::kWhatOMXMessage:
3911        {
3912            return onOMXMessage(msg);
3913        }
3914
3915        case ACodec::kWhatCreateInputSurface:
3916        case ACodec::kWhatSignalEndOfInputStream:
3917        {
3918            // This may result in an app illegal state exception.
3919            ALOGE("Message 0x%x was not handled", msg->what());
3920            mCodec->signalError(OMX_ErrorUndefined, INVALID_OPERATION);
3921            return true;
3922        }
3923
3924        case ACodec::kWhatOMXDied:
3925        {
3926            // This will result in kFlagSawMediaServerDie handling in MediaCodec.
3927            ALOGE("OMX/mediaserver died, signalling error!");
3928            mCodec->signalError(OMX_ErrorResourcesLost, DEAD_OBJECT);
3929            break;
3930        }
3931
3932        case ACodec::kWhatReleaseCodecInstance:
3933        {
3934            ALOGI("[%s] forcing the release of codec",
3935                    mCodec->mComponentName.c_str());
3936            status_t err = mCodec->mOMX->freeNode(mCodec->mNode);
3937            ALOGE_IF("[%s] failed to release codec instance: err=%d",
3938                       mCodec->mComponentName.c_str(), err);
3939            sp<AMessage> notify = mCodec->mNotify->dup();
3940            notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
3941            notify->post();
3942            break;
3943        }
3944
3945        default:
3946            return false;
3947    }
3948
3949    return true;
3950}
3951
3952bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) {
3953    int32_t type;
3954    CHECK(msg->findInt32("type", &type));
3955
3956    // there is a possibility that this is an outstanding message for a
3957    // codec that we have already destroyed
3958    if (mCodec->mNode == NULL) {
3959        ALOGI("ignoring message as already freed component: %s",
3960                msg->debugString().c_str());
3961        return true;
3962    }
3963
3964    IOMX::node_id nodeID;
3965    CHECK(msg->findInt32("node", (int32_t*)&nodeID));
3966    CHECK_EQ(nodeID, mCodec->mNode);
3967
3968    switch (type) {
3969        case omx_message::EVENT:
3970        {
3971            int32_t event, data1, data2;
3972            CHECK(msg->findInt32("event", &event));
3973            CHECK(msg->findInt32("data1", &data1));
3974            CHECK(msg->findInt32("data2", &data2));
3975
3976            if (event == OMX_EventCmdComplete
3977                    && data1 == OMX_CommandFlush
3978                    && data2 == (int32_t)OMX_ALL) {
3979                // Use of this notification is not consistent across
3980                // implementations. We'll drop this notification and rely
3981                // on flush-complete notifications on the individual port
3982                // indices instead.
3983
3984                return true;
3985            }
3986
3987            return onOMXEvent(
3988                    static_cast<OMX_EVENTTYPE>(event),
3989                    static_cast<OMX_U32>(data1),
3990                    static_cast<OMX_U32>(data2));
3991        }
3992
3993        case omx_message::EMPTY_BUFFER_DONE:
3994        {
3995            IOMX::buffer_id bufferID;
3996            CHECK(msg->findInt32("buffer", (int32_t*)&bufferID));
3997
3998            return onOMXEmptyBufferDone(bufferID);
3999        }
4000
4001        case omx_message::FILL_BUFFER_DONE:
4002        {
4003            IOMX::buffer_id bufferID;
4004            CHECK(msg->findInt32("buffer", (int32_t*)&bufferID));
4005
4006            int32_t rangeOffset, rangeLength, flags;
4007            int64_t timeUs;
4008
4009            CHECK(msg->findInt32("range_offset", &rangeOffset));
4010            CHECK(msg->findInt32("range_length", &rangeLength));
4011            CHECK(msg->findInt32("flags", &flags));
4012            CHECK(msg->findInt64("timestamp", &timeUs));
4013
4014            return onOMXFillBufferDone(
4015                    bufferID,
4016                    (size_t)rangeOffset, (size_t)rangeLength,
4017                    (OMX_U32)flags,
4018                    timeUs);
4019        }
4020
4021        default:
4022            TRESPASS();
4023            break;
4024    }
4025}
4026
4027bool ACodec::BaseState::onOMXEvent(
4028        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
4029    if (event != OMX_EventError) {
4030        ALOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)",
4031             mCodec->mComponentName.c_str(), event, data1, data2);
4032
4033        return false;
4034    }
4035
4036    ALOGE("[%s] ERROR(0x%08lx)", mCodec->mComponentName.c_str(), data1);
4037
4038    // verify OMX component sends back an error we expect.
4039    OMX_ERRORTYPE omxError = (OMX_ERRORTYPE)data1;
4040    if (!isOMXError(omxError)) {
4041        ALOGW("Invalid OMX error %#x", omxError);
4042        omxError = OMX_ErrorUndefined;
4043    }
4044    mCodec->signalError(omxError);
4045
4046    return true;
4047}
4048
4049bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) {
4050    ALOGV("[%s] onOMXEmptyBufferDone %p",
4051         mCodec->mComponentName.c_str(), bufferID);
4052
4053    BufferInfo *info =
4054        mCodec->findBufferByID(kPortIndexInput, bufferID);
4055
4056    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
4057    info->mStatus = BufferInfo::OWNED_BY_US;
4058
4059    // We're in "store-metadata-in-buffers" mode, the underlying
4060    // OMX component had access to data that's implicitly refcounted
4061    // by this "MediaBuffer" object. Now that the OMX component has
4062    // told us that it's done with the input buffer, we can decrement
4063    // the mediaBuffer's reference count.
4064    info->mData->setMediaBufferBase(NULL);
4065
4066    PortMode mode = getPortMode(kPortIndexInput);
4067
4068    switch (mode) {
4069        case KEEP_BUFFERS:
4070            break;
4071
4072        case RESUBMIT_BUFFERS:
4073            postFillThisBuffer(info);
4074            break;
4075
4076        default:
4077        {
4078            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
4079            TRESPASS();  // Not currently used
4080            break;
4081        }
4082    }
4083
4084    return true;
4085}
4086
4087void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) {
4088    if (mCodec->mPortEOS[kPortIndexInput]) {
4089        return;
4090    }
4091
4092    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
4093
4094    sp<AMessage> notify = mCodec->mNotify->dup();
4095    notify->setInt32("what", CodecBase::kWhatFillThisBuffer);
4096    notify->setInt32("buffer-id", info->mBufferID);
4097
4098    info->mData->meta()->clear();
4099    notify->setBuffer("buffer", info->mData);
4100
4101    sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id());
4102    reply->setInt32("buffer-id", info->mBufferID);
4103
4104    notify->setMessage("reply", reply);
4105
4106    notify->post();
4107
4108    info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
4109}
4110
4111void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
4112    IOMX::buffer_id bufferID;
4113    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
4114    sp<ABuffer> buffer;
4115    int32_t err = OK;
4116    bool eos = false;
4117    PortMode mode = getPortMode(kPortIndexInput);
4118
4119    if (!msg->findBuffer("buffer", &buffer)) {
4120        /* these are unfilled buffers returned by client */
4121        CHECK(msg->findInt32("err", &err));
4122
4123        if (err == OK) {
4124            /* buffers with no errors are returned on MediaCodec.flush */
4125            mode = KEEP_BUFFERS;
4126        } else {
4127            ALOGV("[%s] saw error %d instead of an input buffer",
4128                 mCodec->mComponentName.c_str(), err);
4129            eos = true;
4130        }
4131
4132        buffer.clear();
4133    }
4134
4135    int32_t tmp;
4136    if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) {
4137        eos = true;
4138        err = ERROR_END_OF_STREAM;
4139    }
4140
4141    BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
4142    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM);
4143
4144    info->mStatus = BufferInfo::OWNED_BY_US;
4145
4146    switch (mode) {
4147        case KEEP_BUFFERS:
4148        {
4149            if (eos) {
4150                if (!mCodec->mPortEOS[kPortIndexInput]) {
4151                    mCodec->mPortEOS[kPortIndexInput] = true;
4152                    mCodec->mInputEOSResult = err;
4153                }
4154            }
4155            break;
4156        }
4157
4158        case RESUBMIT_BUFFERS:
4159        {
4160            if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) {
4161                int64_t timeUs;
4162                CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
4163
4164                OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
4165
4166                int32_t isCSD;
4167                if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) {
4168                    flags |= OMX_BUFFERFLAG_CODECCONFIG;
4169                }
4170
4171                if (eos) {
4172                    flags |= OMX_BUFFERFLAG_EOS;
4173                }
4174
4175                if (buffer != info->mData) {
4176                    ALOGV("[%s] Needs to copy input data for buffer %p. (%p != %p)",
4177                         mCodec->mComponentName.c_str(),
4178                         bufferID,
4179                         buffer.get(), info->mData.get());
4180
4181                    CHECK_LE(buffer->size(), info->mData->capacity());
4182                    memcpy(info->mData->data(), buffer->data(), buffer->size());
4183                }
4184
4185                if (flags & OMX_BUFFERFLAG_CODECCONFIG) {
4186                    ALOGV("[%s] calling emptyBuffer %p w/ codec specific data",
4187                         mCodec->mComponentName.c_str(), bufferID);
4188                } else if (flags & OMX_BUFFERFLAG_EOS) {
4189                    ALOGV("[%s] calling emptyBuffer %p w/ EOS",
4190                         mCodec->mComponentName.c_str(), bufferID);
4191                } else {
4192#if TRACK_BUFFER_TIMING
4193                    ALOGI("[%s] calling emptyBuffer %p w/ time %lld us",
4194                         mCodec->mComponentName.c_str(), bufferID, timeUs);
4195#else
4196                    ALOGV("[%s] calling emptyBuffer %p w/ time %lld us",
4197                         mCodec->mComponentName.c_str(), bufferID, timeUs);
4198#endif
4199                }
4200
4201#if TRACK_BUFFER_TIMING
4202                ACodec::BufferStats stats;
4203                stats.mEmptyBufferTimeUs = ALooper::GetNowUs();
4204                stats.mFillBufferDoneTimeUs = -1ll;
4205                mCodec->mBufferStats.add(timeUs, stats);
4206#endif
4207
4208                if (mCodec->mStoreMetaDataInOutputBuffers) {
4209                    // try to submit an output buffer for each input buffer
4210                    PortMode outputMode = getPortMode(kPortIndexOutput);
4211
4212                    ALOGV("MetaDataBuffersToSubmit=%u portMode=%s",
4213                            mCodec->mMetaDataBuffersToSubmit,
4214                            (outputMode == FREE_BUFFERS ? "FREE" :
4215                             outputMode == KEEP_BUFFERS ? "KEEP" : "RESUBMIT"));
4216                    if (outputMode == RESUBMIT_BUFFERS) {
4217                        mCodec->submitOutputMetaDataBuffer();
4218                    }
4219                }
4220
4221                CHECK_EQ(mCodec->mOMX->emptyBuffer(
4222                            mCodec->mNode,
4223                            bufferID,
4224                            0,
4225                            buffer->size(),
4226                            flags,
4227                            timeUs),
4228                         (status_t)OK);
4229
4230                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4231
4232                if (!eos) {
4233                    getMoreInputDataIfPossible();
4234                } else {
4235                    ALOGV("[%s] Signalled EOS on the input port",
4236                         mCodec->mComponentName.c_str());
4237
4238                    mCodec->mPortEOS[kPortIndexInput] = true;
4239                    mCodec->mInputEOSResult = err;
4240                }
4241            } else if (!mCodec->mPortEOS[kPortIndexInput]) {
4242                if (err != ERROR_END_OF_STREAM) {
4243                    ALOGV("[%s] Signalling EOS on the input port "
4244                         "due to error %d",
4245                         mCodec->mComponentName.c_str(), err);
4246                } else {
4247                    ALOGV("[%s] Signalling EOS on the input port",
4248                         mCodec->mComponentName.c_str());
4249                }
4250
4251                ALOGV("[%s] calling emptyBuffer %p signalling EOS",
4252                     mCodec->mComponentName.c_str(), bufferID);
4253
4254                CHECK_EQ(mCodec->mOMX->emptyBuffer(
4255                            mCodec->mNode,
4256                            bufferID,
4257                            0,
4258                            0,
4259                            OMX_BUFFERFLAG_EOS,
4260                            0),
4261                         (status_t)OK);
4262
4263                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4264
4265                mCodec->mPortEOS[kPortIndexInput] = true;
4266                mCodec->mInputEOSResult = err;
4267            }
4268            break;
4269        }
4270
4271        default:
4272            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
4273            break;
4274    }
4275}
4276
4277void ACodec::BaseState::getMoreInputDataIfPossible() {
4278    if (mCodec->mPortEOS[kPortIndexInput]) {
4279        return;
4280    }
4281
4282    BufferInfo *eligible = NULL;
4283
4284    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
4285        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
4286
4287#if 0
4288        if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) {
4289            // There's already a "read" pending.
4290            return;
4291        }
4292#endif
4293
4294        if (info->mStatus == BufferInfo::OWNED_BY_US) {
4295            eligible = info;
4296        }
4297    }
4298
4299    if (eligible == NULL) {
4300        return;
4301    }
4302
4303    postFillThisBuffer(eligible);
4304}
4305
4306bool ACodec::BaseState::onOMXFillBufferDone(
4307        IOMX::buffer_id bufferID,
4308        size_t rangeOffset, size_t rangeLength,
4309        OMX_U32 flags,
4310        int64_t timeUs) {
4311    ALOGV("[%s] onOMXFillBufferDone %u time %" PRId64 " us, flags = 0x%08x",
4312         mCodec->mComponentName.c_str(), bufferID, timeUs, flags);
4313
4314    ssize_t index;
4315
4316#if TRACK_BUFFER_TIMING
4317    index = mCodec->mBufferStats.indexOfKey(timeUs);
4318    if (index >= 0) {
4319        ACodec::BufferStats *stats = &mCodec->mBufferStats.editValueAt(index);
4320        stats->mFillBufferDoneTimeUs = ALooper::GetNowUs();
4321
4322        ALOGI("frame PTS %lld: %lld",
4323                timeUs,
4324                stats->mFillBufferDoneTimeUs - stats->mEmptyBufferTimeUs);
4325
4326        mCodec->mBufferStats.removeItemsAt(index);
4327        stats = NULL;
4328    }
4329#endif
4330
4331    BufferInfo *info =
4332        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
4333
4334    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
4335
4336    info->mDequeuedAt = ++mCodec->mDequeueCounter;
4337    info->mStatus = BufferInfo::OWNED_BY_US;
4338
4339    PortMode mode = getPortMode(kPortIndexOutput);
4340
4341    switch (mode) {
4342        case KEEP_BUFFERS:
4343            break;
4344
4345        case RESUBMIT_BUFFERS:
4346        {
4347            if (rangeLength == 0 && (!(flags & OMX_BUFFERFLAG_EOS)
4348                    || mCodec->mPortEOS[kPortIndexOutput])) {
4349                ALOGV("[%s] calling fillBuffer %u",
4350                     mCodec->mComponentName.c_str(), info->mBufferID);
4351
4352                CHECK_EQ(mCodec->mOMX->fillBuffer(
4353                            mCodec->mNode, info->mBufferID),
4354                         (status_t)OK);
4355
4356                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4357                break;
4358            }
4359
4360            sp<AMessage> reply =
4361                new AMessage(kWhatOutputBufferDrained, mCodec->id());
4362
4363            if (!mCodec->mSentFormat && rangeLength > 0) {
4364                mCodec->sendFormatChange(reply);
4365            }
4366
4367            if (mCodec->mUseMetadataOnEncoderOutput) {
4368                native_handle_t* handle =
4369                        *(native_handle_t**)(info->mData->data() + 4);
4370                info->mData->meta()->setPointer("handle", handle);
4371                info->mData->meta()->setInt32("rangeOffset", rangeOffset);
4372                info->mData->meta()->setInt32("rangeLength", rangeLength);
4373            } else {
4374                info->mData->setRange(rangeOffset, rangeLength);
4375            }
4376#if 0
4377            if (mCodec->mNativeWindow == NULL) {
4378                if (IsIDR(info->mData)) {
4379                    ALOGI("IDR frame");
4380                }
4381            }
4382#endif
4383
4384            if (mCodec->mSkipCutBuffer != NULL) {
4385                mCodec->mSkipCutBuffer->submit(info->mData);
4386            }
4387            info->mData->meta()->setInt64("timeUs", timeUs);
4388
4389            sp<AMessage> notify = mCodec->mNotify->dup();
4390            notify->setInt32("what", CodecBase::kWhatDrainThisBuffer);
4391            notify->setInt32("buffer-id", info->mBufferID);
4392            notify->setBuffer("buffer", info->mData);
4393            notify->setInt32("flags", flags);
4394
4395            reply->setInt32("buffer-id", info->mBufferID);
4396
4397            notify->setMessage("reply", reply);
4398
4399            notify->post();
4400
4401            info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;
4402
4403            if (flags & OMX_BUFFERFLAG_EOS) {
4404                ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str());
4405
4406                sp<AMessage> notify = mCodec->mNotify->dup();
4407                notify->setInt32("what", CodecBase::kWhatEOS);
4408                notify->setInt32("err", mCodec->mInputEOSResult);
4409                notify->post();
4410
4411                mCodec->mPortEOS[kPortIndexOutput] = true;
4412            }
4413            break;
4414        }
4415
4416        default:
4417        {
4418            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
4419
4420            CHECK_EQ((status_t)OK,
4421                     mCodec->freeBuffer(kPortIndexOutput, index));
4422            break;
4423        }
4424    }
4425
4426    return true;
4427}
4428
4429void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
4430    IOMX::buffer_id bufferID;
4431    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
4432    ssize_t index;
4433    BufferInfo *info =
4434        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
4435    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
4436
4437    android_native_rect_t crop;
4438    if (msg->findRect("crop",
4439            &crop.left, &crop.top, &crop.right, &crop.bottom)) {
4440        CHECK_EQ(0, native_window_set_crop(
4441                mCodec->mNativeWindow.get(), &crop));
4442    }
4443
4444    int32_t render;
4445    if (mCodec->mNativeWindow != NULL
4446            && msg->findInt32("render", &render) && render != 0
4447            && info->mData != NULL && info->mData->size() != 0) {
4448        ATRACE_NAME("render");
4449        // The client wants this buffer to be rendered.
4450
4451        int64_t timestampNs = 0;
4452        if (!msg->findInt64("timestampNs", &timestampNs)) {
4453            // TODO: it seems like we should use the timestamp
4454            // in the (media)buffer as it potentially came from
4455            // an input surface, but we did not propagate it prior to
4456            // API 20.  Perhaps check for target SDK version.
4457#if 0
4458            if (info->mData->meta()->findInt64("timeUs", &timestampNs)) {
4459                ALOGV("using buffer PTS of %" PRId64, timestampNs);
4460                timestampNs *= 1000;
4461            }
4462#endif
4463        }
4464
4465        status_t err;
4466        err = native_window_set_buffers_timestamp(mCodec->mNativeWindow.get(), timestampNs);
4467        if (err != OK) {
4468            ALOGW("failed to set buffer timestamp: %d", err);
4469        }
4470
4471        if ((err = mCodec->mNativeWindow->queueBuffer(
4472                    mCodec->mNativeWindow.get(),
4473                    info->mGraphicBuffer.get(), -1)) == OK) {
4474            info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
4475        } else {
4476            mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
4477            info->mStatus = BufferInfo::OWNED_BY_US;
4478        }
4479    } else {
4480        if (mCodec->mNativeWindow != NULL &&
4481            (info->mData == NULL || info->mData->size() != 0)) {
4482            ATRACE_NAME("frame-drop");
4483        }
4484        info->mStatus = BufferInfo::OWNED_BY_US;
4485    }
4486
4487    PortMode mode = getPortMode(kPortIndexOutput);
4488
4489    switch (mode) {
4490        case KEEP_BUFFERS:
4491        {
4492            // XXX fishy, revisit!!! What about the FREE_BUFFERS case below?
4493
4494            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
4495                // We cannot resubmit the buffer we just rendered, dequeue
4496                // the spare instead.
4497
4498                info = mCodec->dequeueBufferFromNativeWindow();
4499            }
4500            break;
4501        }
4502
4503        case RESUBMIT_BUFFERS:
4504        {
4505            if (!mCodec->mPortEOS[kPortIndexOutput]) {
4506                if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
4507                    // We cannot resubmit the buffer we just rendered, dequeue
4508                    // the spare instead.
4509
4510                    info = mCodec->dequeueBufferFromNativeWindow();
4511                }
4512
4513                if (info != NULL) {
4514                    ALOGV("[%s] calling fillBuffer %u",
4515                         mCodec->mComponentName.c_str(), info->mBufferID);
4516
4517                    CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
4518                             (status_t)OK);
4519
4520                    info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4521                }
4522            }
4523            break;
4524        }
4525
4526        default:
4527        {
4528            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
4529
4530            CHECK_EQ((status_t)OK,
4531                     mCodec->freeBuffer(kPortIndexOutput, index));
4532            break;
4533        }
4534    }
4535}
4536
4537////////////////////////////////////////////////////////////////////////////////
4538
4539ACodec::UninitializedState::UninitializedState(ACodec *codec)
4540    : BaseState(codec) {
4541}
4542
4543void ACodec::UninitializedState::stateEntered() {
4544    ALOGV("Now uninitialized");
4545
4546    if (mDeathNotifier != NULL) {
4547        mCodec->mOMX->asBinder()->unlinkToDeath(mDeathNotifier);
4548        mDeathNotifier.clear();
4549    }
4550
4551    mCodec->mNativeWindow.clear();
4552    mCodec->mNode = NULL;
4553    mCodec->mOMX.clear();
4554    mCodec->mQuirks = 0;
4555    mCodec->mFlags = 0;
4556    mCodec->mUseMetadataOnEncoderOutput = 0;
4557    mCodec->mComponentName.clear();
4558}
4559
4560bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
4561    bool handled = false;
4562
4563    switch (msg->what()) {
4564        case ACodec::kWhatSetup:
4565        {
4566            onSetup(msg);
4567
4568            handled = true;
4569            break;
4570        }
4571
4572        case ACodec::kWhatAllocateComponent:
4573        {
4574            onAllocateComponent(msg);
4575            handled = true;
4576            break;
4577        }
4578
4579        case ACodec::kWhatShutdown:
4580        {
4581            int32_t keepComponentAllocated;
4582            CHECK(msg->findInt32(
4583                        "keepComponentAllocated", &keepComponentAllocated));
4584            ALOGW_IF(keepComponentAllocated,
4585                     "cannot keep component allocated on shutdown in Uninitialized state");
4586
4587            sp<AMessage> notify = mCodec->mNotify->dup();
4588            notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
4589            notify->post();
4590
4591            handled = true;
4592            break;
4593        }
4594
4595        case ACodec::kWhatFlush:
4596        {
4597            sp<AMessage> notify = mCodec->mNotify->dup();
4598            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
4599            notify->post();
4600
4601            handled = true;
4602            break;
4603        }
4604
4605        case ACodec::kWhatReleaseCodecInstance:
4606        {
4607            // nothing to do, as we have already signaled shutdown
4608            handled = true;
4609            break;
4610        }
4611
4612        default:
4613            return BaseState::onMessageReceived(msg);
4614    }
4615
4616    return handled;
4617}
4618
4619void ACodec::UninitializedState::onSetup(
4620        const sp<AMessage> &msg) {
4621    if (onAllocateComponent(msg)
4622            && mCodec->mLoadedState->onConfigureComponent(msg)) {
4623        mCodec->mLoadedState->onStart();
4624    }
4625}
4626
4627bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
4628    ALOGV("onAllocateComponent");
4629
4630    CHECK(mCodec->mNode == NULL);
4631
4632    OMXClient client;
4633    CHECK_EQ(client.connect(), (status_t)OK);
4634
4635    sp<IOMX> omx = client.interface();
4636
4637    sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec->id());
4638
4639    mDeathNotifier = new DeathNotifier(notify);
4640    if (omx->asBinder()->linkToDeath(mDeathNotifier) != OK) {
4641        // This was a local binder, if it dies so do we, we won't care
4642        // about any notifications in the afterlife.
4643        mDeathNotifier.clear();
4644    }
4645
4646    Vector<OMXCodec::CodecNameAndQuirks> matchingCodecs;
4647
4648    AString mime;
4649
4650    AString componentName;
4651    uint32_t quirks = 0;
4652    int32_t encoder = false;
4653    if (msg->findString("componentName", &componentName)) {
4654        ssize_t index = matchingCodecs.add();
4655        OMXCodec::CodecNameAndQuirks *entry = &matchingCodecs.editItemAt(index);
4656        entry->mName = String8(componentName.c_str());
4657
4658        if (!OMXCodec::findCodecQuirks(
4659                    componentName.c_str(), &entry->mQuirks)) {
4660            entry->mQuirks = 0;
4661        }
4662    } else {
4663        CHECK(msg->findString("mime", &mime));
4664
4665        if (!msg->findInt32("encoder", &encoder)) {
4666            encoder = false;
4667        }
4668
4669        OMXCodec::findMatchingCodecs(
4670                mime.c_str(),
4671                encoder, // createEncoder
4672                NULL,  // matchComponentName
4673                0,     // flags
4674                &matchingCodecs);
4675    }
4676
4677    sp<CodecObserver> observer = new CodecObserver;
4678    IOMX::node_id node = NULL;
4679
4680    for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
4681            ++matchIndex) {
4682        componentName = matchingCodecs.itemAt(matchIndex).mName.string();
4683        quirks = matchingCodecs.itemAt(matchIndex).mQuirks;
4684
4685        pid_t tid = androidGetTid();
4686        int prevPriority = androidGetThreadPriority(tid);
4687        androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
4688        status_t err = omx->allocateNode(componentName.c_str(), observer, &node);
4689        androidSetThreadPriority(tid, prevPriority);
4690
4691        if (err == OK) {
4692            break;
4693        } else {
4694            ALOGW("Allocating component '%s' failed, try next one.", componentName.c_str());
4695        }
4696
4697        node = NULL;
4698    }
4699
4700    if (node == NULL) {
4701        if (!mime.empty()) {
4702            ALOGE("Unable to instantiate a %scoder for type '%s'.",
4703                    encoder ? "en" : "de", mime.c_str());
4704        } else {
4705            ALOGE("Unable to instantiate codec '%s'.", componentName.c_str());
4706        }
4707
4708        mCodec->signalError(OMX_ErrorComponentNotFound);
4709        return false;
4710    }
4711
4712    notify = new AMessage(kWhatOMXMessage, mCodec->id());
4713    observer->setNotificationMessage(notify);
4714
4715    mCodec->mComponentName = componentName;
4716    mCodec->mFlags = 0;
4717
4718    if (componentName.endsWith(".secure")) {
4719        mCodec->mFlags |= kFlagIsSecure;
4720        mCodec->mFlags |= kFlagIsGrallocUsageProtected;
4721        mCodec->mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
4722    }
4723
4724    mCodec->mQuirks = quirks;
4725    mCodec->mOMX = omx;
4726    mCodec->mNode = node;
4727
4728    {
4729        sp<AMessage> notify = mCodec->mNotify->dup();
4730        notify->setInt32("what", CodecBase::kWhatComponentAllocated);
4731        notify->setString("componentName", mCodec->mComponentName.c_str());
4732        notify->post();
4733    }
4734
4735    mCodec->changeState(mCodec->mLoadedState);
4736
4737    return true;
4738}
4739
4740////////////////////////////////////////////////////////////////////////////////
4741
4742ACodec::LoadedState::LoadedState(ACodec *codec)
4743    : BaseState(codec) {
4744}
4745
4746void ACodec::LoadedState::stateEntered() {
4747    ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
4748
4749    mCodec->mPortEOS[kPortIndexInput] =
4750        mCodec->mPortEOS[kPortIndexOutput] = false;
4751
4752    mCodec->mInputEOSResult = OK;
4753
4754    mCodec->mDequeueCounter = 0;
4755    mCodec->mMetaDataBuffersToSubmit = 0;
4756    mCodec->mRepeatFrameDelayUs = -1ll;
4757    mCodec->mInputFormat.clear();
4758    mCodec->mOutputFormat.clear();
4759    mCodec->mBaseOutputFormat.clear();
4760
4761    if (mCodec->mShutdownInProgress) {
4762        bool keepComponentAllocated = mCodec->mKeepComponentAllocated;
4763
4764        mCodec->mShutdownInProgress = false;
4765        mCodec->mKeepComponentAllocated = false;
4766
4767        onShutdown(keepComponentAllocated);
4768    }
4769    mCodec->mExplicitShutdown = false;
4770
4771    mCodec->processDeferredMessages();
4772}
4773
4774void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) {
4775    if (!keepComponentAllocated) {
4776        CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
4777
4778        mCodec->changeState(mCodec->mUninitializedState);
4779    }
4780
4781    if (mCodec->mExplicitShutdown) {
4782        sp<AMessage> notify = mCodec->mNotify->dup();
4783        notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
4784        notify->post();
4785        mCodec->mExplicitShutdown = false;
4786    }
4787}
4788
4789bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) {
4790    bool handled = false;
4791
4792    switch (msg->what()) {
4793        case ACodec::kWhatConfigureComponent:
4794        {
4795            onConfigureComponent(msg);
4796            handled = true;
4797            break;
4798        }
4799
4800        case ACodec::kWhatCreateInputSurface:
4801        {
4802            onCreateInputSurface(msg);
4803            handled = true;
4804            break;
4805        }
4806
4807        case ACodec::kWhatStart:
4808        {
4809            onStart();
4810            handled = true;
4811            break;
4812        }
4813
4814        case ACodec::kWhatShutdown:
4815        {
4816            int32_t keepComponentAllocated;
4817            CHECK(msg->findInt32(
4818                        "keepComponentAllocated", &keepComponentAllocated));
4819
4820            mCodec->mExplicitShutdown = true;
4821            onShutdown(keepComponentAllocated);
4822
4823            handled = true;
4824            break;
4825        }
4826
4827        case ACodec::kWhatFlush:
4828        {
4829            sp<AMessage> notify = mCodec->mNotify->dup();
4830            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
4831            notify->post();
4832
4833            handled = true;
4834            break;
4835        }
4836
4837        default:
4838            return BaseState::onMessageReceived(msg);
4839    }
4840
4841    return handled;
4842}
4843
4844bool ACodec::LoadedState::onConfigureComponent(
4845        const sp<AMessage> &msg) {
4846    ALOGV("onConfigureComponent");
4847
4848    CHECK(mCodec->mNode != NULL);
4849
4850    AString mime;
4851    CHECK(msg->findString("mime", &mime));
4852
4853    status_t err = mCodec->configureCodec(mime.c_str(), msg);
4854
4855    if (err != OK) {
4856        ALOGE("[%s] configureCodec returning error %d",
4857              mCodec->mComponentName.c_str(), err);
4858
4859        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
4860        return false;
4861    }
4862
4863    sp<RefBase> obj;
4864    if (msg->findObject("native-window", &obj)
4865            && strncmp("OMX.google.", mCodec->mComponentName.c_str(), 11)) {
4866        sp<NativeWindowWrapper> nativeWindow(
4867                static_cast<NativeWindowWrapper *>(obj.get()));
4868        CHECK(nativeWindow != NULL);
4869        mCodec->mNativeWindow = nativeWindow->getNativeWindow();
4870
4871        native_window_set_scaling_mode(
4872                mCodec->mNativeWindow.get(),
4873                NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
4874    }
4875    CHECK_EQ((status_t)OK, mCodec->initNativeWindow());
4876
4877    {
4878        sp<AMessage> notify = mCodec->mNotify->dup();
4879        notify->setInt32("what", CodecBase::kWhatComponentConfigured);
4880        notify->setMessage("input-format", mCodec->mInputFormat);
4881        notify->setMessage("output-format", mCodec->mOutputFormat);
4882        notify->post();
4883    }
4884
4885    return true;
4886}
4887
4888void ACodec::LoadedState::onCreateInputSurface(
4889        const sp<AMessage> & /* msg */) {
4890    ALOGV("onCreateInputSurface");
4891
4892    sp<AMessage> notify = mCodec->mNotify->dup();
4893    notify->setInt32("what", CodecBase::kWhatInputSurfaceCreated);
4894
4895    sp<IGraphicBufferProducer> bufferProducer;
4896    status_t err;
4897
4898    err = mCodec->mOMX->createInputSurface(mCodec->mNode, kPortIndexInput,
4899            &bufferProducer);
4900
4901    if (err == OK && mCodec->mRepeatFrameDelayUs > 0ll) {
4902        err = mCodec->mOMX->setInternalOption(
4903                mCodec->mNode,
4904                kPortIndexInput,
4905                IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY,
4906                &mCodec->mRepeatFrameDelayUs,
4907                sizeof(mCodec->mRepeatFrameDelayUs));
4908
4909        if (err != OK) {
4910            ALOGE("[%s] Unable to configure option to repeat previous "
4911                  "frames (err %d)",
4912                  mCodec->mComponentName.c_str(),
4913                  err);
4914        }
4915    }
4916
4917    if (err == OK && mCodec->mMaxPtsGapUs > 0ll) {
4918        err = mCodec->mOMX->setInternalOption(
4919                mCodec->mNode,
4920                kPortIndexInput,
4921                IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP,
4922                &mCodec->mMaxPtsGapUs,
4923                sizeof(mCodec->mMaxPtsGapUs));
4924
4925        if (err != OK) {
4926            ALOGE("[%s] Unable to configure max timestamp gap (err %d)",
4927                    mCodec->mComponentName.c_str(),
4928                    err);
4929        }
4930    }
4931
4932    if (err == OK && mCodec->mTimePerCaptureUs > 0ll
4933            && mCodec->mTimePerFrameUs > 0ll) {
4934        int64_t timeLapse[2];
4935        timeLapse[0] = mCodec->mTimePerFrameUs;
4936        timeLapse[1] = mCodec->mTimePerCaptureUs;
4937        err = mCodec->mOMX->setInternalOption(
4938                mCodec->mNode,
4939                kPortIndexInput,
4940                IOMX::INTERNAL_OPTION_TIME_LAPSE,
4941                &timeLapse[0],
4942                sizeof(timeLapse));
4943
4944        if (err != OK) {
4945            ALOGE("[%s] Unable to configure time lapse (err %d)",
4946                    mCodec->mComponentName.c_str(),
4947                    err);
4948        }
4949    }
4950
4951    if (err == OK && mCodec->mCreateInputBuffersSuspended) {
4952        bool suspend = true;
4953        err = mCodec->mOMX->setInternalOption(
4954                mCodec->mNode,
4955                kPortIndexInput,
4956                IOMX::INTERNAL_OPTION_SUSPEND,
4957                &suspend,
4958                sizeof(suspend));
4959
4960        if (err != OK) {
4961            ALOGE("[%s] Unable to configure option to suspend (err %d)",
4962                  mCodec->mComponentName.c_str(),
4963                  err);
4964        }
4965    }
4966
4967    if (err == OK) {
4968        notify->setObject("input-surface",
4969                new BufferProducerWrapper(bufferProducer));
4970    } else {
4971        // Can't use mCodec->signalError() here -- MediaCodec won't forward
4972        // the error through because it's in the "configured" state.  We
4973        // send a kWhatInputSurfaceCreated with an error value instead.
4974        ALOGE("[%s] onCreateInputSurface returning error %d",
4975                mCodec->mComponentName.c_str(), err);
4976        notify->setInt32("err", err);
4977    }
4978    notify->post();
4979}
4980
4981void ACodec::LoadedState::onStart() {
4982    ALOGV("onStart");
4983
4984    CHECK_EQ(mCodec->mOMX->sendCommand(
4985                mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
4986             (status_t)OK);
4987
4988    mCodec->changeState(mCodec->mLoadedToIdleState);
4989}
4990
4991////////////////////////////////////////////////////////////////////////////////
4992
4993ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec)
4994    : BaseState(codec) {
4995}
4996
4997void ACodec::LoadedToIdleState::stateEntered() {
4998    ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
4999
5000    status_t err;
5001    if ((err = allocateBuffers()) != OK) {
5002        ALOGE("Failed to allocate buffers after transitioning to IDLE state "
5003             "(error 0x%08x)",
5004             err);
5005
5006        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5007
5008        mCodec->changeState(mCodec->mLoadedState);
5009    }
5010}
5011
5012status_t ACodec::LoadedToIdleState::allocateBuffers() {
5013    status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput);
5014
5015    if (err != OK) {
5016        return err;
5017    }
5018
5019    return mCodec->allocateBuffersOnPort(kPortIndexOutput);
5020}
5021
5022bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
5023    switch (msg->what()) {
5024        case kWhatSetParameters:
5025        case kWhatShutdown:
5026        {
5027            mCodec->deferMessage(msg);
5028            return true;
5029        }
5030
5031        case kWhatSignalEndOfInputStream:
5032        {
5033            mCodec->onSignalEndOfInputStream();
5034            return true;
5035        }
5036
5037        case kWhatResume:
5038        {
5039            // We'll be active soon enough.
5040            return true;
5041        }
5042
5043        case kWhatFlush:
5044        {
5045            // We haven't even started yet, so we're flushed alright...
5046            sp<AMessage> notify = mCodec->mNotify->dup();
5047            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
5048            notify->post();
5049            return true;
5050        }
5051
5052        default:
5053            return BaseState::onMessageReceived(msg);
5054    }
5055}
5056
5057bool ACodec::LoadedToIdleState::onOMXEvent(
5058        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5059    switch (event) {
5060        case OMX_EventCmdComplete:
5061        {
5062            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
5063            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
5064
5065            CHECK_EQ(mCodec->mOMX->sendCommand(
5066                        mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting),
5067                     (status_t)OK);
5068
5069            mCodec->changeState(mCodec->mIdleToExecutingState);
5070
5071            return true;
5072        }
5073
5074        default:
5075            return BaseState::onOMXEvent(event, data1, data2);
5076    }
5077}
5078
5079////////////////////////////////////////////////////////////////////////////////
5080
5081ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec)
5082    : BaseState(codec) {
5083}
5084
5085void ACodec::IdleToExecutingState::stateEntered() {
5086    ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
5087}
5088
5089bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
5090    switch (msg->what()) {
5091        case kWhatSetParameters:
5092        case kWhatShutdown:
5093        {
5094            mCodec->deferMessage(msg);
5095            return true;
5096        }
5097
5098        case kWhatResume:
5099        {
5100            // We'll be active soon enough.
5101            return true;
5102        }
5103
5104        case kWhatFlush:
5105        {
5106            // We haven't even started yet, so we're flushed alright...
5107            sp<AMessage> notify = mCodec->mNotify->dup();
5108            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
5109            notify->post();
5110
5111            return true;
5112        }
5113
5114        case kWhatSignalEndOfInputStream:
5115        {
5116            mCodec->onSignalEndOfInputStream();
5117            return true;
5118        }
5119
5120        default:
5121            return BaseState::onMessageReceived(msg);
5122    }
5123}
5124
5125bool ACodec::IdleToExecutingState::onOMXEvent(
5126        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5127    switch (event) {
5128        case OMX_EventCmdComplete:
5129        {
5130            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
5131            CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting);
5132
5133            mCodec->mExecutingState->resume();
5134            mCodec->changeState(mCodec->mExecutingState);
5135
5136            return true;
5137        }
5138
5139        default:
5140            return BaseState::onOMXEvent(event, data1, data2);
5141    }
5142}
5143
5144////////////////////////////////////////////////////////////////////////////////
5145
5146ACodec::ExecutingState::ExecutingState(ACodec *codec)
5147    : BaseState(codec),
5148      mActive(false) {
5149}
5150
5151ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode(
5152        OMX_U32 /* portIndex */) {
5153    return RESUBMIT_BUFFERS;
5154}
5155
5156void ACodec::ExecutingState::submitOutputMetaBuffers() {
5157    // submit as many buffers as there are input buffers with the codec
5158    // in case we are in port reconfiguring
5159    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
5160        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
5161
5162        if (info->mStatus == BufferInfo::OWNED_BY_COMPONENT) {
5163            if (mCodec->submitOutputMetaDataBuffer() != OK)
5164                break;
5165        }
5166    }
5167
5168    // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
5169    mCodec->signalSubmitOutputMetaDataBufferIfEOS_workaround();
5170}
5171
5172void ACodec::ExecutingState::submitRegularOutputBuffers() {
5173    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
5174        BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
5175
5176        if (mCodec->mNativeWindow != NULL) {
5177            CHECK(info->mStatus == BufferInfo::OWNED_BY_US
5178                    || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
5179
5180            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
5181                continue;
5182            }
5183        } else {
5184            CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
5185        }
5186
5187        ALOGV("[%s] calling fillBuffer %p",
5188             mCodec->mComponentName.c_str(), info->mBufferID);
5189
5190        CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
5191                 (status_t)OK);
5192
5193        info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
5194    }
5195}
5196
5197void ACodec::ExecutingState::submitOutputBuffers() {
5198    submitRegularOutputBuffers();
5199    if (mCodec->mStoreMetaDataInOutputBuffers) {
5200        submitOutputMetaBuffers();
5201    }
5202}
5203
5204void ACodec::ExecutingState::resume() {
5205    if (mActive) {
5206        ALOGV("[%s] We're already active, no need to resume.",
5207             mCodec->mComponentName.c_str());
5208
5209        return;
5210    }
5211
5212    submitOutputBuffers();
5213
5214    // Post all available input buffers
5215    CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u);
5216    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); i++) {
5217        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
5218        if (info->mStatus == BufferInfo::OWNED_BY_US) {
5219            postFillThisBuffer(info);
5220        }
5221    }
5222
5223    mActive = true;
5224}
5225
5226void ACodec::ExecutingState::stateEntered() {
5227    ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
5228
5229    mCodec->processDeferredMessages();
5230}
5231
5232bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) {
5233    bool handled = false;
5234
5235    switch (msg->what()) {
5236        case kWhatShutdown:
5237        {
5238            int32_t keepComponentAllocated;
5239            CHECK(msg->findInt32(
5240                        "keepComponentAllocated", &keepComponentAllocated));
5241
5242            mCodec->mShutdownInProgress = true;
5243            mCodec->mExplicitShutdown = true;
5244            mCodec->mKeepComponentAllocated = keepComponentAllocated;
5245
5246            mActive = false;
5247
5248            CHECK_EQ(mCodec->mOMX->sendCommand(
5249                        mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
5250                     (status_t)OK);
5251
5252            mCodec->changeState(mCodec->mExecutingToIdleState);
5253
5254            handled = true;
5255            break;
5256        }
5257
5258        case kWhatFlush:
5259        {
5260            ALOGV("[%s] ExecutingState flushing now "
5261                 "(codec owns %d/%d input, %d/%d output).",
5262                    mCodec->mComponentName.c_str(),
5263                    mCodec->countBuffersOwnedByComponent(kPortIndexInput),
5264                    mCodec->mBuffers[kPortIndexInput].size(),
5265                    mCodec->countBuffersOwnedByComponent(kPortIndexOutput),
5266                    mCodec->mBuffers[kPortIndexOutput].size());
5267
5268            mActive = false;
5269
5270            CHECK_EQ(mCodec->mOMX->sendCommand(
5271                        mCodec->mNode, OMX_CommandFlush, OMX_ALL),
5272                     (status_t)OK);
5273
5274            mCodec->changeState(mCodec->mFlushingState);
5275            handled = true;
5276            break;
5277        }
5278
5279        case kWhatResume:
5280        {
5281            resume();
5282
5283            handled = true;
5284            break;
5285        }
5286
5287        case kWhatRequestIDRFrame:
5288        {
5289            status_t err = mCodec->requestIDRFrame();
5290            if (err != OK) {
5291                ALOGW("Requesting an IDR frame failed.");
5292            }
5293
5294            handled = true;
5295            break;
5296        }
5297
5298        case kWhatSetParameters:
5299        {
5300            sp<AMessage> params;
5301            CHECK(msg->findMessage("params", &params));
5302
5303            status_t err = mCodec->setParameters(params);
5304
5305            sp<AMessage> reply;
5306            if (msg->findMessage("reply", &reply)) {
5307                reply->setInt32("err", err);
5308                reply->post();
5309            }
5310
5311            handled = true;
5312            break;
5313        }
5314
5315        case ACodec::kWhatSignalEndOfInputStream:
5316        {
5317            mCodec->onSignalEndOfInputStream();
5318            handled = true;
5319            break;
5320        }
5321
5322        // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
5323        case kWhatSubmitOutputMetaDataBufferIfEOS:
5324        {
5325            if (mCodec->mPortEOS[kPortIndexInput] &&
5326                    !mCodec->mPortEOS[kPortIndexOutput]) {
5327                status_t err = mCodec->submitOutputMetaDataBuffer();
5328                if (err == OK) {
5329                    mCodec->signalSubmitOutputMetaDataBufferIfEOS_workaround();
5330                }
5331            }
5332            return true;
5333        }
5334
5335        default:
5336            handled = BaseState::onMessageReceived(msg);
5337            break;
5338    }
5339
5340    return handled;
5341}
5342
5343status_t ACodec::setParameters(const sp<AMessage> &params) {
5344    int32_t videoBitrate;
5345    if (params->findInt32("video-bitrate", &videoBitrate)) {
5346        OMX_VIDEO_CONFIG_BITRATETYPE configParams;
5347        InitOMXParams(&configParams);
5348        configParams.nPortIndex = kPortIndexOutput;
5349        configParams.nEncodeBitrate = videoBitrate;
5350
5351        status_t err = mOMX->setConfig(
5352                mNode,
5353                OMX_IndexConfigVideoBitrate,
5354                &configParams,
5355                sizeof(configParams));
5356
5357        if (err != OK) {
5358            ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d",
5359                   videoBitrate, err);
5360
5361            return err;
5362        }
5363    }
5364
5365    int64_t skipFramesBeforeUs;
5366    if (params->findInt64("skip-frames-before", &skipFramesBeforeUs)) {
5367        status_t err =
5368            mOMX->setInternalOption(
5369                     mNode,
5370                     kPortIndexInput,
5371                     IOMX::INTERNAL_OPTION_START_TIME,
5372                     &skipFramesBeforeUs,
5373                     sizeof(skipFramesBeforeUs));
5374
5375        if (err != OK) {
5376            ALOGE("Failed to set parameter 'skip-frames-before' (err %d)", err);
5377            return err;
5378        }
5379    }
5380
5381    int32_t dropInputFrames;
5382    if (params->findInt32("drop-input-frames", &dropInputFrames)) {
5383        bool suspend = dropInputFrames != 0;
5384
5385        status_t err =
5386            mOMX->setInternalOption(
5387                     mNode,
5388                     kPortIndexInput,
5389                     IOMX::INTERNAL_OPTION_SUSPEND,
5390                     &suspend,
5391                     sizeof(suspend));
5392
5393        if (err != OK) {
5394            ALOGE("Failed to set parameter 'drop-input-frames' (err %d)", err);
5395            return err;
5396        }
5397    }
5398
5399    int32_t dummy;
5400    if (params->findInt32("request-sync", &dummy)) {
5401        status_t err = requestIDRFrame();
5402
5403        if (err != OK) {
5404            ALOGE("Requesting a sync frame failed w/ err %d", err);
5405            return err;
5406        }
5407    }
5408
5409    return OK;
5410}
5411
5412void ACodec::onSignalEndOfInputStream() {
5413    sp<AMessage> notify = mNotify->dup();
5414    notify->setInt32("what", CodecBase::kWhatSignaledInputEOS);
5415
5416    status_t err = mOMX->signalEndOfInputStream(mNode);
5417    if (err != OK) {
5418        notify->setInt32("err", err);
5419    }
5420    notify->post();
5421}
5422
5423bool ACodec::ExecutingState::onOMXEvent(
5424        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5425    switch (event) {
5426        case OMX_EventPortSettingsChanged:
5427        {
5428            CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
5429
5430            if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
5431                mCodec->mMetaDataBuffersToSubmit = 0;
5432                CHECK_EQ(mCodec->mOMX->sendCommand(
5433                            mCodec->mNode,
5434                            OMX_CommandPortDisable, kPortIndexOutput),
5435                         (status_t)OK);
5436
5437                mCodec->freeOutputBuffersNotOwnedByComponent();
5438
5439                mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
5440            } else if (data2 == OMX_IndexConfigCommonOutputCrop) {
5441                mCodec->mSentFormat = false;
5442            } else {
5443                ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx",
5444                     mCodec->mComponentName.c_str(), data2);
5445            }
5446
5447            return true;
5448        }
5449
5450        case OMX_EventBufferFlag:
5451        {
5452            return true;
5453        }
5454
5455        default:
5456            return BaseState::onOMXEvent(event, data1, data2);
5457    }
5458}
5459
5460////////////////////////////////////////////////////////////////////////////////
5461
5462ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState(
5463        ACodec *codec)
5464    : BaseState(codec) {
5465}
5466
5467ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode(
5468        OMX_U32 portIndex) {
5469    if (portIndex == kPortIndexOutput) {
5470        return FREE_BUFFERS;
5471    }
5472
5473    CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput);
5474
5475    return RESUBMIT_BUFFERS;
5476}
5477
5478bool ACodec::OutputPortSettingsChangedState::onMessageReceived(
5479        const sp<AMessage> &msg) {
5480    bool handled = false;
5481
5482    switch (msg->what()) {
5483        case kWhatFlush:
5484        case kWhatShutdown:
5485        case kWhatResume:
5486        {
5487            if (msg->what() == kWhatResume) {
5488                ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
5489            }
5490
5491            mCodec->deferMessage(msg);
5492            handled = true;
5493            break;
5494        }
5495
5496        default:
5497            handled = BaseState::onMessageReceived(msg);
5498            break;
5499    }
5500
5501    return handled;
5502}
5503
5504void ACodec::OutputPortSettingsChangedState::stateEntered() {
5505    ALOGV("[%s] Now handling output port settings change",
5506         mCodec->mComponentName.c_str());
5507}
5508
5509bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
5510        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5511    switch (event) {
5512        case OMX_EventCmdComplete:
5513        {
5514            if (data1 == (OMX_U32)OMX_CommandPortDisable) {
5515                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
5516
5517                ALOGV("[%s] Output port now disabled.",
5518                        mCodec->mComponentName.c_str());
5519
5520                CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty());
5521                mCodec->mDealer[kPortIndexOutput].clear();
5522
5523                CHECK_EQ(mCodec->mOMX->sendCommand(
5524                            mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput),
5525                         (status_t)OK);
5526
5527                status_t err;
5528                if ((err = mCodec->allocateBuffersOnPort(
5529                                kPortIndexOutput)) != OK) {
5530                    ALOGE("Failed to allocate output port buffers after "
5531                         "port reconfiguration (error 0x%08x)",
5532                         err);
5533
5534                    mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5535
5536                    // This is technically not correct, but appears to be
5537                    // the only way to free the component instance.
5538                    // Controlled transitioning from excecuting->idle
5539                    // and idle->loaded seem impossible probably because
5540                    // the output port never finishes re-enabling.
5541                    mCodec->mShutdownInProgress = true;
5542                    mCodec->mKeepComponentAllocated = false;
5543                    mCodec->changeState(mCodec->mLoadedState);
5544                }
5545
5546                return true;
5547            } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
5548                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
5549
5550                mCodec->mSentFormat = false;
5551
5552                ALOGV("[%s] Output port now reenabled.",
5553                        mCodec->mComponentName.c_str());
5554
5555                if (mCodec->mExecutingState->active()) {
5556                    mCodec->mExecutingState->submitOutputBuffers();
5557                }
5558
5559                mCodec->changeState(mCodec->mExecutingState);
5560
5561                return true;
5562            }
5563
5564            return false;
5565        }
5566
5567        default:
5568            return false;
5569    }
5570}
5571
5572////////////////////////////////////////////////////////////////////////////////
5573
5574ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec)
5575    : BaseState(codec),
5576      mComponentNowIdle(false) {
5577}
5578
5579bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) {
5580    bool handled = false;
5581
5582    switch (msg->what()) {
5583        case kWhatFlush:
5584        {
5585            // Don't send me a flush request if you previously wanted me
5586            // to shutdown.
5587            TRESPASS();
5588            break;
5589        }
5590
5591        case kWhatShutdown:
5592        {
5593            // We're already doing that...
5594
5595            handled = true;
5596            break;
5597        }
5598
5599        default:
5600            handled = BaseState::onMessageReceived(msg);
5601            break;
5602    }
5603
5604    return handled;
5605}
5606
5607void ACodec::ExecutingToIdleState::stateEntered() {
5608    ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
5609
5610    mComponentNowIdle = false;
5611    mCodec->mSentFormat = false;
5612}
5613
5614bool ACodec::ExecutingToIdleState::onOMXEvent(
5615        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5616    switch (event) {
5617        case OMX_EventCmdComplete:
5618        {
5619            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
5620            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
5621
5622            mComponentNowIdle = true;
5623
5624            changeStateIfWeOwnAllBuffers();
5625
5626            return true;
5627        }
5628
5629        case OMX_EventPortSettingsChanged:
5630        case OMX_EventBufferFlag:
5631        {
5632            // We're shutting down and don't care about this anymore.
5633            return true;
5634        }
5635
5636        default:
5637            return BaseState::onOMXEvent(event, data1, data2);
5638    }
5639}
5640
5641void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
5642    if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) {
5643        CHECK_EQ(mCodec->mOMX->sendCommand(
5644                    mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded),
5645                 (status_t)OK);
5646
5647        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK);
5648        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK);
5649
5650        if ((mCodec->mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown)
5651                && mCodec->mNativeWindow != NULL) {
5652            // We push enough 1x1 blank buffers to ensure that one of
5653            // them has made it to the display.  This allows the OMX
5654            // component teardown to zero out any protected buffers
5655            // without the risk of scanning out one of those buffers.
5656            mCodec->pushBlankBuffersToNativeWindow();
5657        }
5658
5659        mCodec->changeState(mCodec->mIdleToLoadedState);
5660    }
5661}
5662
5663void ACodec::ExecutingToIdleState::onInputBufferFilled(
5664        const sp<AMessage> &msg) {
5665    BaseState::onInputBufferFilled(msg);
5666
5667    changeStateIfWeOwnAllBuffers();
5668}
5669
5670void ACodec::ExecutingToIdleState::onOutputBufferDrained(
5671        const sp<AMessage> &msg) {
5672    BaseState::onOutputBufferDrained(msg);
5673
5674    changeStateIfWeOwnAllBuffers();
5675}
5676
5677////////////////////////////////////////////////////////////////////////////////
5678
5679ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec)
5680    : BaseState(codec) {
5681}
5682
5683bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) {
5684    bool handled = false;
5685
5686    switch (msg->what()) {
5687        case kWhatShutdown:
5688        {
5689            // We're already doing that...
5690
5691            handled = true;
5692            break;
5693        }
5694
5695        case kWhatFlush:
5696        {
5697            // Don't send me a flush request if you previously wanted me
5698            // to shutdown.
5699            TRESPASS();
5700            break;
5701        }
5702
5703        default:
5704            handled = BaseState::onMessageReceived(msg);
5705            break;
5706    }
5707
5708    return handled;
5709}
5710
5711void ACodec::IdleToLoadedState::stateEntered() {
5712    ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
5713}
5714
5715bool ACodec::IdleToLoadedState::onOMXEvent(
5716        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5717    switch (event) {
5718        case OMX_EventCmdComplete:
5719        {
5720            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
5721            CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded);
5722
5723            mCodec->changeState(mCodec->mLoadedState);
5724
5725            return true;
5726        }
5727
5728        default:
5729            return BaseState::onOMXEvent(event, data1, data2);
5730    }
5731}
5732
5733////////////////////////////////////////////////////////////////////////////////
5734
5735ACodec::FlushingState::FlushingState(ACodec *codec)
5736    : BaseState(codec) {
5737}
5738
5739void ACodec::FlushingState::stateEntered() {
5740    ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());
5741
5742    mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
5743}
5744
5745bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) {
5746    bool handled = false;
5747
5748    switch (msg->what()) {
5749        case kWhatShutdown:
5750        {
5751            mCodec->deferMessage(msg);
5752            break;
5753        }
5754
5755        case kWhatFlush:
5756        {
5757            // We're already doing this right now.
5758            handled = true;
5759            break;
5760        }
5761
5762        default:
5763            handled = BaseState::onMessageReceived(msg);
5764            break;
5765    }
5766
5767    return handled;
5768}
5769
5770bool ACodec::FlushingState::onOMXEvent(
5771        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5772    ALOGV("[%s] FlushingState onOMXEvent(%d,%ld)",
5773            mCodec->mComponentName.c_str(), event, data1);
5774
5775    switch (event) {
5776        case OMX_EventCmdComplete:
5777        {
5778            CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush);
5779
5780            if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
5781                CHECK(!mFlushComplete[data2]);
5782                mFlushComplete[data2] = true;
5783
5784                if (mFlushComplete[kPortIndexInput]
5785                        && mFlushComplete[kPortIndexOutput]) {
5786                    changeStateIfWeOwnAllBuffers();
5787                }
5788            } else {
5789                CHECK_EQ(data2, OMX_ALL);
5790                CHECK(mFlushComplete[kPortIndexInput]);
5791                CHECK(mFlushComplete[kPortIndexOutput]);
5792
5793                changeStateIfWeOwnAllBuffers();
5794            }
5795
5796            return true;
5797        }
5798
5799        case OMX_EventPortSettingsChanged:
5800        {
5801            sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id());
5802            msg->setInt32("type", omx_message::EVENT);
5803            msg->setInt32("node", mCodec->mNode);
5804            msg->setInt32("event", event);
5805            msg->setInt32("data1", data1);
5806            msg->setInt32("data2", data2);
5807
5808            ALOGV("[%s] Deferring OMX_EventPortSettingsChanged",
5809                 mCodec->mComponentName.c_str());
5810
5811            mCodec->deferMessage(msg);
5812
5813            return true;
5814        }
5815
5816        default:
5817            return BaseState::onOMXEvent(event, data1, data2);
5818    }
5819
5820    return true;
5821}
5822
5823void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) {
5824    BaseState::onOutputBufferDrained(msg);
5825
5826    changeStateIfWeOwnAllBuffers();
5827}
5828
5829void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) {
5830    BaseState::onInputBufferFilled(msg);
5831
5832    changeStateIfWeOwnAllBuffers();
5833}
5834
5835void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() {
5836    if (mFlushComplete[kPortIndexInput]
5837            && mFlushComplete[kPortIndexOutput]
5838            && mCodec->allYourBuffersAreBelongToUs()) {
5839        // We now own all buffers except possibly those still queued with
5840        // the native window for rendering. Let's get those back as well.
5841        mCodec->waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs();
5842
5843        sp<AMessage> notify = mCodec->mNotify->dup();
5844        notify->setInt32("what", CodecBase::kWhatFlushCompleted);
5845        notify->post();
5846
5847        mCodec->mPortEOS[kPortIndexInput] =
5848            mCodec->mPortEOS[kPortIndexOutput] = false;
5849
5850        mCodec->mInputEOSResult = OK;
5851
5852        if (mCodec->mSkipCutBuffer != NULL) {
5853            mCodec->mSkipCutBuffer->clear();
5854        }
5855
5856        mCodec->changeState(mCodec->mExecutingState);
5857    }
5858}
5859
5860}  // namespace android
5861