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