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