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