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