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