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