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