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