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