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