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