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