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