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