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