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