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