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