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