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