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