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