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