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