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