ACodec.cpp revision e9e63bcf6c36351f1129b0bdc5e93f17f0f9f0b4
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            int32_t width, height;
1271            if (!msg->findInt32("width", &width)
1272                    || !msg->findInt32("height", &height)) {
1273                err = INVALID_OPERATION;
1274            } else {
1275                err = setupVideoDecoder(mime, width, height);
1276            }
1277        }
1278    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
1279        int32_t numChannels, sampleRate;
1280        if (!msg->findInt32("channel-count", &numChannels)
1281                || !msg->findInt32("sample-rate", &sampleRate)) {
1282            // Since we did not always check for these, leave them optional
1283            // and have the decoder figure it all out.
1284            err = OK;
1285        } else {
1286            err = setupRawAudioFormat(
1287                    encoder ? kPortIndexInput : kPortIndexOutput,
1288                    sampleRate,
1289                    numChannels);
1290        }
1291    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
1292        int32_t numChannels, sampleRate;
1293        if (!msg->findInt32("channel-count", &numChannels)
1294                || !msg->findInt32("sample-rate", &sampleRate)) {
1295            err = INVALID_OPERATION;
1296        } else {
1297            int32_t isADTS, aacProfile;
1298            if (!msg->findInt32("is-adts", &isADTS)) {
1299                isADTS = 0;
1300            }
1301            if (!msg->findInt32("aac-profile", &aacProfile)) {
1302                aacProfile = OMX_AUDIO_AACObjectNull;
1303            }
1304
1305            err = setupAACCodec(
1306                    encoder, numChannels, sampleRate, bitRate, aacProfile,
1307                    isADTS != 0);
1308        }
1309    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) {
1310        err = setupAMRCodec(encoder, false /* isWAMR */, bitRate);
1311    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
1312        err = setupAMRCodec(encoder, true /* isWAMR */, bitRate);
1313    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW)
1314            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) {
1315        // These are PCM-like formats with a fixed sample rate but
1316        // a variable number of channels.
1317
1318        int32_t numChannels;
1319        if (!msg->findInt32("channel-count", &numChannels)) {
1320            err = INVALID_OPERATION;
1321        } else {
1322            err = setupG711Codec(encoder, numChannels);
1323        }
1324    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)) {
1325        int32_t numChannels, sampleRate, compressionLevel = -1;
1326        if (encoder &&
1327                (!msg->findInt32("channel-count", &numChannels)
1328                        || !msg->findInt32("sample-rate", &sampleRate))) {
1329            ALOGE("missing channel count or sample rate for FLAC encoder");
1330            err = INVALID_OPERATION;
1331        } else {
1332            if (encoder) {
1333                if (!msg->findInt32(
1334                            "flac-compression-level", &compressionLevel)) {
1335                    compressionLevel = 5;// default FLAC compression level
1336                } else if (compressionLevel < 0) {
1337                    ALOGW("compression level %d outside [0..8] range, "
1338                          "using 0",
1339                          compressionLevel);
1340                    compressionLevel = 0;
1341                } else if (compressionLevel > 8) {
1342                    ALOGW("compression level %d outside [0..8] range, "
1343                          "using 8",
1344                          compressionLevel);
1345                    compressionLevel = 8;
1346                }
1347            }
1348            err = setupFlacCodec(
1349                    encoder, numChannels, sampleRate, compressionLevel);
1350        }
1351    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
1352        int32_t numChannels, sampleRate;
1353        if (encoder
1354                || !msg->findInt32("channel-count", &numChannels)
1355                || !msg->findInt32("sample-rate", &sampleRate)) {
1356            err = INVALID_OPERATION;
1357        } else {
1358            err = setupRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
1359        }
1360    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AC3)) {
1361        int32_t numChannels;
1362        int32_t sampleRate;
1363        if (!msg->findInt32("channel-count", &numChannels)
1364                || !msg->findInt32("sample-rate", &sampleRate)) {
1365            err = INVALID_OPERATION;
1366        } else {
1367            err = setupAC3Codec(encoder, numChannels, sampleRate);
1368        }
1369    }
1370
1371    if (err != OK) {
1372        return err;
1373    }
1374
1375    if (!msg->findInt32("encoder-delay", &mEncoderDelay)) {
1376        mEncoderDelay = 0;
1377    }
1378
1379    if (!msg->findInt32("encoder-padding", &mEncoderPadding)) {
1380        mEncoderPadding = 0;
1381    }
1382
1383    if (msg->findInt32("channel-mask", &mChannelMask)) {
1384        mChannelMaskPresent = true;
1385    } else {
1386        mChannelMaskPresent = false;
1387    }
1388
1389    int32_t maxInputSize;
1390    if (msg->findInt32("max-input-size", &maxInputSize)) {
1391        err = setMinBufferSize(kPortIndexInput, (size_t)maxInputSize);
1392    } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) {
1393        err = setMinBufferSize(kPortIndexInput, 8192);  // XXX
1394    }
1395
1396    CHECK_EQ(getPortFormat(kPortIndexInput, inputFormat), (status_t)OK);
1397    CHECK_EQ(getPortFormat(kPortIndexOutput, outputFormat), (status_t)OK);
1398    mInputFormat = inputFormat;
1399    mOutputFormat = outputFormat;
1400
1401    return err;
1402}
1403
1404status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) {
1405    OMX_PARAM_PORTDEFINITIONTYPE def;
1406    InitOMXParams(&def);
1407    def.nPortIndex = portIndex;
1408
1409    status_t err = mOMX->getParameter(
1410            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1411
1412    if (err != OK) {
1413        return err;
1414    }
1415
1416    if (def.nBufferSize >= size) {
1417        return OK;
1418    }
1419
1420    def.nBufferSize = size;
1421
1422    err = mOMX->setParameter(
1423            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1424
1425    if (err != OK) {
1426        return err;
1427    }
1428
1429    err = mOMX->getParameter(
1430            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1431
1432    if (err != OK) {
1433        return err;
1434    }
1435
1436    CHECK(def.nBufferSize >= size);
1437
1438    return OK;
1439}
1440
1441status_t ACodec::selectAudioPortFormat(
1442        OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat) {
1443    OMX_AUDIO_PARAM_PORTFORMATTYPE format;
1444    InitOMXParams(&format);
1445
1446    format.nPortIndex = portIndex;
1447    for (OMX_U32 index = 0;; ++index) {
1448        format.nIndex = index;
1449
1450        status_t err = mOMX->getParameter(
1451                mNode, OMX_IndexParamAudioPortFormat,
1452                &format, sizeof(format));
1453
1454        if (err != OK) {
1455            return err;
1456        }
1457
1458        if (format.eEncoding == desiredFormat) {
1459            break;
1460        }
1461    }
1462
1463    return mOMX->setParameter(
1464            mNode, OMX_IndexParamAudioPortFormat, &format, sizeof(format));
1465}
1466
1467status_t ACodec::setupAACCodec(
1468        bool encoder, int32_t numChannels, int32_t sampleRate,
1469        int32_t bitRate, int32_t aacProfile, bool isADTS) {
1470    if (encoder && isADTS) {
1471        return -EINVAL;
1472    }
1473
1474    status_t err = setupRawAudioFormat(
1475            encoder ? kPortIndexInput : kPortIndexOutput,
1476            sampleRate,
1477            numChannels);
1478
1479    if (err != OK) {
1480        return err;
1481    }
1482
1483    if (encoder) {
1484        err = selectAudioPortFormat(kPortIndexOutput, OMX_AUDIO_CodingAAC);
1485
1486        if (err != OK) {
1487            return err;
1488        }
1489
1490        OMX_PARAM_PORTDEFINITIONTYPE def;
1491        InitOMXParams(&def);
1492        def.nPortIndex = kPortIndexOutput;
1493
1494        err = mOMX->getParameter(
1495                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1496
1497        if (err != OK) {
1498            return err;
1499        }
1500
1501        def.format.audio.bFlagErrorConcealment = OMX_TRUE;
1502        def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
1503
1504        err = mOMX->setParameter(
1505                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1506
1507        if (err != OK) {
1508            return err;
1509        }
1510
1511        OMX_AUDIO_PARAM_AACPROFILETYPE profile;
1512        InitOMXParams(&profile);
1513        profile.nPortIndex = kPortIndexOutput;
1514
1515        err = mOMX->getParameter(
1516                mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1517
1518        if (err != OK) {
1519            return err;
1520        }
1521
1522        profile.nChannels = numChannels;
1523
1524        profile.eChannelMode =
1525            (numChannels == 1)
1526                ? OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo;
1527
1528        profile.nSampleRate = sampleRate;
1529        profile.nBitRate = bitRate;
1530        profile.nAudioBandWidth = 0;
1531        profile.nFrameLength = 0;
1532        profile.nAACtools = OMX_AUDIO_AACToolAll;
1533        profile.nAACERtools = OMX_AUDIO_AACERNone;
1534        profile.eAACProfile = (OMX_AUDIO_AACPROFILETYPE) aacProfile;
1535        profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
1536
1537        err = mOMX->setParameter(
1538                mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1539
1540        if (err != OK) {
1541            return err;
1542        }
1543
1544        return err;
1545    }
1546
1547    OMX_AUDIO_PARAM_AACPROFILETYPE profile;
1548    InitOMXParams(&profile);
1549    profile.nPortIndex = kPortIndexInput;
1550
1551    err = mOMX->getParameter(
1552            mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1553
1554    if (err != OK) {
1555        return err;
1556    }
1557
1558    profile.nChannels = numChannels;
1559    profile.nSampleRate = sampleRate;
1560
1561    profile.eAACStreamFormat =
1562        isADTS
1563            ? OMX_AUDIO_AACStreamFormatMP4ADTS
1564            : OMX_AUDIO_AACStreamFormatMP4FF;
1565
1566    return mOMX->setParameter(
1567            mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1568}
1569
1570status_t ACodec::setupAC3Codec(
1571        bool encoder, int32_t numChannels, int32_t sampleRate) {
1572    status_t err = setupRawAudioFormat(
1573            encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels);
1574
1575    if (err != OK) {
1576        return err;
1577    }
1578
1579    if (encoder) {
1580        ALOGW("AC3 encoding is not supported.");
1581        return INVALID_OPERATION;
1582    }
1583
1584    OMX_AUDIO_PARAM_ANDROID_AC3TYPE def;
1585    InitOMXParams(&def);
1586    def.nPortIndex = kPortIndexInput;
1587
1588    err = mOMX->getParameter(
1589            mNode,
1590            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
1591            &def,
1592            sizeof(def));
1593
1594    if (err != OK) {
1595        return err;
1596    }
1597
1598    def.nChannels = numChannels;
1599    def.nSampleRate = sampleRate;
1600
1601    return mOMX->setParameter(
1602            mNode,
1603            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
1604            &def,
1605            sizeof(def));
1606}
1607
1608static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate(
1609        bool isAMRWB, int32_t bps) {
1610    if (isAMRWB) {
1611        if (bps <= 6600) {
1612            return OMX_AUDIO_AMRBandModeWB0;
1613        } else if (bps <= 8850) {
1614            return OMX_AUDIO_AMRBandModeWB1;
1615        } else if (bps <= 12650) {
1616            return OMX_AUDIO_AMRBandModeWB2;
1617        } else if (bps <= 14250) {
1618            return OMX_AUDIO_AMRBandModeWB3;
1619        } else if (bps <= 15850) {
1620            return OMX_AUDIO_AMRBandModeWB4;
1621        } else if (bps <= 18250) {
1622            return OMX_AUDIO_AMRBandModeWB5;
1623        } else if (bps <= 19850) {
1624            return OMX_AUDIO_AMRBandModeWB6;
1625        } else if (bps <= 23050) {
1626            return OMX_AUDIO_AMRBandModeWB7;
1627        }
1628
1629        // 23850 bps
1630        return OMX_AUDIO_AMRBandModeWB8;
1631    } else {  // AMRNB
1632        if (bps <= 4750) {
1633            return OMX_AUDIO_AMRBandModeNB0;
1634        } else if (bps <= 5150) {
1635            return OMX_AUDIO_AMRBandModeNB1;
1636        } else if (bps <= 5900) {
1637            return OMX_AUDIO_AMRBandModeNB2;
1638        } else if (bps <= 6700) {
1639            return OMX_AUDIO_AMRBandModeNB3;
1640        } else if (bps <= 7400) {
1641            return OMX_AUDIO_AMRBandModeNB4;
1642        } else if (bps <= 7950) {
1643            return OMX_AUDIO_AMRBandModeNB5;
1644        } else if (bps <= 10200) {
1645            return OMX_AUDIO_AMRBandModeNB6;
1646        }
1647
1648        // 12200 bps
1649        return OMX_AUDIO_AMRBandModeNB7;
1650    }
1651}
1652
1653status_t ACodec::setupAMRCodec(bool encoder, bool isWAMR, int32_t bitrate) {
1654    OMX_AUDIO_PARAM_AMRTYPE def;
1655    InitOMXParams(&def);
1656    def.nPortIndex = encoder ? kPortIndexOutput : kPortIndexInput;
1657
1658    status_t err =
1659        mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
1660
1661    if (err != OK) {
1662        return err;
1663    }
1664
1665    def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
1666    def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitrate);
1667
1668    err = mOMX->setParameter(
1669            mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
1670
1671    if (err != OK) {
1672        return err;
1673    }
1674
1675    return setupRawAudioFormat(
1676            encoder ? kPortIndexInput : kPortIndexOutput,
1677            isWAMR ? 16000 : 8000 /* sampleRate */,
1678            1 /* numChannels */);
1679}
1680
1681status_t ACodec::setupG711Codec(bool encoder, int32_t numChannels) {
1682    CHECK(!encoder);  // XXX TODO
1683
1684    return setupRawAudioFormat(
1685            kPortIndexInput, 8000 /* sampleRate */, numChannels);
1686}
1687
1688status_t ACodec::setupFlacCodec(
1689        bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel) {
1690
1691    if (encoder) {
1692        OMX_AUDIO_PARAM_FLACTYPE def;
1693        InitOMXParams(&def);
1694        def.nPortIndex = kPortIndexOutput;
1695
1696        // configure compression level
1697        status_t err = mOMX->getParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def));
1698        if (err != OK) {
1699            ALOGE("setupFlacCodec(): Error %d getting OMX_IndexParamAudioFlac parameter", err);
1700            return err;
1701        }
1702        def.nCompressionLevel = compressionLevel;
1703        err = mOMX->setParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def));
1704        if (err != OK) {
1705            ALOGE("setupFlacCodec(): Error %d setting OMX_IndexParamAudioFlac parameter", err);
1706            return err;
1707        }
1708    }
1709
1710    return setupRawAudioFormat(
1711            encoder ? kPortIndexInput : kPortIndexOutput,
1712            sampleRate,
1713            numChannels);
1714}
1715
1716status_t ACodec::setupRawAudioFormat(
1717        OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) {
1718    OMX_PARAM_PORTDEFINITIONTYPE def;
1719    InitOMXParams(&def);
1720    def.nPortIndex = portIndex;
1721
1722    status_t err = mOMX->getParameter(
1723            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1724
1725    if (err != OK) {
1726        return err;
1727    }
1728
1729    def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
1730
1731    err = mOMX->setParameter(
1732            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1733
1734    if (err != OK) {
1735        return err;
1736    }
1737
1738    OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
1739    InitOMXParams(&pcmParams);
1740    pcmParams.nPortIndex = portIndex;
1741
1742    err = mOMX->getParameter(
1743            mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
1744
1745    if (err != OK) {
1746        return err;
1747    }
1748
1749    pcmParams.nChannels = numChannels;
1750    pcmParams.eNumData = OMX_NumericalDataSigned;
1751    pcmParams.bInterleaved = OMX_TRUE;
1752    pcmParams.nBitPerSample = 16;
1753    pcmParams.nSamplingRate = sampleRate;
1754    pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
1755
1756    if (getOMXChannelMapping(numChannels, pcmParams.eChannelMapping) != OK) {
1757        return OMX_ErrorNone;
1758    }
1759
1760    return mOMX->setParameter(
1761            mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
1762}
1763
1764status_t ACodec::setVideoPortFormatType(
1765        OMX_U32 portIndex,
1766        OMX_VIDEO_CODINGTYPE compressionFormat,
1767        OMX_COLOR_FORMATTYPE colorFormat) {
1768    OMX_VIDEO_PARAM_PORTFORMATTYPE format;
1769    InitOMXParams(&format);
1770    format.nPortIndex = portIndex;
1771    format.nIndex = 0;
1772    bool found = false;
1773
1774    OMX_U32 index = 0;
1775    for (;;) {
1776        format.nIndex = index;
1777        status_t err = mOMX->getParameter(
1778                mNode, OMX_IndexParamVideoPortFormat,
1779                &format, sizeof(format));
1780
1781        if (err != OK) {
1782            return err;
1783        }
1784
1785        // The following assertion is violated by TI's video decoder.
1786        // CHECK_EQ(format.nIndex, index);
1787
1788        if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) {
1789            if (portIndex == kPortIndexInput
1790                    && colorFormat == format.eColorFormat) {
1791                // eCompressionFormat does not seem right.
1792                found = true;
1793                break;
1794            }
1795            if (portIndex == kPortIndexOutput
1796                    && compressionFormat == format.eCompressionFormat) {
1797                // eColorFormat does not seem right.
1798                found = true;
1799                break;
1800            }
1801        }
1802
1803        if (format.eCompressionFormat == compressionFormat
1804            && format.eColorFormat == colorFormat) {
1805            found = true;
1806            break;
1807        }
1808
1809        ++index;
1810    }
1811
1812    if (!found) {
1813        return UNKNOWN_ERROR;
1814    }
1815
1816    status_t err = mOMX->setParameter(
1817            mNode, OMX_IndexParamVideoPortFormat,
1818            &format, sizeof(format));
1819
1820    return err;
1821}
1822
1823status_t ACodec::setSupportedOutputFormat() {
1824    OMX_VIDEO_PARAM_PORTFORMATTYPE format;
1825    InitOMXParams(&format);
1826    format.nPortIndex = kPortIndexOutput;
1827    format.nIndex = 0;
1828
1829    status_t err = mOMX->getParameter(
1830            mNode, OMX_IndexParamVideoPortFormat,
1831            &format, sizeof(format));
1832    CHECK_EQ(err, (status_t)OK);
1833    CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused);
1834
1835    return mOMX->setParameter(
1836            mNode, OMX_IndexParamVideoPortFormat,
1837            &format, sizeof(format));
1838}
1839
1840static const struct VideoCodingMapEntry {
1841    const char *mMime;
1842    OMX_VIDEO_CODINGTYPE mVideoCodingType;
1843} kVideoCodingMapEntry[] = {
1844    { MEDIA_MIMETYPE_VIDEO_AVC, OMX_VIDEO_CodingAVC },
1845    { MEDIA_MIMETYPE_VIDEO_HEVC, OMX_VIDEO_CodingHEVC },
1846    { MEDIA_MIMETYPE_VIDEO_MPEG4, OMX_VIDEO_CodingMPEG4 },
1847    { MEDIA_MIMETYPE_VIDEO_H263, OMX_VIDEO_CodingH263 },
1848    { MEDIA_MIMETYPE_VIDEO_MPEG2, OMX_VIDEO_CodingMPEG2 },
1849    { MEDIA_MIMETYPE_VIDEO_VP8, OMX_VIDEO_CodingVP8 },
1850    { MEDIA_MIMETYPE_VIDEO_VP9, OMX_VIDEO_CodingVP9 },
1851};
1852
1853static status_t GetVideoCodingTypeFromMime(
1854        const char *mime, OMX_VIDEO_CODINGTYPE *codingType) {
1855    for (size_t i = 0;
1856         i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]);
1857         ++i) {
1858        if (!strcasecmp(mime, kVideoCodingMapEntry[i].mMime)) {
1859            *codingType = kVideoCodingMapEntry[i].mVideoCodingType;
1860            return OK;
1861        }
1862    }
1863
1864    *codingType = OMX_VIDEO_CodingUnused;
1865
1866    return ERROR_UNSUPPORTED;
1867}
1868
1869static status_t GetMimeTypeForVideoCoding(
1870        OMX_VIDEO_CODINGTYPE codingType, AString *mime) {
1871    for (size_t i = 0;
1872         i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]);
1873         ++i) {
1874        if (codingType == kVideoCodingMapEntry[i].mVideoCodingType) {
1875            *mime = kVideoCodingMapEntry[i].mMime;
1876            return OK;
1877        }
1878    }
1879
1880    mime->clear();
1881
1882    return ERROR_UNSUPPORTED;
1883}
1884
1885status_t ACodec::setupVideoDecoder(
1886        const char *mime, int32_t width, int32_t height) {
1887    OMX_VIDEO_CODINGTYPE compressionFormat;
1888    status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
1889
1890    if (err != OK) {
1891        return err;
1892    }
1893
1894    err = setVideoPortFormatType(
1895            kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
1896
1897    if (err != OK) {
1898        return err;
1899    }
1900
1901    err = setSupportedOutputFormat();
1902
1903    if (err != OK) {
1904        return err;
1905    }
1906
1907    err = setVideoFormatOnPort(
1908            kPortIndexInput, width, height, compressionFormat);
1909
1910    if (err != OK) {
1911        return err;
1912    }
1913
1914    err = setVideoFormatOnPort(
1915            kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused);
1916
1917    if (err != OK) {
1918        return err;
1919    }
1920
1921    return OK;
1922}
1923
1924status_t ACodec::setupVideoEncoder(const char *mime, const sp<AMessage> &msg) {
1925    int32_t tmp;
1926    if (!msg->findInt32("color-format", &tmp)) {
1927        return INVALID_OPERATION;
1928    }
1929
1930    OMX_COLOR_FORMATTYPE colorFormat =
1931        static_cast<OMX_COLOR_FORMATTYPE>(tmp);
1932
1933    status_t err = setVideoPortFormatType(
1934            kPortIndexInput, OMX_VIDEO_CodingUnused, colorFormat);
1935
1936    if (err != OK) {
1937        ALOGE("[%s] does not support color format %d",
1938              mComponentName.c_str(), colorFormat);
1939
1940        return err;
1941    }
1942
1943    /* Input port configuration */
1944
1945    OMX_PARAM_PORTDEFINITIONTYPE def;
1946    InitOMXParams(&def);
1947
1948    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
1949
1950    def.nPortIndex = kPortIndexInput;
1951
1952    err = mOMX->getParameter(
1953            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1954
1955    if (err != OK) {
1956        return err;
1957    }
1958
1959    int32_t width, height, bitrate;
1960    if (!msg->findInt32("width", &width)
1961            || !msg->findInt32("height", &height)
1962            || !msg->findInt32("bitrate", &bitrate)) {
1963        return INVALID_OPERATION;
1964    }
1965
1966    video_def->nFrameWidth = width;
1967    video_def->nFrameHeight = height;
1968
1969    int32_t stride;
1970    if (!msg->findInt32("stride", &stride)) {
1971        stride = width;
1972    }
1973
1974    video_def->nStride = stride;
1975
1976    int32_t sliceHeight;
1977    if (!msg->findInt32("slice-height", &sliceHeight)) {
1978        sliceHeight = height;
1979    }
1980
1981    video_def->nSliceHeight = sliceHeight;
1982
1983    def.nBufferSize = (video_def->nStride * video_def->nSliceHeight * 3) / 2;
1984
1985    float frameRate;
1986    if (!msg->findFloat("frame-rate", &frameRate)) {
1987        int32_t tmp;
1988        if (!msg->findInt32("frame-rate", &tmp)) {
1989            return INVALID_OPERATION;
1990        }
1991        frameRate = (float)tmp;
1992        mTimePerFrameUs = (int64_t) (1000000.0f / frameRate);
1993    }
1994
1995    video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f);
1996    video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
1997    video_def->eColorFormat = colorFormat;
1998
1999    err = mOMX->setParameter(
2000            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2001
2002    if (err != OK) {
2003        ALOGE("[%s] failed to set input port definition parameters.",
2004              mComponentName.c_str());
2005
2006        return err;
2007    }
2008
2009    /* Output port configuration */
2010
2011    OMX_VIDEO_CODINGTYPE compressionFormat;
2012    err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
2013
2014    if (err != OK) {
2015        return err;
2016    }
2017
2018    err = setVideoPortFormatType(
2019            kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused);
2020
2021    if (err != OK) {
2022        ALOGE("[%s] does not support compression format %d",
2023             mComponentName.c_str(), compressionFormat);
2024
2025        return err;
2026    }
2027
2028    def.nPortIndex = kPortIndexOutput;
2029
2030    err = mOMX->getParameter(
2031            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2032
2033    if (err != OK) {
2034        return err;
2035    }
2036
2037    video_def->nFrameWidth = width;
2038    video_def->nFrameHeight = height;
2039    video_def->xFramerate = 0;
2040    video_def->nBitrate = bitrate;
2041    video_def->eCompressionFormat = compressionFormat;
2042    video_def->eColorFormat = OMX_COLOR_FormatUnused;
2043
2044    err = mOMX->setParameter(
2045            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2046
2047    if (err != OK) {
2048        ALOGE("[%s] failed to set output port definition parameters.",
2049              mComponentName.c_str());
2050
2051        return err;
2052    }
2053
2054    switch (compressionFormat) {
2055        case OMX_VIDEO_CodingMPEG4:
2056            err = setupMPEG4EncoderParameters(msg);
2057            break;
2058
2059        case OMX_VIDEO_CodingH263:
2060            err = setupH263EncoderParameters(msg);
2061            break;
2062
2063        case OMX_VIDEO_CodingAVC:
2064            err = setupAVCEncoderParameters(msg);
2065            break;
2066
2067        case OMX_VIDEO_CodingHEVC:
2068            err = setupHEVCEncoderParameters(msg);
2069            break;
2070
2071        case OMX_VIDEO_CodingVP8:
2072        case OMX_VIDEO_CodingVP9:
2073            err = setupVPXEncoderParameters(msg);
2074            break;
2075
2076        default:
2077            break;
2078    }
2079
2080    ALOGI("setupVideoEncoder succeeded");
2081
2082    return err;
2083}
2084
2085status_t ACodec::setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode) {
2086    OMX_VIDEO_PARAM_INTRAREFRESHTYPE params;
2087    InitOMXParams(&params);
2088    params.nPortIndex = kPortIndexOutput;
2089
2090    params.eRefreshMode = static_cast<OMX_VIDEO_INTRAREFRESHTYPE>(mode);
2091
2092    if (params.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic ||
2093            params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) {
2094        int32_t mbs;
2095        if (!msg->findInt32("intra-refresh-CIR-mbs", &mbs)) {
2096            return INVALID_OPERATION;
2097        }
2098        params.nCirMBs = mbs;
2099    }
2100
2101    if (params.eRefreshMode == OMX_VIDEO_IntraRefreshAdaptive ||
2102            params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) {
2103        int32_t mbs;
2104        if (!msg->findInt32("intra-refresh-AIR-mbs", &mbs)) {
2105            return INVALID_OPERATION;
2106        }
2107        params.nAirMBs = mbs;
2108
2109        int32_t ref;
2110        if (!msg->findInt32("intra-refresh-AIR-ref", &ref)) {
2111            return INVALID_OPERATION;
2112        }
2113        params.nAirRef = ref;
2114    }
2115
2116    status_t err = mOMX->setParameter(
2117            mNode, OMX_IndexParamVideoIntraRefresh,
2118            &params, sizeof(params));
2119    return err;
2120}
2121
2122static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) {
2123    if (iFramesInterval < 0) {
2124        return 0xFFFFFFFF;
2125    } else if (iFramesInterval == 0) {
2126        return 0;
2127    }
2128    OMX_U32 ret = frameRate * iFramesInterval;
2129    CHECK(ret > 1);
2130    return ret;
2131}
2132
2133static OMX_VIDEO_CONTROLRATETYPE getBitrateMode(const sp<AMessage> &msg) {
2134    int32_t tmp;
2135    if (!msg->findInt32("bitrate-mode", &tmp)) {
2136        return OMX_Video_ControlRateVariable;
2137    }
2138
2139    return static_cast<OMX_VIDEO_CONTROLRATETYPE>(tmp);
2140}
2141
2142status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) {
2143    int32_t bitrate, iFrameInterval;
2144    if (!msg->findInt32("bitrate", &bitrate)
2145            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
2146        return INVALID_OPERATION;
2147    }
2148
2149    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
2150
2151    float frameRate;
2152    if (!msg->findFloat("frame-rate", &frameRate)) {
2153        int32_t tmp;
2154        if (!msg->findInt32("frame-rate", &tmp)) {
2155            return INVALID_OPERATION;
2156        }
2157        frameRate = (float)tmp;
2158    }
2159
2160    OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type;
2161    InitOMXParams(&mpeg4type);
2162    mpeg4type.nPortIndex = kPortIndexOutput;
2163
2164    status_t err = mOMX->getParameter(
2165            mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
2166
2167    if (err != OK) {
2168        return err;
2169    }
2170
2171    mpeg4type.nSliceHeaderSpacing = 0;
2172    mpeg4type.bSVH = OMX_FALSE;
2173    mpeg4type.bGov = OMX_FALSE;
2174
2175    mpeg4type.nAllowedPictureTypes =
2176        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
2177
2178    mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
2179    if (mpeg4type.nPFrames == 0) {
2180        mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
2181    }
2182    mpeg4type.nBFrames = 0;
2183    mpeg4type.nIDCVLCThreshold = 0;
2184    mpeg4type.bACPred = OMX_TRUE;
2185    mpeg4type.nMaxPacketSize = 256;
2186    mpeg4type.nTimeIncRes = 1000;
2187    mpeg4type.nHeaderExtension = 0;
2188    mpeg4type.bReversibleVLC = OMX_FALSE;
2189
2190    int32_t profile;
2191    if (msg->findInt32("profile", &profile)) {
2192        int32_t level;
2193        if (!msg->findInt32("level", &level)) {
2194            return INVALID_OPERATION;
2195        }
2196
2197        err = verifySupportForProfileAndLevel(profile, level);
2198
2199        if (err != OK) {
2200            return err;
2201        }
2202
2203        mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile);
2204        mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level);
2205    }
2206
2207    err = mOMX->setParameter(
2208            mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
2209
2210    if (err != OK) {
2211        return err;
2212    }
2213
2214    err = configureBitrate(bitrate, bitrateMode);
2215
2216    if (err != OK) {
2217        return err;
2218    }
2219
2220    return setupErrorCorrectionParameters();
2221}
2222
2223status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) {
2224    int32_t bitrate, iFrameInterval;
2225    if (!msg->findInt32("bitrate", &bitrate)
2226            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
2227        return INVALID_OPERATION;
2228    }
2229
2230    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
2231
2232    float frameRate;
2233    if (!msg->findFloat("frame-rate", &frameRate)) {
2234        int32_t tmp;
2235        if (!msg->findInt32("frame-rate", &tmp)) {
2236            return INVALID_OPERATION;
2237        }
2238        frameRate = (float)tmp;
2239    }
2240
2241    OMX_VIDEO_PARAM_H263TYPE h263type;
2242    InitOMXParams(&h263type);
2243    h263type.nPortIndex = kPortIndexOutput;
2244
2245    status_t err = mOMX->getParameter(
2246            mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
2247
2248    if (err != OK) {
2249        return err;
2250    }
2251
2252    h263type.nAllowedPictureTypes =
2253        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
2254
2255    h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
2256    if (h263type.nPFrames == 0) {
2257        h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
2258    }
2259    h263type.nBFrames = 0;
2260
2261    int32_t profile;
2262    if (msg->findInt32("profile", &profile)) {
2263        int32_t level;
2264        if (!msg->findInt32("level", &level)) {
2265            return INVALID_OPERATION;
2266        }
2267
2268        err = verifySupportForProfileAndLevel(profile, level);
2269
2270        if (err != OK) {
2271            return err;
2272        }
2273
2274        h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile);
2275        h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level);
2276    }
2277
2278    h263type.bPLUSPTYPEAllowed = OMX_FALSE;
2279    h263type.bForceRoundingTypeToZero = OMX_FALSE;
2280    h263type.nPictureHeaderRepetition = 0;
2281    h263type.nGOBHeaderInterval = 0;
2282
2283    err = mOMX->setParameter(
2284            mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
2285
2286    if (err != OK) {
2287        return err;
2288    }
2289
2290    err = configureBitrate(bitrate, bitrateMode);
2291
2292    if (err != OK) {
2293        return err;
2294    }
2295
2296    return setupErrorCorrectionParameters();
2297}
2298
2299status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) {
2300    int32_t bitrate, iFrameInterval;
2301    if (!msg->findInt32("bitrate", &bitrate)
2302            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
2303        return INVALID_OPERATION;
2304    }
2305
2306    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
2307
2308    float frameRate;
2309    if (!msg->findFloat("frame-rate", &frameRate)) {
2310        int32_t tmp;
2311        if (!msg->findInt32("frame-rate", &tmp)) {
2312            return INVALID_OPERATION;
2313        }
2314        frameRate = (float)tmp;
2315    }
2316
2317    status_t err = OK;
2318    int32_t intraRefreshMode = 0;
2319    if (msg->findInt32("intra-refresh-mode", &intraRefreshMode)) {
2320        err = setCyclicIntraMacroblockRefresh(msg, intraRefreshMode);
2321        if (err != OK) {
2322            ALOGE("Setting intra macroblock refresh mode (%d) failed: 0x%x",
2323                    err, intraRefreshMode);
2324            return err;
2325        }
2326    }
2327
2328    OMX_VIDEO_PARAM_AVCTYPE h264type;
2329    InitOMXParams(&h264type);
2330    h264type.nPortIndex = kPortIndexOutput;
2331
2332    err = mOMX->getParameter(
2333            mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
2334
2335    if (err != OK) {
2336        return err;
2337    }
2338
2339    h264type.nAllowedPictureTypes =
2340        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
2341
2342    int32_t profile;
2343    if (msg->findInt32("profile", &profile)) {
2344        int32_t level;
2345        if (!msg->findInt32("level", &level)) {
2346            return INVALID_OPERATION;
2347        }
2348
2349        err = verifySupportForProfileAndLevel(profile, level);
2350
2351        if (err != OK) {
2352            return err;
2353        }
2354
2355        h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile);
2356        h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level);
2357    }
2358
2359    // XXX
2360    if (h264type.eProfile != OMX_VIDEO_AVCProfileBaseline) {
2361        ALOGW("Use baseline profile instead of %d for AVC recording",
2362            h264type.eProfile);
2363        h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
2364    }
2365
2366    if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
2367        h264type.nSliceHeaderSpacing = 0;
2368        h264type.bUseHadamard = OMX_TRUE;
2369        h264type.nRefFrames = 1;
2370        h264type.nBFrames = 0;
2371        h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
2372        if (h264type.nPFrames == 0) {
2373            h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
2374        }
2375        h264type.nRefIdx10ActiveMinus1 = 0;
2376        h264type.nRefIdx11ActiveMinus1 = 0;
2377        h264type.bEntropyCodingCABAC = OMX_FALSE;
2378        h264type.bWeightedPPrediction = OMX_FALSE;
2379        h264type.bconstIpred = OMX_FALSE;
2380        h264type.bDirect8x8Inference = OMX_FALSE;
2381        h264type.bDirectSpatialTemporal = OMX_FALSE;
2382        h264type.nCabacInitIdc = 0;
2383    }
2384
2385    if (h264type.nBFrames != 0) {
2386        h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
2387    }
2388
2389    h264type.bEnableUEP = OMX_FALSE;
2390    h264type.bEnableFMO = OMX_FALSE;
2391    h264type.bEnableASO = OMX_FALSE;
2392    h264type.bEnableRS = OMX_FALSE;
2393    h264type.bFrameMBsOnly = OMX_TRUE;
2394    h264type.bMBAFF = OMX_FALSE;
2395    h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
2396
2397    err = mOMX->setParameter(
2398            mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
2399
2400    if (err != OK) {
2401        return err;
2402    }
2403
2404    return configureBitrate(bitrate, bitrateMode);
2405}
2406
2407status_t ACodec::setupHEVCEncoderParameters(const sp<AMessage> &msg) {
2408    int32_t bitrate, iFrameInterval;
2409    if (!msg->findInt32("bitrate", &bitrate)
2410            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
2411        return INVALID_OPERATION;
2412    }
2413
2414    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
2415
2416    float frameRate;
2417    if (!msg->findFloat("frame-rate", &frameRate)) {
2418        int32_t tmp;
2419        if (!msg->findInt32("frame-rate", &tmp)) {
2420            return INVALID_OPERATION;
2421        }
2422        frameRate = (float)tmp;
2423    }
2424
2425    OMX_VIDEO_PARAM_HEVCTYPE hevcType;
2426    InitOMXParams(&hevcType);
2427    hevcType.nPortIndex = kPortIndexOutput;
2428
2429    status_t err = OK;
2430    err = mOMX->getParameter(
2431            mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
2432    if (err != OK) {
2433        return err;
2434    }
2435
2436    int32_t profile;
2437    if (msg->findInt32("profile", &profile)) {
2438        int32_t level;
2439        if (!msg->findInt32("level", &level)) {
2440            return INVALID_OPERATION;
2441        }
2442
2443        err = verifySupportForProfileAndLevel(profile, level);
2444        if (err != OK) {
2445            return err;
2446        }
2447
2448        hevcType.eProfile = static_cast<OMX_VIDEO_HEVCPROFILETYPE>(profile);
2449        hevcType.eLevel = static_cast<OMX_VIDEO_HEVCLEVELTYPE>(level);
2450    }
2451
2452    // TODO: Need OMX structure definition for setting iFrameInterval
2453
2454    err = mOMX->setParameter(
2455            mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
2456    if (err != OK) {
2457        return err;
2458    }
2459
2460    return configureBitrate(bitrate, bitrateMode);
2461}
2462
2463status_t ACodec::setupVPXEncoderParameters(const sp<AMessage> &msg) {
2464    int32_t bitrate;
2465    int32_t iFrameInterval = 0;
2466    size_t tsLayers = 0;
2467    OMX_VIDEO_ANDROID_VPXTEMPORALLAYERPATTERNTYPE pattern =
2468        OMX_VIDEO_VPXTemporalLayerPatternNone;
2469    static const uint32_t kVp8LayerRateAlloction
2470        [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS]
2471        [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS] = {
2472        {100, 100, 100},  // 1 layer
2473        { 60, 100, 100},  // 2 layers {60%, 40%}
2474        { 40,  60, 100},  // 3 layers {40%, 20%, 40%}
2475    };
2476    if (!msg->findInt32("bitrate", &bitrate)) {
2477        return INVALID_OPERATION;
2478    }
2479    msg->findInt32("i-frame-interval", &iFrameInterval);
2480
2481    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
2482
2483    float frameRate;
2484    if (!msg->findFloat("frame-rate", &frameRate)) {
2485        int32_t tmp;
2486        if (!msg->findInt32("frame-rate", &tmp)) {
2487            return INVALID_OPERATION;
2488        }
2489        frameRate = (float)tmp;
2490    }
2491
2492    AString tsSchema;
2493    if (msg->findString("ts-schema", &tsSchema)) {
2494        if (tsSchema == "webrtc.vp8.1-layer") {
2495            pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
2496            tsLayers = 1;
2497        } else if (tsSchema == "webrtc.vp8.2-layer") {
2498            pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
2499            tsLayers = 2;
2500        } else if (tsSchema == "webrtc.vp8.3-layer") {
2501            pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
2502            tsLayers = 3;
2503        } else {
2504            ALOGW("Unsupported ts-schema [%s]", tsSchema.c_str());
2505        }
2506    }
2507
2508    OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type;
2509    InitOMXParams(&vp8type);
2510    vp8type.nPortIndex = kPortIndexOutput;
2511    status_t err = mOMX->getParameter(
2512            mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
2513            &vp8type, sizeof(vp8type));
2514
2515    if (err == OK) {
2516        if (iFrameInterval > 0) {
2517            vp8type.nKeyFrameInterval = setPFramesSpacing(iFrameInterval, frameRate);
2518        }
2519        vp8type.eTemporalPattern = pattern;
2520        vp8type.nTemporalLayerCount = tsLayers;
2521        if (tsLayers > 0) {
2522            for (size_t i = 0; i < OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS; i++) {
2523                vp8type.nTemporalLayerBitrateRatio[i] =
2524                    kVp8LayerRateAlloction[tsLayers - 1][i];
2525            }
2526        }
2527        if (bitrateMode == OMX_Video_ControlRateConstant) {
2528            vp8type.nMinQuantizer = 2;
2529            vp8type.nMaxQuantizer = 63;
2530        }
2531
2532        err = mOMX->setParameter(
2533                mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
2534                &vp8type, sizeof(vp8type));
2535        if (err != OK) {
2536            ALOGW("Extended VP8 parameters set failed: %d", err);
2537        }
2538    }
2539
2540    return configureBitrate(bitrate, bitrateMode);
2541}
2542
2543status_t ACodec::verifySupportForProfileAndLevel(
2544        int32_t profile, int32_t level) {
2545    OMX_VIDEO_PARAM_PROFILELEVELTYPE params;
2546    InitOMXParams(&params);
2547    params.nPortIndex = kPortIndexOutput;
2548
2549    for (params.nProfileIndex = 0;; ++params.nProfileIndex) {
2550        status_t err = mOMX->getParameter(
2551                mNode,
2552                OMX_IndexParamVideoProfileLevelQuerySupported,
2553                &params,
2554                sizeof(params));
2555
2556        if (err != OK) {
2557            return err;
2558        }
2559
2560        int32_t supportedProfile = static_cast<int32_t>(params.eProfile);
2561        int32_t supportedLevel = static_cast<int32_t>(params.eLevel);
2562
2563        if (profile == supportedProfile && level <= supportedLevel) {
2564            return OK;
2565        }
2566    }
2567}
2568
2569status_t ACodec::configureBitrate(
2570        int32_t bitrate, OMX_VIDEO_CONTROLRATETYPE bitrateMode) {
2571    OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
2572    InitOMXParams(&bitrateType);
2573    bitrateType.nPortIndex = kPortIndexOutput;
2574
2575    status_t err = mOMX->getParameter(
2576            mNode, OMX_IndexParamVideoBitrate,
2577            &bitrateType, sizeof(bitrateType));
2578
2579    if (err != OK) {
2580        return err;
2581    }
2582
2583    bitrateType.eControlRate = bitrateMode;
2584    bitrateType.nTargetBitrate = bitrate;
2585
2586    return mOMX->setParameter(
2587            mNode, OMX_IndexParamVideoBitrate,
2588            &bitrateType, sizeof(bitrateType));
2589}
2590
2591status_t ACodec::setupErrorCorrectionParameters() {
2592    OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
2593    InitOMXParams(&errorCorrectionType);
2594    errorCorrectionType.nPortIndex = kPortIndexOutput;
2595
2596    status_t err = mOMX->getParameter(
2597            mNode, OMX_IndexParamVideoErrorCorrection,
2598            &errorCorrectionType, sizeof(errorCorrectionType));
2599
2600    if (err != OK) {
2601        return OK;  // Optional feature. Ignore this failure
2602    }
2603
2604    errorCorrectionType.bEnableHEC = OMX_FALSE;
2605    errorCorrectionType.bEnableResync = OMX_TRUE;
2606    errorCorrectionType.nResynchMarkerSpacing = 256;
2607    errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
2608    errorCorrectionType.bEnableRVLC = OMX_FALSE;
2609
2610    return mOMX->setParameter(
2611            mNode, OMX_IndexParamVideoErrorCorrection,
2612            &errorCorrectionType, sizeof(errorCorrectionType));
2613}
2614
2615status_t ACodec::setVideoFormatOnPort(
2616        OMX_U32 portIndex,
2617        int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat) {
2618    OMX_PARAM_PORTDEFINITIONTYPE def;
2619    InitOMXParams(&def);
2620    def.nPortIndex = portIndex;
2621
2622    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
2623
2624    status_t err = mOMX->getParameter(
2625            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2626
2627    CHECK_EQ(err, (status_t)OK);
2628
2629    if (portIndex == kPortIndexInput) {
2630        // XXX Need a (much) better heuristic to compute input buffer sizes.
2631        const size_t X = 64 * 1024;
2632        if (def.nBufferSize < X) {
2633            def.nBufferSize = X;
2634        }
2635    }
2636
2637    CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
2638
2639    video_def->nFrameWidth = width;
2640    video_def->nFrameHeight = height;
2641
2642    if (portIndex == kPortIndexInput) {
2643        video_def->eCompressionFormat = compressionFormat;
2644        video_def->eColorFormat = OMX_COLOR_FormatUnused;
2645    }
2646
2647    err = mOMX->setParameter(
2648            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2649
2650    return err;
2651}
2652
2653status_t ACodec::initNativeWindow() {
2654    if (mNativeWindow != NULL) {
2655        return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE);
2656    }
2657
2658    mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE);
2659    return OK;
2660}
2661
2662size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const {
2663    size_t n = 0;
2664
2665    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
2666        const BufferInfo &info = mBuffers[portIndex].itemAt(i);
2667
2668        if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) {
2669            ++n;
2670        }
2671    }
2672
2673    return n;
2674}
2675
2676size_t ACodec::countBuffersOwnedByNativeWindow() const {
2677    size_t n = 0;
2678
2679    for (size_t i = 0; i < mBuffers[kPortIndexOutput].size(); ++i) {
2680        const BufferInfo &info = mBuffers[kPortIndexOutput].itemAt(i);
2681
2682        if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
2683            ++n;
2684        }
2685    }
2686
2687    return n;
2688}
2689
2690void ACodec::waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs() {
2691    if (mNativeWindow == NULL) {
2692        return;
2693    }
2694
2695    while (countBuffersOwnedByNativeWindow() > mNumUndequeuedBuffers
2696            && dequeueBufferFromNativeWindow() != NULL) {
2697        // these buffers will be submitted as regular buffers; account for this
2698        if (mStoreMetaDataInOutputBuffers && mMetaDataBuffersToSubmit > 0) {
2699            --mMetaDataBuffersToSubmit;
2700        }
2701    }
2702}
2703
2704bool ACodec::allYourBuffersAreBelongToUs(
2705        OMX_U32 portIndex) {
2706    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
2707        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
2708
2709        if (info->mStatus != BufferInfo::OWNED_BY_US
2710                && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
2711            ALOGV("[%s] Buffer %u on port %u still has status %d",
2712                    mComponentName.c_str(),
2713                    info->mBufferID, portIndex, info->mStatus);
2714            return false;
2715        }
2716    }
2717
2718    return true;
2719}
2720
2721bool ACodec::allYourBuffersAreBelongToUs() {
2722    return allYourBuffersAreBelongToUs(kPortIndexInput)
2723        && allYourBuffersAreBelongToUs(kPortIndexOutput);
2724}
2725
2726void ACodec::deferMessage(const sp<AMessage> &msg) {
2727    bool wasEmptyBefore = mDeferredQueue.empty();
2728    mDeferredQueue.push_back(msg);
2729}
2730
2731void ACodec::processDeferredMessages() {
2732    List<sp<AMessage> > queue = mDeferredQueue;
2733    mDeferredQueue.clear();
2734
2735    List<sp<AMessage> >::iterator it = queue.begin();
2736    while (it != queue.end()) {
2737        onMessageReceived(*it++);
2738    }
2739}
2740
2741// static
2742void ACodec::describeDefaultColorFormat(DescribeColorFormatParams &params) {
2743    MediaImage &image = params.sMediaImage;
2744    memset(&image, 0, sizeof(image));
2745
2746    image.mType = MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
2747    image.mNumPlanes = 0;
2748
2749    const OMX_COLOR_FORMATTYPE fmt = params.eColorFormat;
2750    // we need stride and slice-height to be non-zero
2751    if (params.nStride == 0 || params.nSliceHeight == 0) {
2752        ALOGW("cannot describe color format 0x%x = %d with stride=%u and sliceHeight=%u",
2753                fmt, fmt, params.nStride, params.nSliceHeight);
2754        return;
2755    }
2756
2757    image.mWidth = params.nFrameWidth;
2758    image.mHeight = params.nFrameHeight;
2759
2760    // only supporting YUV420
2761    if (fmt != OMX_COLOR_FormatYUV420Planar &&
2762        fmt != OMX_COLOR_FormatYUV420PackedPlanar &&
2763        fmt != OMX_COLOR_FormatYUV420SemiPlanar &&
2764        fmt != OMX_COLOR_FormatYUV420PackedSemiPlanar) {
2765        ALOGW("do not know color format 0x%x = %d", fmt, fmt);
2766        return;
2767    }
2768
2769    // set-up YUV format
2770    image.mType = MediaImage::MEDIA_IMAGE_TYPE_YUV;
2771    image.mNumPlanes = 3;
2772    image.mBitDepth = 8;
2773    image.mPlane[image.Y].mOffset = 0;
2774    image.mPlane[image.Y].mColInc = 1;
2775    image.mPlane[image.Y].mRowInc = params.nStride;
2776    image.mPlane[image.Y].mHorizSubsampling = 1;
2777    image.mPlane[image.Y].mVertSubsampling = 1;
2778
2779    switch (fmt) {
2780        case OMX_COLOR_FormatYUV420Planar: // used for YV12
2781        case OMX_COLOR_FormatYUV420PackedPlanar:
2782            image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight;
2783            image.mPlane[image.U].mColInc = 1;
2784            image.mPlane[image.U].mRowInc = params.nStride / 2;
2785            image.mPlane[image.U].mHorizSubsampling = 2;
2786            image.mPlane[image.U].mVertSubsampling = 2;
2787
2788            image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset
2789                    + (params.nStride * params.nSliceHeight / 4);
2790            image.mPlane[image.V].mColInc = 1;
2791            image.mPlane[image.V].mRowInc = params.nStride / 2;
2792            image.mPlane[image.V].mHorizSubsampling = 2;
2793            image.mPlane[image.V].mVertSubsampling = 2;
2794            break;
2795
2796        case OMX_COLOR_FormatYUV420SemiPlanar:
2797            // FIXME: NV21 for sw-encoder, NV12 for decoder and hw-encoder
2798        case OMX_COLOR_FormatYUV420PackedSemiPlanar:
2799            // NV12
2800            image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight;
2801            image.mPlane[image.U].mColInc = 2;
2802            image.mPlane[image.U].mRowInc = params.nStride;
2803            image.mPlane[image.U].mHorizSubsampling = 2;
2804            image.mPlane[image.U].mVertSubsampling = 2;
2805
2806            image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset + 1;
2807            image.mPlane[image.V].mColInc = 2;
2808            image.mPlane[image.V].mRowInc = params.nStride;
2809            image.mPlane[image.V].mHorizSubsampling = 2;
2810            image.mPlane[image.V].mVertSubsampling = 2;
2811            break;
2812
2813        default:
2814            TRESPASS();
2815    }
2816}
2817
2818status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> &notify) {
2819    // TODO: catch errors an return them instead of using CHECK
2820    OMX_PARAM_PORTDEFINITIONTYPE def;
2821    InitOMXParams(&def);
2822    def.nPortIndex = portIndex;
2823
2824    CHECK_EQ(mOMX->getParameter(
2825                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)),
2826             (status_t)OK);
2827
2828    CHECK_EQ((int)def.eDir,
2829            (int)(portIndex == kPortIndexOutput ? OMX_DirOutput : OMX_DirInput));
2830
2831    switch (def.eDomain) {
2832        case OMX_PortDomainVideo:
2833        {
2834            OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
2835            switch ((int)videoDef->eCompressionFormat) {
2836                case OMX_VIDEO_CodingUnused:
2837                {
2838                    CHECK(mIsEncoder ^ (portIndex == kPortIndexOutput));
2839                    notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW);
2840
2841                    notify->setInt32("stride", videoDef->nStride);
2842                    notify->setInt32("slice-height", videoDef->nSliceHeight);
2843                    notify->setInt32("color-format", videoDef->eColorFormat);
2844
2845
2846                    DescribeColorFormatParams describeParams;
2847                    InitOMXParams(&describeParams);
2848                    describeParams.eColorFormat = videoDef->eColorFormat;
2849                    describeParams.nFrameWidth = videoDef->nFrameWidth;
2850                    describeParams.nFrameHeight = videoDef->nFrameHeight;
2851                    describeParams.nStride = videoDef->nStride;
2852                    describeParams.nSliceHeight = videoDef->nSliceHeight;
2853
2854                    OMX_INDEXTYPE describeColorFormatIndex;
2855                    if (mOMX->getExtensionIndex(
2856                            mNode, "OMX.google.android.index.describeColorFormat",
2857                            &describeColorFormatIndex) ||
2858                        mOMX->getParameter(
2859                            mNode, describeColorFormatIndex,
2860                            &describeParams, sizeof(describeParams))) {
2861                        describeDefaultColorFormat(describeParams);
2862                    }
2863
2864                    if (describeParams.sMediaImage.mType != MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN) {
2865                        notify->setBuffer(
2866                                "image-data",
2867                                ABuffer::CreateAsCopy(
2868                                        &describeParams.sMediaImage,
2869                                        sizeof(describeParams.sMediaImage)));
2870                    }
2871
2872                    OMX_CONFIG_RECTTYPE rect;
2873                    InitOMXParams(&rect);
2874                    rect.nPortIndex = kPortIndexOutput;
2875
2876                    if (mOMX->getConfig(
2877                                mNode, OMX_IndexConfigCommonOutputCrop,
2878                                &rect, sizeof(rect)) != OK) {
2879                        rect.nLeft = 0;
2880                        rect.nTop = 0;
2881                        rect.nWidth = videoDef->nFrameWidth;
2882                        rect.nHeight = videoDef->nFrameHeight;
2883                    }
2884
2885                    CHECK_GE(rect.nLeft, 0);
2886                    CHECK_GE(rect.nTop, 0);
2887                    CHECK_GE(rect.nWidth, 0u);
2888                    CHECK_GE(rect.nHeight, 0u);
2889                    CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth);
2890                    CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight);
2891
2892                    notify->setRect(
2893                            "crop",
2894                            rect.nLeft,
2895                            rect.nTop,
2896                            rect.nLeft + rect.nWidth - 1,
2897                            rect.nTop + rect.nHeight - 1);
2898
2899                    break;
2900                }
2901
2902                case OMX_VIDEO_CodingVP8:
2903                case OMX_VIDEO_CodingVP9:
2904                {
2905                    OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type;
2906                    InitOMXParams(&vp8type);
2907                    vp8type.nPortIndex = kPortIndexOutput;
2908                    status_t err = mOMX->getParameter(
2909                            mNode,
2910                            (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
2911                            &vp8type,
2912                            sizeof(vp8type));
2913
2914                    if (err == OK) {
2915                        AString tsSchema = "none";
2916                        if (vp8type.eTemporalPattern
2917                                == OMX_VIDEO_VPXTemporalLayerPatternWebRTC) {
2918                            switch (vp8type.nTemporalLayerCount) {
2919                                case 1:
2920                                {
2921                                    tsSchema = "webrtc.vp8.1-layer";
2922                                    break;
2923                                }
2924                                case 2:
2925                                {
2926                                    tsSchema = "webrtc.vp8.2-layer";
2927                                    break;
2928                                }
2929                                case 3:
2930                                {
2931                                    tsSchema = "webrtc.vp8.3-layer";
2932                                    break;
2933                                }
2934                                default:
2935                                {
2936                                    break;
2937                                }
2938                            }
2939                        }
2940                        notify->setString("ts-schema", tsSchema);
2941                    }
2942                    // Fall through to set up mime.
2943                }
2944
2945                default:
2946                {
2947                    CHECK(mIsEncoder ^ (portIndex == kPortIndexInput));
2948                    AString mime;
2949                    if (GetMimeTypeForVideoCoding(
2950                        videoDef->eCompressionFormat, &mime) != OK) {
2951                        notify->setString("mime", "application/octet-stream");
2952                    } else {
2953                        notify->setString("mime", mime.c_str());
2954                    }
2955                    break;
2956                }
2957            }
2958
2959            notify->setInt32("width", videoDef->nFrameWidth);
2960            notify->setInt32("height", videoDef->nFrameHeight);
2961            break;
2962        }
2963
2964        case OMX_PortDomainAudio:
2965        {
2966            OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
2967
2968            switch ((int)audioDef->eEncoding) {
2969                case OMX_AUDIO_CodingPCM:
2970                {
2971                    OMX_AUDIO_PARAM_PCMMODETYPE params;
2972                    InitOMXParams(&params);
2973                    params.nPortIndex = portIndex;
2974
2975                    CHECK_EQ(mOMX->getParameter(
2976                                mNode, OMX_IndexParamAudioPcm,
2977                                &params, sizeof(params)),
2978                             (status_t)OK);
2979
2980                    CHECK_GT(params.nChannels, 0);
2981                    CHECK(params.nChannels == 1 || params.bInterleaved);
2982                    CHECK_EQ(params.nBitPerSample, 16u);
2983
2984                    CHECK_EQ((int)params.eNumData,
2985                             (int)OMX_NumericalDataSigned);
2986
2987                    CHECK_EQ((int)params.ePCMMode,
2988                             (int)OMX_AUDIO_PCMModeLinear);
2989
2990                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
2991                    notify->setInt32("channel-count", params.nChannels);
2992                    notify->setInt32("sample-rate", params.nSamplingRate);
2993
2994                    if (mChannelMaskPresent) {
2995                        notify->setInt32("channel-mask", mChannelMask);
2996                    }
2997                    break;
2998                }
2999
3000                case OMX_AUDIO_CodingAAC:
3001                {
3002                    OMX_AUDIO_PARAM_AACPROFILETYPE params;
3003                    InitOMXParams(&params);
3004                    params.nPortIndex = portIndex;
3005
3006                    CHECK_EQ(mOMX->getParameter(
3007                                mNode, OMX_IndexParamAudioAac,
3008                                &params, sizeof(params)),
3009                             (status_t)OK);
3010
3011                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
3012                    notify->setInt32("channel-count", params.nChannels);
3013                    notify->setInt32("sample-rate", params.nSampleRate);
3014                    break;
3015                }
3016
3017                case OMX_AUDIO_CodingAMR:
3018                {
3019                    OMX_AUDIO_PARAM_AMRTYPE params;
3020                    InitOMXParams(&params);
3021                    params.nPortIndex = portIndex;
3022
3023                    CHECK_EQ(mOMX->getParameter(
3024                                mNode, OMX_IndexParamAudioAmr,
3025                                &params, sizeof(params)),
3026                             (status_t)OK);
3027
3028                    notify->setInt32("channel-count", 1);
3029                    if (params.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0) {
3030                        notify->setString(
3031                                "mime", MEDIA_MIMETYPE_AUDIO_AMR_WB);
3032
3033                        notify->setInt32("sample-rate", 16000);
3034                    } else {
3035                        notify->setString(
3036                                "mime", MEDIA_MIMETYPE_AUDIO_AMR_NB);
3037
3038                        notify->setInt32("sample-rate", 8000);
3039                    }
3040                    break;
3041                }
3042
3043                case OMX_AUDIO_CodingFLAC:
3044                {
3045                    OMX_AUDIO_PARAM_FLACTYPE params;
3046                    InitOMXParams(&params);
3047                    params.nPortIndex = portIndex;
3048
3049                    CHECK_EQ(mOMX->getParameter(
3050                                mNode, OMX_IndexParamAudioFlac,
3051                                &params, sizeof(params)),
3052                             (status_t)OK);
3053
3054                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_FLAC);
3055                    notify->setInt32("channel-count", params.nChannels);
3056                    notify->setInt32("sample-rate", params.nSampleRate);
3057                    break;
3058                }
3059
3060                case OMX_AUDIO_CodingMP3:
3061                {
3062                    OMX_AUDIO_PARAM_MP3TYPE params;
3063                    InitOMXParams(&params);
3064                    params.nPortIndex = portIndex;
3065
3066                    CHECK_EQ(mOMX->getParameter(
3067                                mNode, OMX_IndexParamAudioMp3,
3068                                &params, sizeof(params)),
3069                             (status_t)OK);
3070
3071                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MPEG);
3072                    notify->setInt32("channel-count", params.nChannels);
3073                    notify->setInt32("sample-rate", params.nSampleRate);
3074                    break;
3075                }
3076
3077                case OMX_AUDIO_CodingVORBIS:
3078                {
3079                    OMX_AUDIO_PARAM_VORBISTYPE params;
3080                    InitOMXParams(&params);
3081                    params.nPortIndex = portIndex;
3082
3083                    CHECK_EQ(mOMX->getParameter(
3084                                mNode, OMX_IndexParamAudioVorbis,
3085                                &params, sizeof(params)),
3086                             (status_t)OK);
3087
3088                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_VORBIS);
3089                    notify->setInt32("channel-count", params.nChannels);
3090                    notify->setInt32("sample-rate", params.nSampleRate);
3091                    break;
3092                }
3093
3094                case OMX_AUDIO_CodingAndroidAC3:
3095                {
3096                    OMX_AUDIO_PARAM_ANDROID_AC3TYPE params;
3097                    InitOMXParams(&params);
3098                    params.nPortIndex = portIndex;
3099
3100                    CHECK_EQ((status_t)OK, mOMX->getParameter(
3101                            mNode,
3102                            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
3103                            &params,
3104                            sizeof(params)));
3105
3106                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AC3);
3107                    notify->setInt32("channel-count", params.nChannels);
3108                    notify->setInt32("sample-rate", params.nSampleRate);
3109                    break;
3110                }
3111
3112                case OMX_AUDIO_CodingAndroidOPUS:
3113                {
3114                    OMX_AUDIO_PARAM_ANDROID_OPUSTYPE params;
3115                    InitOMXParams(&params);
3116                    params.nPortIndex = portIndex;
3117
3118                    CHECK_EQ((status_t)OK, mOMX->getParameter(
3119                            mNode,
3120                            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus,
3121                            &params,
3122                            sizeof(params)));
3123
3124                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_OPUS);
3125                    notify->setInt32("channel-count", params.nChannels);
3126                    notify->setInt32("sample-rate", params.nSampleRate);
3127                    break;
3128                }
3129
3130                default:
3131                    ALOGE("UNKNOWN AUDIO CODING: %d\n", audioDef->eEncoding);
3132                    TRESPASS();
3133            }
3134            break;
3135        }
3136
3137        default:
3138            TRESPASS();
3139    }
3140
3141    return OK;
3142}
3143
3144void ACodec::sendFormatChange(const sp<AMessage> &reply) {
3145    sp<AMessage> notify = mNotify->dup();
3146    notify->setInt32("what", kWhatOutputFormatChanged);
3147
3148    CHECK_EQ(getPortFormat(kPortIndexOutput, notify), (status_t)OK);
3149
3150    AString mime;
3151    CHECK(notify->findString("mime", &mime));
3152
3153    int32_t left, top, right, bottom;
3154    if (mime == MEDIA_MIMETYPE_VIDEO_RAW &&
3155        mNativeWindow != NULL &&
3156        notify->findRect("crop", &left, &top, &right, &bottom)) {
3157        // notify renderer of the crop change
3158        // NOTE: native window uses extended right-bottom coordinate
3159        reply->setRect("crop", left, top, right + 1, bottom + 1);
3160    } else if (mime == MEDIA_MIMETYPE_AUDIO_RAW &&
3161               (mEncoderDelay || mEncoderPadding)) {
3162        int32_t channelCount;
3163        CHECK(notify->findInt32("channel-count", &channelCount));
3164        size_t frameSize = channelCount * sizeof(int16_t);
3165        if (mSkipCutBuffer != NULL) {
3166            size_t prevbufsize = mSkipCutBuffer->size();
3167            if (prevbufsize != 0) {
3168                ALOGW("Replacing SkipCutBuffer holding %d "
3169                      "bytes",
3170                      prevbufsize);
3171            }
3172        }
3173        mSkipCutBuffer = new SkipCutBuffer(
3174                mEncoderDelay * frameSize,
3175                mEncoderPadding * frameSize);
3176    }
3177
3178    notify->post();
3179
3180    mSentFormat = true;
3181}
3182
3183void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) {
3184    sp<AMessage> notify = mNotify->dup();
3185    notify->setInt32("what", CodecBase::kWhatError);
3186    notify->setInt32("omx-error", error);
3187    notify->setInt32("err", internalError);
3188    notify->post();
3189}
3190
3191status_t ACodec::pushBlankBuffersToNativeWindow() {
3192    status_t err = NO_ERROR;
3193    ANativeWindowBuffer* anb = NULL;
3194    int numBufs = 0;
3195    int minUndequeuedBufs = 0;
3196
3197    // We need to reconnect to the ANativeWindow as a CPU client to ensure that
3198    // no frames get dropped by SurfaceFlinger assuming that these are video
3199    // frames.
3200    err = native_window_api_disconnect(mNativeWindow.get(),
3201            NATIVE_WINDOW_API_MEDIA);
3202    if (err != NO_ERROR) {
3203        ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
3204                strerror(-err), -err);
3205        return err;
3206    }
3207
3208    err = native_window_api_connect(mNativeWindow.get(),
3209            NATIVE_WINDOW_API_CPU);
3210    if (err != NO_ERROR) {
3211        ALOGE("error pushing blank frames: api_connect failed: %s (%d)",
3212                strerror(-err), -err);
3213        return err;
3214    }
3215
3216    err = native_window_set_buffers_geometry(mNativeWindow.get(), 1, 1,
3217            HAL_PIXEL_FORMAT_RGBX_8888);
3218    if (err != NO_ERROR) {
3219        ALOGE("error pushing blank frames: set_buffers_geometry failed: %s (%d)",
3220                strerror(-err), -err);
3221        goto error;
3222    }
3223
3224    err = native_window_set_scaling_mode(mNativeWindow.get(),
3225                NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
3226    if (err != NO_ERROR) {
3227        ALOGE("error pushing blank_frames: set_scaling_mode failed: %s (%d)",
3228              strerror(-err), -err);
3229        goto error;
3230    }
3231
3232    err = native_window_set_usage(mNativeWindow.get(),
3233            GRALLOC_USAGE_SW_WRITE_OFTEN);
3234    if (err != NO_ERROR) {
3235        ALOGE("error pushing blank frames: set_usage failed: %s (%d)",
3236                strerror(-err), -err);
3237        goto error;
3238    }
3239
3240    err = mNativeWindow->query(mNativeWindow.get(),
3241            NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs);
3242    if (err != NO_ERROR) {
3243        ALOGE("error pushing blank frames: MIN_UNDEQUEUED_BUFFERS query "
3244                "failed: %s (%d)", strerror(-err), -err);
3245        goto error;
3246    }
3247
3248    numBufs = minUndequeuedBufs + 1;
3249    err = native_window_set_buffer_count(mNativeWindow.get(), numBufs);
3250    if (err != NO_ERROR) {
3251        ALOGE("error pushing blank frames: set_buffer_count failed: %s (%d)",
3252                strerror(-err), -err);
3253        goto error;
3254    }
3255
3256    // We  push numBufs + 1 buffers to ensure that we've drawn into the same
3257    // buffer twice.  This should guarantee that the buffer has been displayed
3258    // on the screen and then been replaced, so an previous video frames are
3259    // guaranteed NOT to be currently displayed.
3260    for (int i = 0; i < numBufs + 1; i++) {
3261        int fenceFd = -1;
3262        err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &anb);
3263        if (err != NO_ERROR) {
3264            ALOGE("error pushing blank frames: dequeueBuffer failed: %s (%d)",
3265                    strerror(-err), -err);
3266            goto error;
3267        }
3268
3269        sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
3270
3271        // Fill the buffer with the a 1x1 checkerboard pattern ;)
3272        uint32_t* img = NULL;
3273        err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
3274        if (err != NO_ERROR) {
3275            ALOGE("error pushing blank frames: lock failed: %s (%d)",
3276                    strerror(-err), -err);
3277            goto error;
3278        }
3279
3280        *img = 0;
3281
3282        err = buf->unlock();
3283        if (err != NO_ERROR) {
3284            ALOGE("error pushing blank frames: unlock failed: %s (%d)",
3285                    strerror(-err), -err);
3286            goto error;
3287        }
3288
3289        err = mNativeWindow->queueBuffer(mNativeWindow.get(),
3290                buf->getNativeBuffer(), -1);
3291        if (err != NO_ERROR) {
3292            ALOGE("error pushing blank frames: queueBuffer failed: %s (%d)",
3293                    strerror(-err), -err);
3294            goto error;
3295        }
3296
3297        anb = NULL;
3298    }
3299
3300error:
3301
3302    if (err != NO_ERROR) {
3303        // Clean up after an error.
3304        if (anb != NULL) {
3305            mNativeWindow->cancelBuffer(mNativeWindow.get(), anb, -1);
3306        }
3307
3308        native_window_api_disconnect(mNativeWindow.get(),
3309                NATIVE_WINDOW_API_CPU);
3310        native_window_api_connect(mNativeWindow.get(),
3311                NATIVE_WINDOW_API_MEDIA);
3312
3313        return err;
3314    } else {
3315        // Clean up after success.
3316        err = native_window_api_disconnect(mNativeWindow.get(),
3317                NATIVE_WINDOW_API_CPU);
3318        if (err != NO_ERROR) {
3319            ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
3320                    strerror(-err), -err);
3321            return err;
3322        }
3323
3324        err = native_window_api_connect(mNativeWindow.get(),
3325                NATIVE_WINDOW_API_MEDIA);
3326        if (err != NO_ERROR) {
3327            ALOGE("error pushing blank frames: api_connect failed: %s (%d)",
3328                    strerror(-err), -err);
3329            return err;
3330        }
3331
3332        return NO_ERROR;
3333    }
3334}
3335
3336////////////////////////////////////////////////////////////////////////////////
3337
3338ACodec::PortDescription::PortDescription() {
3339}
3340
3341status_t ACodec::requestIDRFrame() {
3342    if (!mIsEncoder) {
3343        return ERROR_UNSUPPORTED;
3344    }
3345
3346    OMX_CONFIG_INTRAREFRESHVOPTYPE params;
3347    InitOMXParams(&params);
3348
3349    params.nPortIndex = kPortIndexOutput;
3350    params.IntraRefreshVOP = OMX_TRUE;
3351
3352    return mOMX->setConfig(
3353            mNode,
3354            OMX_IndexConfigVideoIntraVOPRefresh,
3355            &params,
3356            sizeof(params));
3357}
3358
3359void ACodec::PortDescription::addBuffer(
3360        IOMX::buffer_id id, const sp<ABuffer> &buffer) {
3361    mBufferIDs.push_back(id);
3362    mBuffers.push_back(buffer);
3363}
3364
3365size_t ACodec::PortDescription::countBuffers() {
3366    return mBufferIDs.size();
3367}
3368
3369IOMX::buffer_id ACodec::PortDescription::bufferIDAt(size_t index) const {
3370    return mBufferIDs.itemAt(index);
3371}
3372
3373sp<ABuffer> ACodec::PortDescription::bufferAt(size_t index) const {
3374    return mBuffers.itemAt(index);
3375}
3376
3377////////////////////////////////////////////////////////////////////////////////
3378
3379ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
3380    : AState(parentState),
3381      mCodec(codec) {
3382}
3383
3384ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(
3385        OMX_U32 /* portIndex */) {
3386    return KEEP_BUFFERS;
3387}
3388
3389bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) {
3390    switch (msg->what()) {
3391        case kWhatInputBufferFilled:
3392        {
3393            onInputBufferFilled(msg);
3394            break;
3395        }
3396
3397        case kWhatOutputBufferDrained:
3398        {
3399            onOutputBufferDrained(msg);
3400            break;
3401        }
3402
3403        case ACodec::kWhatOMXMessage:
3404        {
3405            return onOMXMessage(msg);
3406        }
3407
3408        case ACodec::kWhatCreateInputSurface:
3409        case ACodec::kWhatSignalEndOfInputStream:
3410        {
3411            ALOGE("Message 0x%x was not handled", msg->what());
3412            mCodec->signalError(OMX_ErrorUndefined, INVALID_OPERATION);
3413            return true;
3414        }
3415
3416        case ACodec::kWhatOMXDied:
3417        {
3418            ALOGE("OMX/mediaserver died, signalling error!");
3419            mCodec->signalError(OMX_ErrorResourcesLost, DEAD_OBJECT);
3420            break;
3421        }
3422
3423        default:
3424            return false;
3425    }
3426
3427    return true;
3428}
3429
3430bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) {
3431    int32_t type;
3432    CHECK(msg->findInt32("type", &type));
3433
3434    // there is a possibility that this is an outstanding message for a
3435    // codec that we have already destroyed
3436    if (mCodec->mNode == NULL) {
3437        ALOGI("ignoring message as already freed component: %s",
3438                msg->debugString().c_str());
3439        return true;
3440    }
3441
3442    IOMX::node_id nodeID;
3443    CHECK(msg->findInt32("node", (int32_t*)&nodeID));
3444    CHECK_EQ(nodeID, mCodec->mNode);
3445
3446    switch (type) {
3447        case omx_message::EVENT:
3448        {
3449            int32_t event, data1, data2;
3450            CHECK(msg->findInt32("event", &event));
3451            CHECK(msg->findInt32("data1", &data1));
3452            CHECK(msg->findInt32("data2", &data2));
3453
3454            if (event == OMX_EventCmdComplete
3455                    && data1 == OMX_CommandFlush
3456                    && data2 == (int32_t)OMX_ALL) {
3457                // Use of this notification is not consistent across
3458                // implementations. We'll drop this notification and rely
3459                // on flush-complete notifications on the individual port
3460                // indices instead.
3461
3462                return true;
3463            }
3464
3465            return onOMXEvent(
3466                    static_cast<OMX_EVENTTYPE>(event),
3467                    static_cast<OMX_U32>(data1),
3468                    static_cast<OMX_U32>(data2));
3469        }
3470
3471        case omx_message::EMPTY_BUFFER_DONE:
3472        {
3473            IOMX::buffer_id bufferID;
3474            CHECK(msg->findInt32("buffer", (int32_t*)&bufferID));
3475
3476            return onOMXEmptyBufferDone(bufferID);
3477        }
3478
3479        case omx_message::FILL_BUFFER_DONE:
3480        {
3481            IOMX::buffer_id bufferID;
3482            CHECK(msg->findInt32("buffer", (int32_t*)&bufferID));
3483
3484            int32_t rangeOffset, rangeLength, flags;
3485            int64_t timeUs;
3486
3487            CHECK(msg->findInt32("range_offset", &rangeOffset));
3488            CHECK(msg->findInt32("range_length", &rangeLength));
3489            CHECK(msg->findInt32("flags", &flags));
3490            CHECK(msg->findInt64("timestamp", &timeUs));
3491
3492            return onOMXFillBufferDone(
3493                    bufferID,
3494                    (size_t)rangeOffset, (size_t)rangeLength,
3495                    (OMX_U32)flags,
3496                    timeUs);
3497        }
3498
3499        default:
3500            TRESPASS();
3501            break;
3502    }
3503}
3504
3505bool ACodec::BaseState::onOMXEvent(
3506        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3507    if (event != OMX_EventError) {
3508        ALOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)",
3509             mCodec->mComponentName.c_str(), event, data1, data2);
3510
3511        return false;
3512    }
3513
3514    ALOGE("[%s] ERROR(0x%08lx)", mCodec->mComponentName.c_str(), data1);
3515
3516    mCodec->signalError((OMX_ERRORTYPE)data1);
3517
3518    return true;
3519}
3520
3521bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) {
3522    ALOGV("[%s] onOMXEmptyBufferDone %p",
3523         mCodec->mComponentName.c_str(), bufferID);
3524
3525    BufferInfo *info =
3526        mCodec->findBufferByID(kPortIndexInput, bufferID);
3527
3528    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
3529    info->mStatus = BufferInfo::OWNED_BY_US;
3530
3531    const sp<AMessage> &bufferMeta = info->mData->meta();
3532    void *mediaBuffer;
3533    if (bufferMeta->findPointer("mediaBuffer", &mediaBuffer)
3534            && mediaBuffer != NULL) {
3535        // We're in "store-metadata-in-buffers" mode, the underlying
3536        // OMX component had access to data that's implicitly refcounted
3537        // by this "mediaBuffer" object. Now that the OMX component has
3538        // told us that it's done with the input buffer, we can decrement
3539        // the mediaBuffer's reference count.
3540
3541        ALOGV("releasing mbuf %p", mediaBuffer);
3542
3543        ((MediaBuffer *)mediaBuffer)->release();
3544        mediaBuffer = NULL;
3545
3546        bufferMeta->setPointer("mediaBuffer", NULL);
3547    }
3548
3549    PortMode mode = getPortMode(kPortIndexInput);
3550
3551    switch (mode) {
3552        case KEEP_BUFFERS:
3553            break;
3554
3555        case RESUBMIT_BUFFERS:
3556            postFillThisBuffer(info);
3557            break;
3558
3559        default:
3560        {
3561            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
3562            TRESPASS();  // Not currently used
3563            break;
3564        }
3565    }
3566
3567    return true;
3568}
3569
3570void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) {
3571    if (mCodec->mPortEOS[kPortIndexInput]) {
3572        return;
3573    }
3574
3575    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
3576
3577    sp<AMessage> notify = mCodec->mNotify->dup();
3578    notify->setInt32("what", CodecBase::kWhatFillThisBuffer);
3579    notify->setInt32("buffer-id", info->mBufferID);
3580
3581    info->mData->meta()->clear();
3582    notify->setBuffer("buffer", info->mData);
3583
3584    sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id());
3585    reply->setInt32("buffer-id", info->mBufferID);
3586
3587    notify->setMessage("reply", reply);
3588
3589    notify->post();
3590
3591    info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
3592}
3593
3594void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
3595    IOMX::buffer_id bufferID;
3596    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
3597    sp<ABuffer> buffer;
3598    int32_t err = OK;
3599    bool eos = false;
3600    PortMode mode = getPortMode(kPortIndexInput);
3601
3602    if (!msg->findBuffer("buffer", &buffer)) {
3603        /* these are unfilled buffers returned by client */
3604        CHECK(msg->findInt32("err", &err));
3605
3606        if (err == OK) {
3607            /* buffers with no errors are returned on MediaCodec.flush */
3608            mode = KEEP_BUFFERS;
3609        } else {
3610            ALOGV("[%s] saw error %d instead of an input buffer",
3611                 mCodec->mComponentName.c_str(), err);
3612            eos = true;
3613        }
3614
3615        buffer.clear();
3616    }
3617
3618    int32_t tmp;
3619    if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) {
3620        eos = true;
3621        err = ERROR_END_OF_STREAM;
3622    }
3623
3624    BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
3625    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM);
3626
3627    info->mStatus = BufferInfo::OWNED_BY_US;
3628
3629    switch (mode) {
3630        case KEEP_BUFFERS:
3631        {
3632            if (eos) {
3633                if (!mCodec->mPortEOS[kPortIndexInput]) {
3634                    mCodec->mPortEOS[kPortIndexInput] = true;
3635                    mCodec->mInputEOSResult = err;
3636                }
3637            }
3638            break;
3639        }
3640
3641        case RESUBMIT_BUFFERS:
3642        {
3643            if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) {
3644                int64_t timeUs;
3645                CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
3646
3647                OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
3648
3649                int32_t isCSD;
3650                if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) {
3651                    flags |= OMX_BUFFERFLAG_CODECCONFIG;
3652                }
3653
3654                if (eos) {
3655                    flags |= OMX_BUFFERFLAG_EOS;
3656                }
3657
3658                if (buffer != info->mData) {
3659                    ALOGV("[%s] Needs to copy input data for buffer %p. (%p != %p)",
3660                         mCodec->mComponentName.c_str(),
3661                         bufferID,
3662                         buffer.get(), info->mData.get());
3663
3664                    CHECK_LE(buffer->size(), info->mData->capacity());
3665                    memcpy(info->mData->data(), buffer->data(), buffer->size());
3666                }
3667
3668                if (flags & OMX_BUFFERFLAG_CODECCONFIG) {
3669                    ALOGV("[%s] calling emptyBuffer %p w/ codec specific data",
3670                         mCodec->mComponentName.c_str(), bufferID);
3671                } else if (flags & OMX_BUFFERFLAG_EOS) {
3672                    ALOGV("[%s] calling emptyBuffer %p w/ EOS",
3673                         mCodec->mComponentName.c_str(), bufferID);
3674                } else {
3675#if TRACK_BUFFER_TIMING
3676                    ALOGI("[%s] calling emptyBuffer %p w/ time %lld us",
3677                         mCodec->mComponentName.c_str(), bufferID, timeUs);
3678#else
3679                    ALOGV("[%s] calling emptyBuffer %p w/ time %lld us",
3680                         mCodec->mComponentName.c_str(), bufferID, timeUs);
3681#endif
3682                }
3683
3684#if TRACK_BUFFER_TIMING
3685                ACodec::BufferStats stats;
3686                stats.mEmptyBufferTimeUs = ALooper::GetNowUs();
3687                stats.mFillBufferDoneTimeUs = -1ll;
3688                mCodec->mBufferStats.add(timeUs, stats);
3689#endif
3690
3691                if (mCodec->mStoreMetaDataInOutputBuffers) {
3692                    // try to submit an output buffer for each input buffer
3693                    PortMode outputMode = getPortMode(kPortIndexOutput);
3694
3695                    ALOGV("MetaDataBuffersToSubmit=%u portMode=%s",
3696                            mCodec->mMetaDataBuffersToSubmit,
3697                            (outputMode == FREE_BUFFERS ? "FREE" :
3698                             outputMode == KEEP_BUFFERS ? "KEEP" : "RESUBMIT"));
3699                    if (outputMode == RESUBMIT_BUFFERS) {
3700                        CHECK_EQ(mCodec->submitOutputMetaDataBuffer(),
3701                                (status_t)OK);
3702                    }
3703                }
3704
3705                CHECK_EQ(mCodec->mOMX->emptyBuffer(
3706                            mCodec->mNode,
3707                            bufferID,
3708                            0,
3709                            buffer->size(),
3710                            flags,
3711                            timeUs),
3712                         (status_t)OK);
3713
3714                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
3715
3716                if (!eos) {
3717                    getMoreInputDataIfPossible();
3718                } else {
3719                    ALOGV("[%s] Signalled EOS on the input port",
3720                         mCodec->mComponentName.c_str());
3721
3722                    mCodec->mPortEOS[kPortIndexInput] = true;
3723                    mCodec->mInputEOSResult = err;
3724                }
3725            } else if (!mCodec->mPortEOS[kPortIndexInput]) {
3726                if (err != ERROR_END_OF_STREAM) {
3727                    ALOGV("[%s] Signalling EOS on the input port "
3728                         "due to error %d",
3729                         mCodec->mComponentName.c_str(), err);
3730                } else {
3731                    ALOGV("[%s] Signalling EOS on the input port",
3732                         mCodec->mComponentName.c_str());
3733                }
3734
3735                ALOGV("[%s] calling emptyBuffer %p signalling EOS",
3736                     mCodec->mComponentName.c_str(), bufferID);
3737
3738                CHECK_EQ(mCodec->mOMX->emptyBuffer(
3739                            mCodec->mNode,
3740                            bufferID,
3741                            0,
3742                            0,
3743                            OMX_BUFFERFLAG_EOS,
3744                            0),
3745                         (status_t)OK);
3746
3747                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
3748
3749                mCodec->mPortEOS[kPortIndexInput] = true;
3750                mCodec->mInputEOSResult = err;
3751            }
3752            break;
3753        }
3754
3755        default:
3756            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
3757            break;
3758    }
3759}
3760
3761void ACodec::BaseState::getMoreInputDataIfPossible() {
3762    if (mCodec->mPortEOS[kPortIndexInput]) {
3763        return;
3764    }
3765
3766    BufferInfo *eligible = NULL;
3767
3768    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
3769        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
3770
3771#if 0
3772        if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) {
3773            // There's already a "read" pending.
3774            return;
3775        }
3776#endif
3777
3778        if (info->mStatus == BufferInfo::OWNED_BY_US) {
3779            eligible = info;
3780        }
3781    }
3782
3783    if (eligible == NULL) {
3784        return;
3785    }
3786
3787    postFillThisBuffer(eligible);
3788}
3789
3790bool ACodec::BaseState::onOMXFillBufferDone(
3791        IOMX::buffer_id bufferID,
3792        size_t rangeOffset, size_t rangeLength,
3793        OMX_U32 flags,
3794        int64_t timeUs) {
3795    ALOGV("[%s] onOMXFillBufferDone %u time %" PRId64 " us, flags = 0x%08x",
3796         mCodec->mComponentName.c_str(), bufferID, timeUs, flags);
3797
3798    ssize_t index;
3799
3800#if TRACK_BUFFER_TIMING
3801    index = mCodec->mBufferStats.indexOfKey(timeUs);
3802    if (index >= 0) {
3803        ACodec::BufferStats *stats = &mCodec->mBufferStats.editValueAt(index);
3804        stats->mFillBufferDoneTimeUs = ALooper::GetNowUs();
3805
3806        ALOGI("frame PTS %lld: %lld",
3807                timeUs,
3808                stats->mFillBufferDoneTimeUs - stats->mEmptyBufferTimeUs);
3809
3810        mCodec->mBufferStats.removeItemsAt(index);
3811        stats = NULL;
3812    }
3813#endif
3814
3815    BufferInfo *info =
3816        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
3817
3818    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
3819
3820    info->mDequeuedAt = ++mCodec->mDequeueCounter;
3821    info->mStatus = BufferInfo::OWNED_BY_US;
3822
3823    PortMode mode = getPortMode(kPortIndexOutput);
3824
3825    switch (mode) {
3826        case KEEP_BUFFERS:
3827            break;
3828
3829        case RESUBMIT_BUFFERS:
3830        {
3831            if (rangeLength == 0 && !(flags & OMX_BUFFERFLAG_EOS)) {
3832                ALOGV("[%s] calling fillBuffer %u",
3833                     mCodec->mComponentName.c_str(), info->mBufferID);
3834
3835                CHECK_EQ(mCodec->mOMX->fillBuffer(
3836                            mCodec->mNode, info->mBufferID),
3837                         (status_t)OK);
3838
3839                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
3840                break;
3841            }
3842
3843            sp<AMessage> reply =
3844                new AMessage(kWhatOutputBufferDrained, mCodec->id());
3845
3846            if (!mCodec->mSentFormat && rangeLength > 0) {
3847                mCodec->sendFormatChange(reply);
3848            }
3849
3850            if (mCodec->mUseMetadataOnEncoderOutput) {
3851                native_handle_t* handle =
3852                        *(native_handle_t**)(info->mData->data() + 4);
3853                info->mData->meta()->setPointer("handle", handle);
3854                info->mData->meta()->setInt32("rangeOffset", rangeOffset);
3855                info->mData->meta()->setInt32("rangeLength", rangeLength);
3856            } else {
3857                info->mData->setRange(rangeOffset, rangeLength);
3858            }
3859#if 0
3860            if (mCodec->mNativeWindow == NULL) {
3861                if (IsIDR(info->mData)) {
3862                    ALOGI("IDR frame");
3863                }
3864            }
3865#endif
3866
3867            if (mCodec->mSkipCutBuffer != NULL) {
3868                mCodec->mSkipCutBuffer->submit(info->mData);
3869            }
3870            info->mData->meta()->setInt64("timeUs", timeUs);
3871
3872            sp<AMessage> notify = mCodec->mNotify->dup();
3873            notify->setInt32("what", CodecBase::kWhatDrainThisBuffer);
3874            notify->setInt32("buffer-id", info->mBufferID);
3875            notify->setBuffer("buffer", info->mData);
3876            notify->setInt32("flags", flags);
3877
3878            reply->setInt32("buffer-id", info->mBufferID);
3879
3880            notify->setMessage("reply", reply);
3881
3882            notify->post();
3883
3884            info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;
3885
3886            if (flags & OMX_BUFFERFLAG_EOS) {
3887                ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str());
3888
3889                sp<AMessage> notify = mCodec->mNotify->dup();
3890                notify->setInt32("what", CodecBase::kWhatEOS);
3891                notify->setInt32("err", mCodec->mInputEOSResult);
3892                notify->post();
3893
3894                mCodec->mPortEOS[kPortIndexOutput] = true;
3895            }
3896            break;
3897        }
3898
3899        default:
3900        {
3901            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
3902
3903            CHECK_EQ((status_t)OK,
3904                     mCodec->freeBuffer(kPortIndexOutput, index));
3905            break;
3906        }
3907    }
3908
3909    return true;
3910}
3911
3912void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
3913    IOMX::buffer_id bufferID;
3914    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
3915    ssize_t index;
3916    BufferInfo *info =
3917        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
3918    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
3919
3920    android_native_rect_t crop;
3921    if (msg->findRect("crop",
3922            &crop.left, &crop.top, &crop.right, &crop.bottom)) {
3923        CHECK_EQ(0, native_window_set_crop(
3924                mCodec->mNativeWindow.get(), &crop));
3925    }
3926
3927    int32_t render;
3928    if (mCodec->mNativeWindow != NULL
3929            && msg->findInt32("render", &render) && render != 0
3930            && info->mData != NULL && info->mData->size() != 0) {
3931        ATRACE_NAME("render");
3932        // The client wants this buffer to be rendered.
3933
3934        int64_t timestampNs = 0;
3935        if (!msg->findInt64("timestampNs", &timestampNs)) {
3936            // TODO: it seems like we should use the timestamp
3937            // in the (media)buffer as it potentially came from
3938            // an input surface, but we did not propagate it prior to
3939            // API 20.  Perhaps check for target SDK version.
3940#if 0
3941            if (info->mData->meta()->findInt64("timeUs", &timestampNs)) {
3942                ALOGV("using buffer PTS of %" PRId64, timestampNs);
3943                timestampNs *= 1000;
3944            }
3945#endif
3946        }
3947
3948        status_t err;
3949        err = native_window_set_buffers_timestamp(mCodec->mNativeWindow.get(), timestampNs);
3950        if (err != OK) {
3951            ALOGW("failed to set buffer timestamp: %d", err);
3952        }
3953
3954        if ((err = mCodec->mNativeWindow->queueBuffer(
3955                    mCodec->mNativeWindow.get(),
3956                    info->mGraphicBuffer.get(), -1)) == OK) {
3957            info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
3958        } else {
3959            mCodec->signalError(OMX_ErrorUndefined, err);
3960            info->mStatus = BufferInfo::OWNED_BY_US;
3961        }
3962    } else {
3963        if (mCodec->mNativeWindow != NULL &&
3964            (info->mData == NULL || info->mData->size() != 0)) {
3965            ATRACE_NAME("frame-drop");
3966        }
3967        info->mStatus = BufferInfo::OWNED_BY_US;
3968    }
3969
3970    PortMode mode = getPortMode(kPortIndexOutput);
3971
3972    switch (mode) {
3973        case KEEP_BUFFERS:
3974        {
3975            // XXX fishy, revisit!!! What about the FREE_BUFFERS case below?
3976
3977            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
3978                // We cannot resubmit the buffer we just rendered, dequeue
3979                // the spare instead.
3980
3981                info = mCodec->dequeueBufferFromNativeWindow();
3982            }
3983            break;
3984        }
3985
3986        case RESUBMIT_BUFFERS:
3987        {
3988            if (!mCodec->mPortEOS[kPortIndexOutput]) {
3989                if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
3990                    // We cannot resubmit the buffer we just rendered, dequeue
3991                    // the spare instead.
3992
3993                    info = mCodec->dequeueBufferFromNativeWindow();
3994                }
3995
3996                if (info != NULL) {
3997                    ALOGV("[%s] calling fillBuffer %u",
3998                         mCodec->mComponentName.c_str(), info->mBufferID);
3999
4000                    CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
4001                             (status_t)OK);
4002
4003                    info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4004                }
4005            }
4006            break;
4007        }
4008
4009        default:
4010        {
4011            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
4012
4013            CHECK_EQ((status_t)OK,
4014                     mCodec->freeBuffer(kPortIndexOutput, index));
4015            break;
4016        }
4017    }
4018}
4019
4020////////////////////////////////////////////////////////////////////////////////
4021
4022ACodec::UninitializedState::UninitializedState(ACodec *codec)
4023    : BaseState(codec) {
4024}
4025
4026void ACodec::UninitializedState::stateEntered() {
4027    ALOGV("Now uninitialized");
4028
4029    if (mDeathNotifier != NULL) {
4030        mCodec->mOMX->asBinder()->unlinkToDeath(mDeathNotifier);
4031        mDeathNotifier.clear();
4032    }
4033
4034    mCodec->mNativeWindow.clear();
4035    mCodec->mNode = NULL;
4036    mCodec->mOMX.clear();
4037    mCodec->mQuirks = 0;
4038    mCodec->mFlags = 0;
4039    mCodec->mUseMetadataOnEncoderOutput = 0;
4040    mCodec->mComponentName.clear();
4041}
4042
4043bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
4044    bool handled = false;
4045
4046    switch (msg->what()) {
4047        case ACodec::kWhatSetup:
4048        {
4049            onSetup(msg);
4050
4051            handled = true;
4052            break;
4053        }
4054
4055        case ACodec::kWhatAllocateComponent:
4056        {
4057            onAllocateComponent(msg);
4058            handled = true;
4059            break;
4060        }
4061
4062        case ACodec::kWhatShutdown:
4063        {
4064            int32_t keepComponentAllocated;
4065            CHECK(msg->findInt32(
4066                        "keepComponentAllocated", &keepComponentAllocated));
4067            ALOGW_IF(keepComponentAllocated,
4068                     "cannot keep component allocated on shutdown in Uninitialized state");
4069
4070            sp<AMessage> notify = mCodec->mNotify->dup();
4071            notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
4072            notify->post();
4073
4074            handled = true;
4075            break;
4076        }
4077
4078        case ACodec::kWhatFlush:
4079        {
4080            sp<AMessage> notify = mCodec->mNotify->dup();
4081            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
4082            notify->post();
4083
4084            handled = true;
4085            break;
4086        }
4087
4088        default:
4089            return BaseState::onMessageReceived(msg);
4090    }
4091
4092    return handled;
4093}
4094
4095void ACodec::UninitializedState::onSetup(
4096        const sp<AMessage> &msg) {
4097    if (onAllocateComponent(msg)
4098            && mCodec->mLoadedState->onConfigureComponent(msg)) {
4099        mCodec->mLoadedState->onStart();
4100    }
4101}
4102
4103bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
4104    ALOGV("onAllocateComponent");
4105
4106    CHECK(mCodec->mNode == NULL);
4107
4108    OMXClient client;
4109    CHECK_EQ(client.connect(), (status_t)OK);
4110
4111    sp<IOMX> omx = client.interface();
4112
4113    sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec->id());
4114
4115    mDeathNotifier = new DeathNotifier(notify);
4116    if (omx->asBinder()->linkToDeath(mDeathNotifier) != OK) {
4117        // This was a local binder, if it dies so do we, we won't care
4118        // about any notifications in the afterlife.
4119        mDeathNotifier.clear();
4120    }
4121
4122    Vector<OMXCodec::CodecNameAndQuirks> matchingCodecs;
4123
4124    AString mime;
4125
4126    AString componentName;
4127    uint32_t quirks = 0;
4128    int32_t encoder = false;
4129    if (msg->findString("componentName", &componentName)) {
4130        ssize_t index = matchingCodecs.add();
4131        OMXCodec::CodecNameAndQuirks *entry = &matchingCodecs.editItemAt(index);
4132        entry->mName = String8(componentName.c_str());
4133
4134        if (!OMXCodec::findCodecQuirks(
4135                    componentName.c_str(), &entry->mQuirks)) {
4136            entry->mQuirks = 0;
4137        }
4138    } else {
4139        CHECK(msg->findString("mime", &mime));
4140
4141        if (!msg->findInt32("encoder", &encoder)) {
4142            encoder = false;
4143        }
4144
4145        OMXCodec::findMatchingCodecs(
4146                mime.c_str(),
4147                encoder, // createEncoder
4148                NULL,  // matchComponentName
4149                0,     // flags
4150                &matchingCodecs);
4151    }
4152
4153    sp<CodecObserver> observer = new CodecObserver;
4154    IOMX::node_id node = NULL;
4155
4156    for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
4157            ++matchIndex) {
4158        componentName = matchingCodecs.itemAt(matchIndex).mName.string();
4159        quirks = matchingCodecs.itemAt(matchIndex).mQuirks;
4160
4161        pid_t tid = androidGetTid();
4162        int prevPriority = androidGetThreadPriority(tid);
4163        androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
4164        status_t err = omx->allocateNode(componentName.c_str(), observer, &node);
4165        androidSetThreadPriority(tid, prevPriority);
4166
4167        if (err == OK) {
4168            break;
4169        } else {
4170            ALOGW("Allocating component '%s' failed, try next one.", componentName.c_str());
4171        }
4172
4173        node = NULL;
4174    }
4175
4176    if (node == NULL) {
4177        if (!mime.empty()) {
4178            ALOGE("Unable to instantiate a %scoder for type '%s'.",
4179                    encoder ? "en" : "de", mime.c_str());
4180        } else {
4181            ALOGE("Unable to instantiate codec '%s'.", componentName.c_str());
4182        }
4183
4184        mCodec->signalError(OMX_ErrorComponentNotFound);
4185        return false;
4186    }
4187
4188    notify = new AMessage(kWhatOMXMessage, mCodec->id());
4189    observer->setNotificationMessage(notify);
4190
4191    mCodec->mComponentName = componentName;
4192    mCodec->mFlags = 0;
4193
4194    if (componentName.endsWith(".secure")) {
4195        mCodec->mFlags |= kFlagIsSecure;
4196        mCodec->mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
4197    }
4198
4199    mCodec->mQuirks = quirks;
4200    mCodec->mOMX = omx;
4201    mCodec->mNode = node;
4202
4203    {
4204        sp<AMessage> notify = mCodec->mNotify->dup();
4205        notify->setInt32("what", CodecBase::kWhatComponentAllocated);
4206        notify->setString("componentName", mCodec->mComponentName.c_str());
4207        notify->post();
4208    }
4209
4210    mCodec->changeState(mCodec->mLoadedState);
4211
4212    return true;
4213}
4214
4215////////////////////////////////////////////////////////////////////////////////
4216
4217ACodec::LoadedState::LoadedState(ACodec *codec)
4218    : BaseState(codec) {
4219}
4220
4221void ACodec::LoadedState::stateEntered() {
4222    ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
4223
4224    mCodec->mPortEOS[kPortIndexInput] =
4225        mCodec->mPortEOS[kPortIndexOutput] = false;
4226
4227    mCodec->mInputEOSResult = OK;
4228
4229    mCodec->mDequeueCounter = 0;
4230    mCodec->mMetaDataBuffersToSubmit = 0;
4231    mCodec->mRepeatFrameDelayUs = -1ll;
4232    mCodec->mInputFormat.clear();
4233    mCodec->mOutputFormat.clear();
4234
4235    if (mCodec->mShutdownInProgress) {
4236        bool keepComponentAllocated = mCodec->mKeepComponentAllocated;
4237
4238        mCodec->mShutdownInProgress = false;
4239        mCodec->mKeepComponentAllocated = false;
4240
4241        onShutdown(keepComponentAllocated);
4242    }
4243    mCodec->mExplicitShutdown = false;
4244}
4245
4246void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) {
4247    if (!keepComponentAllocated) {
4248        CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
4249
4250        mCodec->changeState(mCodec->mUninitializedState);
4251    }
4252
4253    if (mCodec->mExplicitShutdown) {
4254        sp<AMessage> notify = mCodec->mNotify->dup();
4255        notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
4256        notify->post();
4257        mCodec->mExplicitShutdown = false;
4258    }
4259}
4260
4261bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) {
4262    bool handled = false;
4263
4264    switch (msg->what()) {
4265        case ACodec::kWhatConfigureComponent:
4266        {
4267            onConfigureComponent(msg);
4268            handled = true;
4269            break;
4270        }
4271
4272        case ACodec::kWhatCreateInputSurface:
4273        {
4274            onCreateInputSurface(msg);
4275            handled = true;
4276            break;
4277        }
4278
4279        case ACodec::kWhatStart:
4280        {
4281            onStart();
4282            handled = true;
4283            break;
4284        }
4285
4286        case ACodec::kWhatShutdown:
4287        {
4288            int32_t keepComponentAllocated;
4289            CHECK(msg->findInt32(
4290                        "keepComponentAllocated", &keepComponentAllocated));
4291
4292            mCodec->mExplicitShutdown = true;
4293            onShutdown(keepComponentAllocated);
4294
4295            handled = true;
4296            break;
4297        }
4298
4299        case ACodec::kWhatFlush:
4300        {
4301            sp<AMessage> notify = mCodec->mNotify->dup();
4302            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
4303            notify->post();
4304
4305            handled = true;
4306            break;
4307        }
4308
4309        default:
4310            return BaseState::onMessageReceived(msg);
4311    }
4312
4313    return handled;
4314}
4315
4316bool ACodec::LoadedState::onConfigureComponent(
4317        const sp<AMessage> &msg) {
4318    ALOGV("onConfigureComponent");
4319
4320    CHECK(mCodec->mNode != NULL);
4321
4322    AString mime;
4323    CHECK(msg->findString("mime", &mime));
4324
4325    status_t err = mCodec->configureCodec(mime.c_str(), msg);
4326
4327    if (err != OK) {
4328        ALOGE("[%s] configureCodec returning error %d",
4329              mCodec->mComponentName.c_str(), err);
4330
4331        mCodec->signalError(OMX_ErrorUndefined, err);
4332        return false;
4333    }
4334
4335    sp<RefBase> obj;
4336    if (msg->findObject("native-window", &obj)
4337            && strncmp("OMX.google.", mCodec->mComponentName.c_str(), 11)) {
4338        sp<NativeWindowWrapper> nativeWindow(
4339                static_cast<NativeWindowWrapper *>(obj.get()));
4340        CHECK(nativeWindow != NULL);
4341        mCodec->mNativeWindow = nativeWindow->getNativeWindow();
4342
4343        native_window_set_scaling_mode(
4344                mCodec->mNativeWindow.get(),
4345                NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
4346    }
4347    CHECK_EQ((status_t)OK, mCodec->initNativeWindow());
4348
4349    {
4350        sp<AMessage> notify = mCodec->mNotify->dup();
4351        notify->setInt32("what", CodecBase::kWhatComponentConfigured);
4352        notify->setMessage("input-format", mCodec->mInputFormat);
4353        notify->setMessage("output-format", mCodec->mOutputFormat);
4354        notify->post();
4355    }
4356
4357    return true;
4358}
4359
4360void ACodec::LoadedState::onCreateInputSurface(
4361        const sp<AMessage> & /* msg */) {
4362    ALOGV("onCreateInputSurface");
4363
4364    sp<AMessage> notify = mCodec->mNotify->dup();
4365    notify->setInt32("what", CodecBase::kWhatInputSurfaceCreated);
4366
4367    sp<IGraphicBufferProducer> bufferProducer;
4368    status_t err;
4369
4370    err = mCodec->mOMX->createInputSurface(mCodec->mNode, kPortIndexInput,
4371            &bufferProducer);
4372
4373    if (err == OK && mCodec->mRepeatFrameDelayUs > 0ll) {
4374        err = mCodec->mOMX->setInternalOption(
4375                mCodec->mNode,
4376                kPortIndexInput,
4377                IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY,
4378                &mCodec->mRepeatFrameDelayUs,
4379                sizeof(mCodec->mRepeatFrameDelayUs));
4380
4381        if (err != OK) {
4382            ALOGE("[%s] Unable to configure option to repeat previous "
4383                  "frames (err %d)",
4384                  mCodec->mComponentName.c_str(),
4385                  err);
4386        }
4387    }
4388
4389    if (err == OK && mCodec->mMaxPtsGapUs > 0ll) {
4390        err = mCodec->mOMX->setInternalOption(
4391                mCodec->mNode,
4392                kPortIndexInput,
4393                IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP,
4394                &mCodec->mMaxPtsGapUs,
4395                sizeof(mCodec->mMaxPtsGapUs));
4396
4397        if (err != OK) {
4398            ALOGE("[%s] Unable to configure max timestamp gap (err %d)",
4399                    mCodec->mComponentName.c_str(),
4400                    err);
4401        }
4402    }
4403
4404    if (err == OK && mCodec->mTimePerCaptureUs > 0ll
4405            && mCodec->mTimePerFrameUs > 0ll) {
4406        int64_t timeLapse[2];
4407        timeLapse[0] = mCodec->mTimePerFrameUs;
4408        timeLapse[1] = mCodec->mTimePerCaptureUs;
4409        err = mCodec->mOMX->setInternalOption(
4410                mCodec->mNode,
4411                kPortIndexInput,
4412                IOMX::INTERNAL_OPTION_TIME_LAPSE,
4413                &timeLapse[0],
4414                sizeof(timeLapse));
4415
4416        if (err != OK) {
4417            ALOGE("[%s] Unable to configure time lapse (err %d)",
4418                    mCodec->mComponentName.c_str(),
4419                    err);
4420        }
4421    }
4422
4423    if (err == OK && mCodec->mCreateInputBuffersSuspended) {
4424        bool suspend = true;
4425        err = mCodec->mOMX->setInternalOption(
4426                mCodec->mNode,
4427                kPortIndexInput,
4428                IOMX::INTERNAL_OPTION_SUSPEND,
4429                &suspend,
4430                sizeof(suspend));
4431
4432        if (err != OK) {
4433            ALOGE("[%s] Unable to configure option to suspend (err %d)",
4434                  mCodec->mComponentName.c_str(),
4435                  err);
4436        }
4437    }
4438
4439    if (err == OK) {
4440        notify->setObject("input-surface",
4441                new BufferProducerWrapper(bufferProducer));
4442    } else {
4443        // Can't use mCodec->signalError() here -- MediaCodec won't forward
4444        // the error through because it's in the "configured" state.  We
4445        // send a kWhatInputSurfaceCreated with an error value instead.
4446        ALOGE("[%s] onCreateInputSurface returning error %d",
4447                mCodec->mComponentName.c_str(), err);
4448        notify->setInt32("err", err);
4449    }
4450    notify->post();
4451}
4452
4453void ACodec::LoadedState::onStart() {
4454    ALOGV("onStart");
4455
4456    CHECK_EQ(mCodec->mOMX->sendCommand(
4457                mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
4458             (status_t)OK);
4459
4460    mCodec->changeState(mCodec->mLoadedToIdleState);
4461}
4462
4463////////////////////////////////////////////////////////////////////////////////
4464
4465ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec)
4466    : BaseState(codec) {
4467}
4468
4469void ACodec::LoadedToIdleState::stateEntered() {
4470    ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
4471
4472    status_t err;
4473    if ((err = allocateBuffers()) != OK) {
4474        ALOGE("Failed to allocate buffers after transitioning to IDLE state "
4475             "(error 0x%08x)",
4476             err);
4477
4478        mCodec->signalError(OMX_ErrorUndefined, err);
4479
4480        mCodec->changeState(mCodec->mLoadedState);
4481    }
4482}
4483
4484status_t ACodec::LoadedToIdleState::allocateBuffers() {
4485    status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput);
4486
4487    if (err != OK) {
4488        return err;
4489    }
4490
4491    return mCodec->allocateBuffersOnPort(kPortIndexOutput);
4492}
4493
4494bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
4495    switch (msg->what()) {
4496        case kWhatSetParameters:
4497        case kWhatShutdown:
4498        {
4499            mCodec->deferMessage(msg);
4500            return true;
4501        }
4502
4503        case kWhatSignalEndOfInputStream:
4504        {
4505            mCodec->onSignalEndOfInputStream();
4506            return true;
4507        }
4508
4509        case kWhatResume:
4510        {
4511            // We'll be active soon enough.
4512            return true;
4513        }
4514
4515        case kWhatFlush:
4516        {
4517            // We haven't even started yet, so we're flushed alright...
4518            sp<AMessage> notify = mCodec->mNotify->dup();
4519            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
4520            notify->post();
4521            return true;
4522        }
4523
4524        default:
4525            return BaseState::onMessageReceived(msg);
4526    }
4527}
4528
4529bool ACodec::LoadedToIdleState::onOMXEvent(
4530        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
4531    switch (event) {
4532        case OMX_EventCmdComplete:
4533        {
4534            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
4535            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
4536
4537            CHECK_EQ(mCodec->mOMX->sendCommand(
4538                        mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting),
4539                     (status_t)OK);
4540
4541            mCodec->changeState(mCodec->mIdleToExecutingState);
4542
4543            return true;
4544        }
4545
4546        default:
4547            return BaseState::onOMXEvent(event, data1, data2);
4548    }
4549}
4550
4551////////////////////////////////////////////////////////////////////////////////
4552
4553ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec)
4554    : BaseState(codec) {
4555}
4556
4557void ACodec::IdleToExecutingState::stateEntered() {
4558    ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
4559}
4560
4561bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
4562    switch (msg->what()) {
4563        case kWhatSetParameters:
4564        case kWhatShutdown:
4565        {
4566            mCodec->deferMessage(msg);
4567            return true;
4568        }
4569
4570        case kWhatResume:
4571        {
4572            // We'll be active soon enough.
4573            return true;
4574        }
4575
4576        case kWhatFlush:
4577        {
4578            // We haven't even started yet, so we're flushed alright...
4579            sp<AMessage> notify = mCodec->mNotify->dup();
4580            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
4581            notify->post();
4582
4583            return true;
4584        }
4585
4586        case kWhatSignalEndOfInputStream:
4587        {
4588            mCodec->onSignalEndOfInputStream();
4589            return true;
4590        }
4591
4592        default:
4593            return BaseState::onMessageReceived(msg);
4594    }
4595}
4596
4597bool ACodec::IdleToExecutingState::onOMXEvent(
4598        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
4599    switch (event) {
4600        case OMX_EventCmdComplete:
4601        {
4602            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
4603            CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting);
4604
4605            mCodec->mExecutingState->resume();
4606            mCodec->changeState(mCodec->mExecutingState);
4607
4608            return true;
4609        }
4610
4611        default:
4612            return BaseState::onOMXEvent(event, data1, data2);
4613    }
4614}
4615
4616////////////////////////////////////////////////////////////////////////////////
4617
4618ACodec::ExecutingState::ExecutingState(ACodec *codec)
4619    : BaseState(codec),
4620      mActive(false) {
4621}
4622
4623ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode(
4624        OMX_U32 /* portIndex */) {
4625    return RESUBMIT_BUFFERS;
4626}
4627
4628void ACodec::ExecutingState::submitOutputMetaBuffers() {
4629    // submit as many buffers as there are input buffers with the codec
4630    // in case we are in port reconfiguring
4631    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
4632        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
4633
4634        if (info->mStatus == BufferInfo::OWNED_BY_COMPONENT) {
4635            if (mCodec->submitOutputMetaDataBuffer() != OK)
4636                break;
4637        }
4638    }
4639
4640    // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
4641    mCodec->signalSubmitOutputMetaDataBufferIfEOS_workaround();
4642}
4643
4644void ACodec::ExecutingState::submitRegularOutputBuffers() {
4645    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
4646        BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
4647
4648        if (mCodec->mNativeWindow != NULL) {
4649            CHECK(info->mStatus == BufferInfo::OWNED_BY_US
4650                    || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
4651
4652            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
4653                continue;
4654            }
4655        } else {
4656            CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
4657        }
4658
4659        ALOGV("[%s] calling fillBuffer %p",
4660             mCodec->mComponentName.c_str(), info->mBufferID);
4661
4662        CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
4663                 (status_t)OK);
4664
4665        info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4666    }
4667}
4668
4669void ACodec::ExecutingState::submitOutputBuffers() {
4670    submitRegularOutputBuffers();
4671    if (mCodec->mStoreMetaDataInOutputBuffers) {
4672        submitOutputMetaBuffers();
4673    }
4674}
4675
4676void ACodec::ExecutingState::resume() {
4677    if (mActive) {
4678        ALOGV("[%s] We're already active, no need to resume.",
4679             mCodec->mComponentName.c_str());
4680
4681        return;
4682    }
4683
4684    submitOutputBuffers();
4685
4686    // Post all available input buffers
4687    CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u);
4688    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); i++) {
4689        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
4690        if (info->mStatus == BufferInfo::OWNED_BY_US) {
4691            postFillThisBuffer(info);
4692        }
4693    }
4694
4695    mActive = true;
4696}
4697
4698void ACodec::ExecutingState::stateEntered() {
4699    ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
4700
4701    mCodec->processDeferredMessages();
4702}
4703
4704bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) {
4705    bool handled = false;
4706
4707    switch (msg->what()) {
4708        case kWhatShutdown:
4709        {
4710            int32_t keepComponentAllocated;
4711            CHECK(msg->findInt32(
4712                        "keepComponentAllocated", &keepComponentAllocated));
4713
4714            mCodec->mShutdownInProgress = true;
4715            mCodec->mExplicitShutdown = true;
4716            mCodec->mKeepComponentAllocated = keepComponentAllocated;
4717
4718            mActive = false;
4719
4720            CHECK_EQ(mCodec->mOMX->sendCommand(
4721                        mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
4722                     (status_t)OK);
4723
4724            mCodec->changeState(mCodec->mExecutingToIdleState);
4725
4726            handled = true;
4727            break;
4728        }
4729
4730        case kWhatFlush:
4731        {
4732            ALOGV("[%s] ExecutingState flushing now "
4733                 "(codec owns %d/%d input, %d/%d output).",
4734                    mCodec->mComponentName.c_str(),
4735                    mCodec->countBuffersOwnedByComponent(kPortIndexInput),
4736                    mCodec->mBuffers[kPortIndexInput].size(),
4737                    mCodec->countBuffersOwnedByComponent(kPortIndexOutput),
4738                    mCodec->mBuffers[kPortIndexOutput].size());
4739
4740            mActive = false;
4741
4742            CHECK_EQ(mCodec->mOMX->sendCommand(
4743                        mCodec->mNode, OMX_CommandFlush, OMX_ALL),
4744                     (status_t)OK);
4745
4746            mCodec->changeState(mCodec->mFlushingState);
4747            handled = true;
4748            break;
4749        }
4750
4751        case kWhatResume:
4752        {
4753            resume();
4754
4755            handled = true;
4756            break;
4757        }
4758
4759        case kWhatRequestIDRFrame:
4760        {
4761            status_t err = mCodec->requestIDRFrame();
4762            if (err != OK) {
4763                ALOGW("Requesting an IDR frame failed.");
4764            }
4765
4766            handled = true;
4767            break;
4768        }
4769
4770        case kWhatSetParameters:
4771        {
4772            sp<AMessage> params;
4773            CHECK(msg->findMessage("params", &params));
4774
4775            status_t err = mCodec->setParameters(params);
4776
4777            sp<AMessage> reply;
4778            if (msg->findMessage("reply", &reply)) {
4779                reply->setInt32("err", err);
4780                reply->post();
4781            }
4782
4783            handled = true;
4784            break;
4785        }
4786
4787        case ACodec::kWhatSignalEndOfInputStream:
4788        {
4789            mCodec->onSignalEndOfInputStream();
4790            handled = true;
4791            break;
4792        }
4793
4794        // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
4795        case kWhatSubmitOutputMetaDataBufferIfEOS:
4796        {
4797            if (mCodec->mPortEOS[kPortIndexInput] &&
4798                    !mCodec->mPortEOS[kPortIndexOutput]) {
4799                status_t err = mCodec->submitOutputMetaDataBuffer();
4800                if (err == OK) {
4801                    mCodec->signalSubmitOutputMetaDataBufferIfEOS_workaround();
4802                }
4803            }
4804            return true;
4805        }
4806
4807        default:
4808            handled = BaseState::onMessageReceived(msg);
4809            break;
4810    }
4811
4812    return handled;
4813}
4814
4815status_t ACodec::setParameters(const sp<AMessage> &params) {
4816    int32_t videoBitrate;
4817    if (params->findInt32("video-bitrate", &videoBitrate)) {
4818        OMX_VIDEO_CONFIG_BITRATETYPE configParams;
4819        InitOMXParams(&configParams);
4820        configParams.nPortIndex = kPortIndexOutput;
4821        configParams.nEncodeBitrate = videoBitrate;
4822
4823        status_t err = mOMX->setConfig(
4824                mNode,
4825                OMX_IndexConfigVideoBitrate,
4826                &configParams,
4827                sizeof(configParams));
4828
4829        if (err != OK) {
4830            ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d",
4831                   videoBitrate, err);
4832
4833            return err;
4834        }
4835    }
4836
4837    int64_t skipFramesBeforeUs;
4838    if (params->findInt64("skip-frames-before", &skipFramesBeforeUs)) {
4839        status_t err =
4840            mOMX->setInternalOption(
4841                     mNode,
4842                     kPortIndexInput,
4843                     IOMX::INTERNAL_OPTION_START_TIME,
4844                     &skipFramesBeforeUs,
4845                     sizeof(skipFramesBeforeUs));
4846
4847        if (err != OK) {
4848            ALOGE("Failed to set parameter 'skip-frames-before' (err %d)", err);
4849            return err;
4850        }
4851    }
4852
4853    int32_t dropInputFrames;
4854    if (params->findInt32("drop-input-frames", &dropInputFrames)) {
4855        bool suspend = dropInputFrames != 0;
4856
4857        status_t err =
4858            mOMX->setInternalOption(
4859                     mNode,
4860                     kPortIndexInput,
4861                     IOMX::INTERNAL_OPTION_SUSPEND,
4862                     &suspend,
4863                     sizeof(suspend));
4864
4865        if (err != OK) {
4866            ALOGE("Failed to set parameter 'drop-input-frames' (err %d)", err);
4867            return err;
4868        }
4869    }
4870
4871    int32_t dummy;
4872    if (params->findInt32("request-sync", &dummy)) {
4873        status_t err = requestIDRFrame();
4874
4875        if (err != OK) {
4876            ALOGE("Requesting a sync frame failed w/ err %d", err);
4877            return err;
4878        }
4879    }
4880
4881    return OK;
4882}
4883
4884void ACodec::onSignalEndOfInputStream() {
4885    sp<AMessage> notify = mNotify->dup();
4886    notify->setInt32("what", CodecBase::kWhatSignaledInputEOS);
4887
4888    status_t err = mOMX->signalEndOfInputStream(mNode);
4889    if (err != OK) {
4890        notify->setInt32("err", err);
4891    }
4892    notify->post();
4893}
4894
4895bool ACodec::ExecutingState::onOMXEvent(
4896        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
4897    switch (event) {
4898        case OMX_EventPortSettingsChanged:
4899        {
4900            CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
4901
4902            if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
4903                mCodec->mMetaDataBuffersToSubmit = 0;
4904                CHECK_EQ(mCodec->mOMX->sendCommand(
4905                            mCodec->mNode,
4906                            OMX_CommandPortDisable, kPortIndexOutput),
4907                         (status_t)OK);
4908
4909                mCodec->freeOutputBuffersNotOwnedByComponent();
4910
4911                mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
4912            } else if (data2 == OMX_IndexConfigCommonOutputCrop) {
4913                mCodec->mSentFormat = false;
4914            } else {
4915                ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx",
4916                     mCodec->mComponentName.c_str(), data2);
4917            }
4918
4919            return true;
4920        }
4921
4922        case OMX_EventBufferFlag:
4923        {
4924            return true;
4925        }
4926
4927        default:
4928            return BaseState::onOMXEvent(event, data1, data2);
4929    }
4930}
4931
4932////////////////////////////////////////////////////////////////////////////////
4933
4934ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState(
4935        ACodec *codec)
4936    : BaseState(codec) {
4937}
4938
4939ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode(
4940        OMX_U32 portIndex) {
4941    if (portIndex == kPortIndexOutput) {
4942        return FREE_BUFFERS;
4943    }
4944
4945    CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput);
4946
4947    return RESUBMIT_BUFFERS;
4948}
4949
4950bool ACodec::OutputPortSettingsChangedState::onMessageReceived(
4951        const sp<AMessage> &msg) {
4952    bool handled = false;
4953
4954    switch (msg->what()) {
4955        case kWhatFlush:
4956        case kWhatShutdown:
4957        case kWhatResume:
4958        {
4959            if (msg->what() == kWhatResume) {
4960                ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
4961            }
4962
4963            mCodec->deferMessage(msg);
4964            handled = true;
4965            break;
4966        }
4967
4968        default:
4969            handled = BaseState::onMessageReceived(msg);
4970            break;
4971    }
4972
4973    return handled;
4974}
4975
4976void ACodec::OutputPortSettingsChangedState::stateEntered() {
4977    ALOGV("[%s] Now handling output port settings change",
4978         mCodec->mComponentName.c_str());
4979}
4980
4981bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
4982        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
4983    switch (event) {
4984        case OMX_EventCmdComplete:
4985        {
4986            if (data1 == (OMX_U32)OMX_CommandPortDisable) {
4987                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
4988
4989                ALOGV("[%s] Output port now disabled.",
4990                        mCodec->mComponentName.c_str());
4991
4992                CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty());
4993                mCodec->mDealer[kPortIndexOutput].clear();
4994
4995                CHECK_EQ(mCodec->mOMX->sendCommand(
4996                            mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput),
4997                         (status_t)OK);
4998
4999                status_t err;
5000                if ((err = mCodec->allocateBuffersOnPort(
5001                                kPortIndexOutput)) != OK) {
5002                    ALOGE("Failed to allocate output port buffers after "
5003                         "port reconfiguration (error 0x%08x)",
5004                         err);
5005
5006                    mCodec->signalError(OMX_ErrorUndefined, err);
5007
5008                    // This is technically not correct, but appears to be
5009                    // the only way to free the component instance.
5010                    // Controlled transitioning from excecuting->idle
5011                    // and idle->loaded seem impossible probably because
5012                    // the output port never finishes re-enabling.
5013                    mCodec->mShutdownInProgress = true;
5014                    mCodec->mKeepComponentAllocated = false;
5015                    mCodec->changeState(mCodec->mLoadedState);
5016                }
5017
5018                return true;
5019            } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
5020                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
5021
5022                mCodec->mSentFormat = false;
5023
5024                ALOGV("[%s] Output port now reenabled.",
5025                        mCodec->mComponentName.c_str());
5026
5027                if (mCodec->mExecutingState->active()) {
5028                    mCodec->mExecutingState->submitOutputBuffers();
5029                }
5030
5031                mCodec->changeState(mCodec->mExecutingState);
5032
5033                return true;
5034            }
5035
5036            return false;
5037        }
5038
5039        default:
5040            return false;
5041    }
5042}
5043
5044////////////////////////////////////////////////////////////////////////////////
5045
5046ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec)
5047    : BaseState(codec),
5048      mComponentNowIdle(false) {
5049}
5050
5051bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) {
5052    bool handled = false;
5053
5054    switch (msg->what()) {
5055        case kWhatFlush:
5056        {
5057            // Don't send me a flush request if you previously wanted me
5058            // to shutdown.
5059            TRESPASS();
5060            break;
5061        }
5062
5063        case kWhatShutdown:
5064        {
5065            // We're already doing that...
5066
5067            handled = true;
5068            break;
5069        }
5070
5071        default:
5072            handled = BaseState::onMessageReceived(msg);
5073            break;
5074    }
5075
5076    return handled;
5077}
5078
5079void ACodec::ExecutingToIdleState::stateEntered() {
5080    ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
5081
5082    mComponentNowIdle = false;
5083    mCodec->mSentFormat = false;
5084}
5085
5086bool ACodec::ExecutingToIdleState::onOMXEvent(
5087        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5088    switch (event) {
5089        case OMX_EventCmdComplete:
5090        {
5091            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
5092            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
5093
5094            mComponentNowIdle = true;
5095
5096            changeStateIfWeOwnAllBuffers();
5097
5098            return true;
5099        }
5100
5101        case OMX_EventPortSettingsChanged:
5102        case OMX_EventBufferFlag:
5103        {
5104            // We're shutting down and don't care about this anymore.
5105            return true;
5106        }
5107
5108        default:
5109            return BaseState::onOMXEvent(event, data1, data2);
5110    }
5111}
5112
5113void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
5114    if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) {
5115        CHECK_EQ(mCodec->mOMX->sendCommand(
5116                    mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded),
5117                 (status_t)OK);
5118
5119        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK);
5120        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK);
5121
5122        if ((mCodec->mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown)
5123                && mCodec->mNativeWindow != NULL) {
5124            // We push enough 1x1 blank buffers to ensure that one of
5125            // them has made it to the display.  This allows the OMX
5126            // component teardown to zero out any protected buffers
5127            // without the risk of scanning out one of those buffers.
5128            mCodec->pushBlankBuffersToNativeWindow();
5129        }
5130
5131        mCodec->changeState(mCodec->mIdleToLoadedState);
5132    }
5133}
5134
5135void ACodec::ExecutingToIdleState::onInputBufferFilled(
5136        const sp<AMessage> &msg) {
5137    BaseState::onInputBufferFilled(msg);
5138
5139    changeStateIfWeOwnAllBuffers();
5140}
5141
5142void ACodec::ExecutingToIdleState::onOutputBufferDrained(
5143        const sp<AMessage> &msg) {
5144    BaseState::onOutputBufferDrained(msg);
5145
5146    changeStateIfWeOwnAllBuffers();
5147}
5148
5149////////////////////////////////////////////////////////////////////////////////
5150
5151ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec)
5152    : BaseState(codec) {
5153}
5154
5155bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) {
5156    bool handled = false;
5157
5158    switch (msg->what()) {
5159        case kWhatShutdown:
5160        {
5161            // We're already doing that...
5162
5163            handled = true;
5164            break;
5165        }
5166
5167        case kWhatFlush:
5168        {
5169            // Don't send me a flush request if you previously wanted me
5170            // to shutdown.
5171            TRESPASS();
5172            break;
5173        }
5174
5175        default:
5176            handled = BaseState::onMessageReceived(msg);
5177            break;
5178    }
5179
5180    return handled;
5181}
5182
5183void ACodec::IdleToLoadedState::stateEntered() {
5184    ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
5185}
5186
5187bool ACodec::IdleToLoadedState::onOMXEvent(
5188        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5189    switch (event) {
5190        case OMX_EventCmdComplete:
5191        {
5192            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
5193            CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded);
5194
5195            mCodec->changeState(mCodec->mLoadedState);
5196
5197            return true;
5198        }
5199
5200        default:
5201            return BaseState::onOMXEvent(event, data1, data2);
5202    }
5203}
5204
5205////////////////////////////////////////////////////////////////////////////////
5206
5207ACodec::FlushingState::FlushingState(ACodec *codec)
5208    : BaseState(codec) {
5209}
5210
5211void ACodec::FlushingState::stateEntered() {
5212    ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());
5213
5214    mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
5215}
5216
5217bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) {
5218    bool handled = false;
5219
5220    switch (msg->what()) {
5221        case kWhatShutdown:
5222        {
5223            mCodec->deferMessage(msg);
5224            break;
5225        }
5226
5227        case kWhatFlush:
5228        {
5229            // We're already doing this right now.
5230            handled = true;
5231            break;
5232        }
5233
5234        default:
5235            handled = BaseState::onMessageReceived(msg);
5236            break;
5237    }
5238
5239    return handled;
5240}
5241
5242bool ACodec::FlushingState::onOMXEvent(
5243        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5244    ALOGV("[%s] FlushingState onOMXEvent(%d,%ld)",
5245            mCodec->mComponentName.c_str(), event, data1);
5246
5247    switch (event) {
5248        case OMX_EventCmdComplete:
5249        {
5250            CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush);
5251
5252            if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
5253                CHECK(!mFlushComplete[data2]);
5254                mFlushComplete[data2] = true;
5255
5256                if (mFlushComplete[kPortIndexInput]
5257                        && mFlushComplete[kPortIndexOutput]) {
5258                    changeStateIfWeOwnAllBuffers();
5259                }
5260            } else {
5261                CHECK_EQ(data2, OMX_ALL);
5262                CHECK(mFlushComplete[kPortIndexInput]);
5263                CHECK(mFlushComplete[kPortIndexOutput]);
5264
5265                changeStateIfWeOwnAllBuffers();
5266            }
5267
5268            return true;
5269        }
5270
5271        case OMX_EventPortSettingsChanged:
5272        {
5273            sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id());
5274            msg->setInt32("type", omx_message::EVENT);
5275            msg->setInt32("node", mCodec->mNode);
5276            msg->setInt32("event", event);
5277            msg->setInt32("data1", data1);
5278            msg->setInt32("data2", data2);
5279
5280            ALOGV("[%s] Deferring OMX_EventPortSettingsChanged",
5281                 mCodec->mComponentName.c_str());
5282
5283            mCodec->deferMessage(msg);
5284
5285            return true;
5286        }
5287
5288        default:
5289            return BaseState::onOMXEvent(event, data1, data2);
5290    }
5291
5292    return true;
5293}
5294
5295void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) {
5296    BaseState::onOutputBufferDrained(msg);
5297
5298    changeStateIfWeOwnAllBuffers();
5299}
5300
5301void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) {
5302    BaseState::onInputBufferFilled(msg);
5303
5304    changeStateIfWeOwnAllBuffers();
5305}
5306
5307void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() {
5308    if (mFlushComplete[kPortIndexInput]
5309            && mFlushComplete[kPortIndexOutput]
5310            && mCodec->allYourBuffersAreBelongToUs()) {
5311        // We now own all buffers except possibly those still queued with
5312        // the native window for rendering. Let's get those back as well.
5313        mCodec->waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs();
5314
5315        sp<AMessage> notify = mCodec->mNotify->dup();
5316        notify->setInt32("what", CodecBase::kWhatFlushCompleted);
5317        notify->post();
5318
5319        mCodec->mPortEOS[kPortIndexInput] =
5320            mCodec->mPortEOS[kPortIndexOutput] = false;
5321
5322        mCodec->mInputEOSResult = OK;
5323
5324        if (mCodec->mSkipCutBuffer != NULL) {
5325            mCodec->mSkipCutBuffer->clear();
5326        }
5327
5328        mCodec->changeState(mCodec->mExecutingState);
5329    }
5330}
5331
5332}  // namespace android
5333