ACodec.cpp revision 8b806ea894ca098366629458bfdd1df4866afcdf
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            err = setupG711Codec(encoder, numChannels);
1595        }
1596    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)) {
1597        int32_t numChannels, sampleRate, compressionLevel = -1;
1598        if (encoder &&
1599                (!msg->findInt32("channel-count", &numChannels)
1600                        || !msg->findInt32("sample-rate", &sampleRate))) {
1601            ALOGE("missing channel count or sample rate for FLAC encoder");
1602            err = INVALID_OPERATION;
1603        } else {
1604            if (encoder) {
1605                if (!msg->findInt32(
1606                            "complexity", &compressionLevel) &&
1607                    !msg->findInt32(
1608                            "flac-compression-level", &compressionLevel)) {
1609                    compressionLevel = 5; // default FLAC compression level
1610                } else if (compressionLevel < 0) {
1611                    ALOGW("compression level %d outside [0..8] range, "
1612                          "using 0",
1613                          compressionLevel);
1614                    compressionLevel = 0;
1615                } else if (compressionLevel > 8) {
1616                    ALOGW("compression level %d outside [0..8] range, "
1617                          "using 8",
1618                          compressionLevel);
1619                    compressionLevel = 8;
1620                }
1621            }
1622            err = setupFlacCodec(
1623                    encoder, numChannels, sampleRate, compressionLevel);
1624        }
1625    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
1626        int32_t numChannels, sampleRate;
1627        if (encoder
1628                || !msg->findInt32("channel-count", &numChannels)
1629                || !msg->findInt32("sample-rate", &sampleRate)) {
1630            err = INVALID_OPERATION;
1631        } else {
1632            err = setupRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
1633        }
1634    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AC3)) {
1635        int32_t numChannels;
1636        int32_t sampleRate;
1637        if (!msg->findInt32("channel-count", &numChannels)
1638                || !msg->findInt32("sample-rate", &sampleRate)) {
1639            err = INVALID_OPERATION;
1640        } else {
1641            err = setupAC3Codec(encoder, numChannels, sampleRate);
1642        }
1643    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_EAC3)) {
1644        int32_t numChannels;
1645        int32_t sampleRate;
1646        if (!msg->findInt32("channel-count", &numChannels)
1647                || !msg->findInt32("sample-rate", &sampleRate)) {
1648            err = INVALID_OPERATION;
1649        } else {
1650            err = setupEAC3Codec(encoder, numChannels, sampleRate);
1651        }
1652    }
1653
1654    if (err != OK) {
1655        return err;
1656    }
1657
1658    if (!msg->findInt32("encoder-delay", &mEncoderDelay)) {
1659        mEncoderDelay = 0;
1660    }
1661
1662    if (!msg->findInt32("encoder-padding", &mEncoderPadding)) {
1663        mEncoderPadding = 0;
1664    }
1665
1666    if (msg->findInt32("channel-mask", &mChannelMask)) {
1667        mChannelMaskPresent = true;
1668    } else {
1669        mChannelMaskPresent = false;
1670    }
1671
1672    int32_t maxInputSize;
1673    if (msg->findInt32("max-input-size", &maxInputSize)) {
1674        err = setMinBufferSize(kPortIndexInput, (size_t)maxInputSize);
1675    } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) {
1676        err = setMinBufferSize(kPortIndexInput, 8192);  // XXX
1677    }
1678
1679    int32_t priority;
1680    if (msg->findInt32("priority", &priority)) {
1681        err = setPriority(priority);
1682    }
1683
1684    mBaseOutputFormat = outputFormat;
1685
1686    CHECK_EQ(getPortFormat(kPortIndexInput, inputFormat), (status_t)OK);
1687    CHECK_EQ(getPortFormat(kPortIndexOutput, outputFormat), (status_t)OK);
1688    mInputFormat = inputFormat;
1689    mOutputFormat = outputFormat;
1690
1691    return err;
1692}
1693
1694status_t ACodec::setPriority(int32_t priority) {
1695    if (priority < 0) {
1696        return BAD_VALUE;
1697    }
1698    OMX_PARAM_U32TYPE config;
1699    InitOMXParams(&config);
1700    config.nU32 = (OMX_U32)priority;
1701    status_t temp = mOMX->setConfig(
1702            mNode, (OMX_INDEXTYPE)OMX_IndexConfigPriority,
1703            &config, sizeof(config));
1704    if (temp != OK) {
1705        ALOGI("codec does not support config priority (err %d)", temp);
1706    }
1707    return OK;
1708}
1709
1710status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) {
1711    OMX_PARAM_PORTDEFINITIONTYPE def;
1712    InitOMXParams(&def);
1713    def.nPortIndex = portIndex;
1714
1715    status_t err = mOMX->getParameter(
1716            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1717
1718    if (err != OK) {
1719        return err;
1720    }
1721
1722    if (def.nBufferSize >= size) {
1723        return OK;
1724    }
1725
1726    def.nBufferSize = size;
1727
1728    err = mOMX->setParameter(
1729            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1730
1731    if (err != OK) {
1732        return err;
1733    }
1734
1735    err = mOMX->getParameter(
1736            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1737
1738    if (err != OK) {
1739        return err;
1740    }
1741
1742    CHECK(def.nBufferSize >= size);
1743
1744    return OK;
1745}
1746
1747status_t ACodec::selectAudioPortFormat(
1748        OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat) {
1749    OMX_AUDIO_PARAM_PORTFORMATTYPE format;
1750    InitOMXParams(&format);
1751
1752    format.nPortIndex = portIndex;
1753    for (OMX_U32 index = 0;; ++index) {
1754        format.nIndex = index;
1755
1756        status_t err = mOMX->getParameter(
1757                mNode, OMX_IndexParamAudioPortFormat,
1758                &format, sizeof(format));
1759
1760        if (err != OK) {
1761            return err;
1762        }
1763
1764        if (format.eEncoding == desiredFormat) {
1765            break;
1766        }
1767    }
1768
1769    return mOMX->setParameter(
1770            mNode, OMX_IndexParamAudioPortFormat, &format, sizeof(format));
1771}
1772
1773status_t ACodec::setupAACCodec(
1774        bool encoder, int32_t numChannels, int32_t sampleRate,
1775        int32_t bitRate, int32_t aacProfile, bool isADTS, int32_t sbrMode,
1776        int32_t maxOutputChannelCount, const drcParams_t& drc,
1777        int32_t pcmLimiterEnable) {
1778    if (encoder && isADTS) {
1779        return -EINVAL;
1780    }
1781
1782    status_t err = setupRawAudioFormat(
1783            encoder ? kPortIndexInput : kPortIndexOutput,
1784            sampleRate,
1785            numChannels);
1786
1787    if (err != OK) {
1788        return err;
1789    }
1790
1791    if (encoder) {
1792        err = selectAudioPortFormat(kPortIndexOutput, OMX_AUDIO_CodingAAC);
1793
1794        if (err != OK) {
1795            return err;
1796        }
1797
1798        OMX_PARAM_PORTDEFINITIONTYPE def;
1799        InitOMXParams(&def);
1800        def.nPortIndex = kPortIndexOutput;
1801
1802        err = mOMX->getParameter(
1803                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1804
1805        if (err != OK) {
1806            return err;
1807        }
1808
1809        def.format.audio.bFlagErrorConcealment = OMX_TRUE;
1810        def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
1811
1812        err = mOMX->setParameter(
1813                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1814
1815        if (err != OK) {
1816            return err;
1817        }
1818
1819        OMX_AUDIO_PARAM_AACPROFILETYPE profile;
1820        InitOMXParams(&profile);
1821        profile.nPortIndex = kPortIndexOutput;
1822
1823        err = mOMX->getParameter(
1824                mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1825
1826        if (err != OK) {
1827            return err;
1828        }
1829
1830        profile.nChannels = numChannels;
1831
1832        profile.eChannelMode =
1833            (numChannels == 1)
1834                ? OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo;
1835
1836        profile.nSampleRate = sampleRate;
1837        profile.nBitRate = bitRate;
1838        profile.nAudioBandWidth = 0;
1839        profile.nFrameLength = 0;
1840        profile.nAACtools = OMX_AUDIO_AACToolAll;
1841        profile.nAACERtools = OMX_AUDIO_AACERNone;
1842        profile.eAACProfile = (OMX_AUDIO_AACPROFILETYPE) aacProfile;
1843        profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
1844        switch (sbrMode) {
1845        case 0:
1846            // disable sbr
1847            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR;
1848            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR;
1849            break;
1850        case 1:
1851            // enable single-rate sbr
1852            profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR;
1853            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR;
1854            break;
1855        case 2:
1856            // enable dual-rate sbr
1857            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR;
1858            profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR;
1859            break;
1860        case -1:
1861            // enable both modes -> the codec will decide which mode should be used
1862            profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR;
1863            profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR;
1864            break;
1865        default:
1866            // unsupported sbr mode
1867            return BAD_VALUE;
1868        }
1869
1870
1871        err = mOMX->setParameter(
1872                mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1873
1874        if (err != OK) {
1875            return err;
1876        }
1877
1878        return err;
1879    }
1880
1881    OMX_AUDIO_PARAM_AACPROFILETYPE profile;
1882    InitOMXParams(&profile);
1883    profile.nPortIndex = kPortIndexInput;
1884
1885    err = mOMX->getParameter(
1886            mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1887
1888    if (err != OK) {
1889        return err;
1890    }
1891
1892    profile.nChannels = numChannels;
1893    profile.nSampleRate = sampleRate;
1894
1895    profile.eAACStreamFormat =
1896        isADTS
1897            ? OMX_AUDIO_AACStreamFormatMP4ADTS
1898            : OMX_AUDIO_AACStreamFormatMP4FF;
1899
1900    OMX_AUDIO_PARAM_ANDROID_AACPRESENTATIONTYPE presentation;
1901    presentation.nMaxOutputChannels = maxOutputChannelCount;
1902    presentation.nDrcCut = drc.drcCut;
1903    presentation.nDrcBoost = drc.drcBoost;
1904    presentation.nHeavyCompression = drc.heavyCompression;
1905    presentation.nTargetReferenceLevel = drc.targetRefLevel;
1906    presentation.nEncodedTargetLevel = drc.encodedTargetLevel;
1907    presentation.nPCMLimiterEnable = pcmLimiterEnable;
1908
1909    status_t res = mOMX->setParameter(mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1910    if (res == OK) {
1911        // optional parameters, will not cause configuration failure
1912        mOMX->setParameter(mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAacPresentation,
1913                &presentation, sizeof(presentation));
1914    } else {
1915        ALOGW("did not set AudioAndroidAacPresentation due to error %d when setting AudioAac", res);
1916    }
1917    return res;
1918}
1919
1920status_t ACodec::setupAC3Codec(
1921        bool encoder, int32_t numChannels, int32_t sampleRate) {
1922    status_t err = setupRawAudioFormat(
1923            encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels);
1924
1925    if (err != OK) {
1926        return err;
1927    }
1928
1929    if (encoder) {
1930        ALOGW("AC3 encoding is not supported.");
1931        return INVALID_OPERATION;
1932    }
1933
1934    OMX_AUDIO_PARAM_ANDROID_AC3TYPE def;
1935    InitOMXParams(&def);
1936    def.nPortIndex = kPortIndexInput;
1937
1938    err = mOMX->getParameter(
1939            mNode,
1940            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
1941            &def,
1942            sizeof(def));
1943
1944    if (err != OK) {
1945        return err;
1946    }
1947
1948    def.nChannels = numChannels;
1949    def.nSampleRate = sampleRate;
1950
1951    return mOMX->setParameter(
1952            mNode,
1953            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
1954            &def,
1955            sizeof(def));
1956}
1957
1958status_t ACodec::setupEAC3Codec(
1959        bool encoder, int32_t numChannels, int32_t sampleRate) {
1960    status_t err = setupRawAudioFormat(
1961            encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels);
1962
1963    if (err != OK) {
1964        return err;
1965    }
1966
1967    if (encoder) {
1968        ALOGW("EAC3 encoding is not supported.");
1969        return INVALID_OPERATION;
1970    }
1971
1972    OMX_AUDIO_PARAM_ANDROID_EAC3TYPE def;
1973    InitOMXParams(&def);
1974    def.nPortIndex = kPortIndexInput;
1975
1976    err = mOMX->getParameter(
1977            mNode,
1978            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
1979            &def,
1980            sizeof(def));
1981
1982    if (err != OK) {
1983        return err;
1984    }
1985
1986    def.nChannels = numChannels;
1987    def.nSampleRate = sampleRate;
1988
1989    return mOMX->setParameter(
1990            mNode,
1991            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
1992            &def,
1993            sizeof(def));
1994}
1995
1996static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate(
1997        bool isAMRWB, int32_t bps) {
1998    if (isAMRWB) {
1999        if (bps <= 6600) {
2000            return OMX_AUDIO_AMRBandModeWB0;
2001        } else if (bps <= 8850) {
2002            return OMX_AUDIO_AMRBandModeWB1;
2003        } else if (bps <= 12650) {
2004            return OMX_AUDIO_AMRBandModeWB2;
2005        } else if (bps <= 14250) {
2006            return OMX_AUDIO_AMRBandModeWB3;
2007        } else if (bps <= 15850) {
2008            return OMX_AUDIO_AMRBandModeWB4;
2009        } else if (bps <= 18250) {
2010            return OMX_AUDIO_AMRBandModeWB5;
2011        } else if (bps <= 19850) {
2012            return OMX_AUDIO_AMRBandModeWB6;
2013        } else if (bps <= 23050) {
2014            return OMX_AUDIO_AMRBandModeWB7;
2015        }
2016
2017        // 23850 bps
2018        return OMX_AUDIO_AMRBandModeWB8;
2019    } else {  // AMRNB
2020        if (bps <= 4750) {
2021            return OMX_AUDIO_AMRBandModeNB0;
2022        } else if (bps <= 5150) {
2023            return OMX_AUDIO_AMRBandModeNB1;
2024        } else if (bps <= 5900) {
2025            return OMX_AUDIO_AMRBandModeNB2;
2026        } else if (bps <= 6700) {
2027            return OMX_AUDIO_AMRBandModeNB3;
2028        } else if (bps <= 7400) {
2029            return OMX_AUDIO_AMRBandModeNB4;
2030        } else if (bps <= 7950) {
2031            return OMX_AUDIO_AMRBandModeNB5;
2032        } else if (bps <= 10200) {
2033            return OMX_AUDIO_AMRBandModeNB6;
2034        }
2035
2036        // 12200 bps
2037        return OMX_AUDIO_AMRBandModeNB7;
2038    }
2039}
2040
2041status_t ACodec::setupAMRCodec(bool encoder, bool isWAMR, int32_t bitrate) {
2042    OMX_AUDIO_PARAM_AMRTYPE def;
2043    InitOMXParams(&def);
2044    def.nPortIndex = encoder ? kPortIndexOutput : kPortIndexInput;
2045
2046    status_t err =
2047        mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
2048
2049    if (err != OK) {
2050        return err;
2051    }
2052
2053    def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
2054    def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitrate);
2055
2056    err = mOMX->setParameter(
2057            mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
2058
2059    if (err != OK) {
2060        return err;
2061    }
2062
2063    return setupRawAudioFormat(
2064            encoder ? kPortIndexInput : kPortIndexOutput,
2065            isWAMR ? 16000 : 8000 /* sampleRate */,
2066            1 /* numChannels */);
2067}
2068
2069status_t ACodec::setupG711Codec(bool encoder, int32_t numChannels) {
2070    CHECK(!encoder);  // XXX TODO
2071
2072    return setupRawAudioFormat(
2073            kPortIndexInput, 8000 /* sampleRate */, numChannels);
2074}
2075
2076status_t ACodec::setupFlacCodec(
2077        bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel) {
2078
2079    if (encoder) {
2080        OMX_AUDIO_PARAM_FLACTYPE def;
2081        InitOMXParams(&def);
2082        def.nPortIndex = kPortIndexOutput;
2083
2084        // configure compression level
2085        status_t err = mOMX->getParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def));
2086        if (err != OK) {
2087            ALOGE("setupFlacCodec(): Error %d getting OMX_IndexParamAudioFlac parameter", err);
2088            return err;
2089        }
2090        def.nCompressionLevel = compressionLevel;
2091        err = mOMX->setParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def));
2092        if (err != OK) {
2093            ALOGE("setupFlacCodec(): Error %d setting OMX_IndexParamAudioFlac parameter", err);
2094            return err;
2095        }
2096    }
2097
2098    return setupRawAudioFormat(
2099            encoder ? kPortIndexInput : kPortIndexOutput,
2100            sampleRate,
2101            numChannels);
2102}
2103
2104status_t ACodec::setupRawAudioFormat(
2105        OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) {
2106    OMX_PARAM_PORTDEFINITIONTYPE def;
2107    InitOMXParams(&def);
2108    def.nPortIndex = portIndex;
2109
2110    status_t err = mOMX->getParameter(
2111            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2112
2113    if (err != OK) {
2114        return err;
2115    }
2116
2117    def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
2118
2119    err = mOMX->setParameter(
2120            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2121
2122    if (err != OK) {
2123        return err;
2124    }
2125
2126    OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
2127    InitOMXParams(&pcmParams);
2128    pcmParams.nPortIndex = portIndex;
2129
2130    err = mOMX->getParameter(
2131            mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
2132
2133    if (err != OK) {
2134        return err;
2135    }
2136
2137    pcmParams.nChannels = numChannels;
2138    pcmParams.eNumData = OMX_NumericalDataSigned;
2139    pcmParams.bInterleaved = OMX_TRUE;
2140    pcmParams.nBitPerSample = 16;
2141    pcmParams.nSamplingRate = sampleRate;
2142    pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
2143
2144    if (getOMXChannelMapping(numChannels, pcmParams.eChannelMapping) != OK) {
2145        return OMX_ErrorNone;
2146    }
2147
2148    return mOMX->setParameter(
2149            mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
2150}
2151
2152status_t ACodec::configureTunneledVideoPlayback(
2153        int32_t audioHwSync, const sp<ANativeWindow> &nativeWindow) {
2154    native_handle_t* sidebandHandle;
2155
2156    status_t err = mOMX->configureVideoTunnelMode(
2157            mNode, kPortIndexOutput, OMX_TRUE, audioHwSync, &sidebandHandle);
2158    if (err != OK) {
2159        ALOGE("configureVideoTunnelMode failed! (err %d).", err);
2160        return err;
2161    }
2162
2163    err = native_window_set_sideband_stream(nativeWindow.get(), sidebandHandle);
2164    if (err != OK) {
2165        ALOGE("native_window_set_sideband_stream(%p) failed! (err %d).",
2166                sidebandHandle, err);
2167        return err;
2168    }
2169
2170    return OK;
2171}
2172
2173status_t ACodec::setVideoPortFormatType(
2174        OMX_U32 portIndex,
2175        OMX_VIDEO_CODINGTYPE compressionFormat,
2176        OMX_COLOR_FORMATTYPE colorFormat,
2177        bool usingNativeBuffers) {
2178    OMX_VIDEO_PARAM_PORTFORMATTYPE format;
2179    InitOMXParams(&format);
2180    format.nPortIndex = portIndex;
2181    format.nIndex = 0;
2182    bool found = false;
2183
2184    OMX_U32 index = 0;
2185    for (;;) {
2186        format.nIndex = index;
2187        status_t err = mOMX->getParameter(
2188                mNode, OMX_IndexParamVideoPortFormat,
2189                &format, sizeof(format));
2190
2191        if (err != OK) {
2192            return err;
2193        }
2194
2195        // substitute back flexible color format to codec supported format
2196        OMX_U32 flexibleEquivalent;
2197        if (compressionFormat == OMX_VIDEO_CodingUnused
2198                && isFlexibleColorFormat(
2199                        mOMX, mNode, format.eColorFormat, usingNativeBuffers, &flexibleEquivalent)
2200                && colorFormat == flexibleEquivalent) {
2201            ALOGI("[%s] using color format %#x in place of %#x",
2202                    mComponentName.c_str(), format.eColorFormat, colorFormat);
2203            colorFormat = format.eColorFormat;
2204        }
2205
2206        // The following assertion is violated by TI's video decoder.
2207        // CHECK_EQ(format.nIndex, index);
2208
2209        if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) {
2210            if (portIndex == kPortIndexInput
2211                    && colorFormat == format.eColorFormat) {
2212                // eCompressionFormat does not seem right.
2213                found = true;
2214                break;
2215            }
2216            if (portIndex == kPortIndexOutput
2217                    && compressionFormat == format.eCompressionFormat) {
2218                // eColorFormat does not seem right.
2219                found = true;
2220                break;
2221            }
2222        }
2223
2224        if (format.eCompressionFormat == compressionFormat
2225            && format.eColorFormat == colorFormat) {
2226            found = true;
2227            break;
2228        }
2229
2230        ++index;
2231    }
2232
2233    if (!found) {
2234        return UNKNOWN_ERROR;
2235    }
2236
2237    status_t err = mOMX->setParameter(
2238            mNode, OMX_IndexParamVideoPortFormat,
2239            &format, sizeof(format));
2240
2241    return err;
2242}
2243
2244// Set optimal output format. OMX component lists output formats in the order
2245// of preference, but this got more complicated since the introduction of flexible
2246// YUV formats. We support a legacy behavior for applications that do not use
2247// surface output, do not specify an output format, but expect a "usable" standard
2248// OMX format. SW readable and standard formats must be flex-YUV.
2249//
2250// Suggested preference order:
2251// - optimal format for texture rendering (mediaplayer behavior)
2252// - optimal SW readable & texture renderable format (flex-YUV support)
2253// - optimal SW readable non-renderable format (flex-YUV bytebuffer support)
2254// - legacy "usable" standard formats
2255//
2256// For legacy support, we prefer a standard format, but will settle for a SW readable
2257// flex-YUV format.
2258status_t ACodec::setSupportedOutputFormat(bool getLegacyFlexibleFormat) {
2259    OMX_VIDEO_PARAM_PORTFORMATTYPE format, legacyFormat;
2260    InitOMXParams(&format);
2261    format.nPortIndex = kPortIndexOutput;
2262
2263    InitOMXParams(&legacyFormat);
2264    // this field will change when we find a suitable legacy format
2265    legacyFormat.eColorFormat = OMX_COLOR_FormatUnused;
2266
2267    for (OMX_U32 index = 0; ; ++index) {
2268        format.nIndex = index;
2269        status_t err = mOMX->getParameter(
2270                mNode, OMX_IndexParamVideoPortFormat,
2271                &format, sizeof(format));
2272        if (err != OK) {
2273            // no more formats, pick legacy format if found
2274            if (legacyFormat.eColorFormat != OMX_COLOR_FormatUnused) {
2275                 memcpy(&format, &legacyFormat, sizeof(format));
2276                 break;
2277            }
2278            return err;
2279        }
2280        if (format.eCompressionFormat != OMX_VIDEO_CodingUnused) {
2281            return OMX_ErrorBadParameter;
2282        }
2283        if (!getLegacyFlexibleFormat) {
2284            break;
2285        }
2286        // standard formats that were exposed to users before
2287        if (format.eColorFormat == OMX_COLOR_FormatYUV420Planar
2288                || format.eColorFormat == OMX_COLOR_FormatYUV420PackedPlanar
2289                || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
2290                || format.eColorFormat == OMX_COLOR_FormatYUV420PackedSemiPlanar
2291                || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar) {
2292            break;
2293        }
2294        // find best legacy non-standard format
2295        OMX_U32 flexibleEquivalent;
2296        if (legacyFormat.eColorFormat == OMX_COLOR_FormatUnused
2297                && isFlexibleColorFormat(
2298                        mOMX, mNode, format.eColorFormat, false /* usingNativeBuffers */,
2299                        &flexibleEquivalent)
2300                && flexibleEquivalent == OMX_COLOR_FormatYUV420Flexible) {
2301            memcpy(&legacyFormat, &format, sizeof(format));
2302        }
2303    }
2304    return mOMX->setParameter(
2305            mNode, OMX_IndexParamVideoPortFormat,
2306            &format, sizeof(format));
2307}
2308
2309static const struct VideoCodingMapEntry {
2310    const char *mMime;
2311    OMX_VIDEO_CODINGTYPE mVideoCodingType;
2312} kVideoCodingMapEntry[] = {
2313    { MEDIA_MIMETYPE_VIDEO_AVC, OMX_VIDEO_CodingAVC },
2314    { MEDIA_MIMETYPE_VIDEO_HEVC, OMX_VIDEO_CodingHEVC },
2315    { MEDIA_MIMETYPE_VIDEO_MPEG4, OMX_VIDEO_CodingMPEG4 },
2316    { MEDIA_MIMETYPE_VIDEO_H263, OMX_VIDEO_CodingH263 },
2317    { MEDIA_MIMETYPE_VIDEO_MPEG2, OMX_VIDEO_CodingMPEG2 },
2318    { MEDIA_MIMETYPE_VIDEO_VP8, OMX_VIDEO_CodingVP8 },
2319    { MEDIA_MIMETYPE_VIDEO_VP9, OMX_VIDEO_CodingVP9 },
2320};
2321
2322static status_t GetVideoCodingTypeFromMime(
2323        const char *mime, OMX_VIDEO_CODINGTYPE *codingType) {
2324    for (size_t i = 0;
2325         i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]);
2326         ++i) {
2327        if (!strcasecmp(mime, kVideoCodingMapEntry[i].mMime)) {
2328            *codingType = kVideoCodingMapEntry[i].mVideoCodingType;
2329            return OK;
2330        }
2331    }
2332
2333    *codingType = OMX_VIDEO_CodingUnused;
2334
2335    return ERROR_UNSUPPORTED;
2336}
2337
2338static status_t GetMimeTypeForVideoCoding(
2339        OMX_VIDEO_CODINGTYPE codingType, AString *mime) {
2340    for (size_t i = 0;
2341         i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]);
2342         ++i) {
2343        if (codingType == kVideoCodingMapEntry[i].mVideoCodingType) {
2344            *mime = kVideoCodingMapEntry[i].mMime;
2345            return OK;
2346        }
2347    }
2348
2349    mime->clear();
2350
2351    return ERROR_UNSUPPORTED;
2352}
2353
2354status_t ACodec::setupVideoDecoder(
2355        const char *mime, const sp<AMessage> &msg, bool haveNativeWindow) {
2356    int32_t width, height;
2357    if (!msg->findInt32("width", &width)
2358            || !msg->findInt32("height", &height)) {
2359        return INVALID_OPERATION;
2360    }
2361
2362    OMX_VIDEO_CODINGTYPE compressionFormat;
2363    status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
2364
2365    if (err != OK) {
2366        return err;
2367    }
2368
2369    err = setVideoPortFormatType(
2370            kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
2371
2372    if (err != OK) {
2373        return err;
2374    }
2375
2376    int32_t tmp;
2377    if (msg->findInt32("color-format", &tmp)) {
2378        OMX_COLOR_FORMATTYPE colorFormat =
2379            static_cast<OMX_COLOR_FORMATTYPE>(tmp);
2380        err = setVideoPortFormatType(
2381                kPortIndexOutput, OMX_VIDEO_CodingUnused, colorFormat, haveNativeWindow);
2382        if (err != OK) {
2383            ALOGW("[%s] does not support color format %d",
2384                  mComponentName.c_str(), colorFormat);
2385            err = setSupportedOutputFormat(!haveNativeWindow /* getLegacyFlexibleFormat */);
2386        }
2387    } else {
2388        err = setSupportedOutputFormat(!haveNativeWindow /* getLegacyFlexibleFormat */);
2389    }
2390
2391    if (err != OK) {
2392        return err;
2393    }
2394
2395    int32_t frameRateInt;
2396    float frameRateFloat;
2397    if (!msg->findFloat("frame-rate", &frameRateFloat)) {
2398        if (!msg->findInt32("frame-rate", &frameRateInt)) {
2399            frameRateInt = -1;
2400        }
2401        frameRateFloat = (float)frameRateInt;
2402    }
2403
2404    err = setVideoFormatOnPort(
2405            kPortIndexInput, width, height, compressionFormat, frameRateFloat);
2406
2407    if (err != OK) {
2408        return err;
2409    }
2410
2411    err = setVideoFormatOnPort(
2412            kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused);
2413
2414    if (err != OK) {
2415        return err;
2416    }
2417
2418    return OK;
2419}
2420
2421status_t ACodec::setupVideoEncoder(const char *mime, const sp<AMessage> &msg) {
2422    int32_t tmp;
2423    if (!msg->findInt32("color-format", &tmp)) {
2424        return INVALID_OPERATION;
2425    }
2426
2427    OMX_COLOR_FORMATTYPE colorFormat =
2428        static_cast<OMX_COLOR_FORMATTYPE>(tmp);
2429
2430    status_t err = setVideoPortFormatType(
2431            kPortIndexInput, OMX_VIDEO_CodingUnused, colorFormat);
2432
2433    if (err != OK) {
2434        ALOGE("[%s] does not support color format %d",
2435              mComponentName.c_str(), colorFormat);
2436
2437        return err;
2438    }
2439
2440    /* Input port configuration */
2441
2442    OMX_PARAM_PORTDEFINITIONTYPE def;
2443    InitOMXParams(&def);
2444
2445    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
2446
2447    def.nPortIndex = kPortIndexInput;
2448
2449    err = mOMX->getParameter(
2450            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2451
2452    if (err != OK) {
2453        return err;
2454    }
2455
2456    int32_t width, height, bitrate;
2457    if (!msg->findInt32("width", &width)
2458            || !msg->findInt32("height", &height)
2459            || !msg->findInt32("bitrate", &bitrate)) {
2460        return INVALID_OPERATION;
2461    }
2462
2463    video_def->nFrameWidth = width;
2464    video_def->nFrameHeight = height;
2465
2466    int32_t stride;
2467    if (!msg->findInt32("stride", &stride)) {
2468        stride = width;
2469    }
2470
2471    video_def->nStride = stride;
2472
2473    int32_t sliceHeight;
2474    if (!msg->findInt32("slice-height", &sliceHeight)) {
2475        sliceHeight = height;
2476    }
2477
2478    video_def->nSliceHeight = sliceHeight;
2479
2480    def.nBufferSize = (video_def->nStride * video_def->nSliceHeight * 3) / 2;
2481
2482    float frameRate;
2483    if (!msg->findFloat("frame-rate", &frameRate)) {
2484        int32_t tmp;
2485        if (!msg->findInt32("frame-rate", &tmp)) {
2486            return INVALID_OPERATION;
2487        }
2488        frameRate = (float)tmp;
2489        mTimePerFrameUs = (int64_t) (1000000.0f / frameRate);
2490    }
2491
2492    video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f);
2493    video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
2494    // this is redundant as it was already set up in setVideoPortFormatType
2495    // FIXME for now skip this only for flexible YUV formats
2496    if (colorFormat != OMX_COLOR_FormatYUV420Flexible) {
2497        video_def->eColorFormat = colorFormat;
2498    }
2499
2500    err = mOMX->setParameter(
2501            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2502
2503    if (err != OK) {
2504        ALOGE("[%s] failed to set input port definition parameters.",
2505              mComponentName.c_str());
2506
2507        return err;
2508    }
2509
2510    /* Output port configuration */
2511
2512    OMX_VIDEO_CODINGTYPE compressionFormat;
2513    err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
2514
2515    if (err != OK) {
2516        return err;
2517    }
2518
2519    err = setVideoPortFormatType(
2520            kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused);
2521
2522    if (err != OK) {
2523        ALOGE("[%s] does not support compression format %d",
2524             mComponentName.c_str(), compressionFormat);
2525
2526        return err;
2527    }
2528
2529    def.nPortIndex = kPortIndexOutput;
2530
2531    err = mOMX->getParameter(
2532            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2533
2534    if (err != OK) {
2535        return err;
2536    }
2537
2538    video_def->nFrameWidth = width;
2539    video_def->nFrameHeight = height;
2540    video_def->xFramerate = 0;
2541    video_def->nBitrate = bitrate;
2542    video_def->eCompressionFormat = compressionFormat;
2543    video_def->eColorFormat = OMX_COLOR_FormatUnused;
2544
2545    err = mOMX->setParameter(
2546            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2547
2548    if (err != OK) {
2549        ALOGE("[%s] failed to set output port definition parameters.",
2550              mComponentName.c_str());
2551
2552        return err;
2553    }
2554
2555    switch (compressionFormat) {
2556        case OMX_VIDEO_CodingMPEG4:
2557            err = setupMPEG4EncoderParameters(msg);
2558            break;
2559
2560        case OMX_VIDEO_CodingH263:
2561            err = setupH263EncoderParameters(msg);
2562            break;
2563
2564        case OMX_VIDEO_CodingAVC:
2565            err = setupAVCEncoderParameters(msg);
2566            break;
2567
2568        case OMX_VIDEO_CodingHEVC:
2569            err = setupHEVCEncoderParameters(msg);
2570            break;
2571
2572        case OMX_VIDEO_CodingVP8:
2573        case OMX_VIDEO_CodingVP9:
2574            err = setupVPXEncoderParameters(msg);
2575            break;
2576
2577        default:
2578            break;
2579    }
2580
2581    ALOGI("setupVideoEncoder succeeded");
2582
2583    return err;
2584}
2585
2586status_t ACodec::setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode) {
2587    OMX_VIDEO_PARAM_INTRAREFRESHTYPE params;
2588    InitOMXParams(&params);
2589    params.nPortIndex = kPortIndexOutput;
2590
2591    params.eRefreshMode = static_cast<OMX_VIDEO_INTRAREFRESHTYPE>(mode);
2592
2593    if (params.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic ||
2594            params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) {
2595        int32_t mbs;
2596        if (!msg->findInt32("intra-refresh-CIR-mbs", &mbs)) {
2597            return INVALID_OPERATION;
2598        }
2599        params.nCirMBs = mbs;
2600    }
2601
2602    if (params.eRefreshMode == OMX_VIDEO_IntraRefreshAdaptive ||
2603            params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) {
2604        int32_t mbs;
2605        if (!msg->findInt32("intra-refresh-AIR-mbs", &mbs)) {
2606            return INVALID_OPERATION;
2607        }
2608        params.nAirMBs = mbs;
2609
2610        int32_t ref;
2611        if (!msg->findInt32("intra-refresh-AIR-ref", &ref)) {
2612            return INVALID_OPERATION;
2613        }
2614        params.nAirRef = ref;
2615    }
2616
2617    status_t err = mOMX->setParameter(
2618            mNode, OMX_IndexParamVideoIntraRefresh,
2619            &params, sizeof(params));
2620    return err;
2621}
2622
2623static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) {
2624    if (iFramesInterval < 0) {
2625        return 0xFFFFFFFF;
2626    } else if (iFramesInterval == 0) {
2627        return 0;
2628    }
2629    OMX_U32 ret = frameRate * iFramesInterval;
2630    return ret;
2631}
2632
2633static OMX_VIDEO_CONTROLRATETYPE getBitrateMode(const sp<AMessage> &msg) {
2634    int32_t tmp;
2635    if (!msg->findInt32("bitrate-mode", &tmp)) {
2636        return OMX_Video_ControlRateVariable;
2637    }
2638
2639    return static_cast<OMX_VIDEO_CONTROLRATETYPE>(tmp);
2640}
2641
2642status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) {
2643    int32_t bitrate, iFrameInterval;
2644    if (!msg->findInt32("bitrate", &bitrate)
2645            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
2646        return INVALID_OPERATION;
2647    }
2648
2649    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
2650
2651    float frameRate;
2652    if (!msg->findFloat("frame-rate", &frameRate)) {
2653        int32_t tmp;
2654        if (!msg->findInt32("frame-rate", &tmp)) {
2655            return INVALID_OPERATION;
2656        }
2657        frameRate = (float)tmp;
2658    }
2659
2660    OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type;
2661    InitOMXParams(&mpeg4type);
2662    mpeg4type.nPortIndex = kPortIndexOutput;
2663
2664    status_t err = mOMX->getParameter(
2665            mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
2666
2667    if (err != OK) {
2668        return err;
2669    }
2670
2671    mpeg4type.nSliceHeaderSpacing = 0;
2672    mpeg4type.bSVH = OMX_FALSE;
2673    mpeg4type.bGov = OMX_FALSE;
2674
2675    mpeg4type.nAllowedPictureTypes =
2676        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
2677
2678    mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
2679    if (mpeg4type.nPFrames == 0) {
2680        mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
2681    }
2682    mpeg4type.nBFrames = 0;
2683    mpeg4type.nIDCVLCThreshold = 0;
2684    mpeg4type.bACPred = OMX_TRUE;
2685    mpeg4type.nMaxPacketSize = 256;
2686    mpeg4type.nTimeIncRes = 1000;
2687    mpeg4type.nHeaderExtension = 0;
2688    mpeg4type.bReversibleVLC = OMX_FALSE;
2689
2690    int32_t profile;
2691    if (msg->findInt32("profile", &profile)) {
2692        int32_t level;
2693        if (!msg->findInt32("level", &level)) {
2694            return INVALID_OPERATION;
2695        }
2696
2697        err = verifySupportForProfileAndLevel(profile, level);
2698
2699        if (err != OK) {
2700            return err;
2701        }
2702
2703        mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile);
2704        mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level);
2705    }
2706
2707    err = mOMX->setParameter(
2708            mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
2709
2710    if (err != OK) {
2711        return err;
2712    }
2713
2714    err = configureBitrate(bitrate, bitrateMode);
2715
2716    if (err != OK) {
2717        return err;
2718    }
2719
2720    return setupErrorCorrectionParameters();
2721}
2722
2723status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) {
2724    int32_t bitrate, iFrameInterval;
2725    if (!msg->findInt32("bitrate", &bitrate)
2726            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
2727        return INVALID_OPERATION;
2728    }
2729
2730    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
2731
2732    float frameRate;
2733    if (!msg->findFloat("frame-rate", &frameRate)) {
2734        int32_t tmp;
2735        if (!msg->findInt32("frame-rate", &tmp)) {
2736            return INVALID_OPERATION;
2737        }
2738        frameRate = (float)tmp;
2739    }
2740
2741    OMX_VIDEO_PARAM_H263TYPE h263type;
2742    InitOMXParams(&h263type);
2743    h263type.nPortIndex = kPortIndexOutput;
2744
2745    status_t err = mOMX->getParameter(
2746            mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
2747
2748    if (err != OK) {
2749        return err;
2750    }
2751
2752    h263type.nAllowedPictureTypes =
2753        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
2754
2755    h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
2756    if (h263type.nPFrames == 0) {
2757        h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
2758    }
2759    h263type.nBFrames = 0;
2760
2761    int32_t profile;
2762    if (msg->findInt32("profile", &profile)) {
2763        int32_t level;
2764        if (!msg->findInt32("level", &level)) {
2765            return INVALID_OPERATION;
2766        }
2767
2768        err = verifySupportForProfileAndLevel(profile, level);
2769
2770        if (err != OK) {
2771            return err;
2772        }
2773
2774        h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile);
2775        h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level);
2776    }
2777
2778    h263type.bPLUSPTYPEAllowed = OMX_FALSE;
2779    h263type.bForceRoundingTypeToZero = OMX_FALSE;
2780    h263type.nPictureHeaderRepetition = 0;
2781    h263type.nGOBHeaderInterval = 0;
2782
2783    err = mOMX->setParameter(
2784            mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
2785
2786    if (err != OK) {
2787        return err;
2788    }
2789
2790    err = configureBitrate(bitrate, bitrateMode);
2791
2792    if (err != OK) {
2793        return err;
2794    }
2795
2796    return setupErrorCorrectionParameters();
2797}
2798
2799// static
2800int /* OMX_VIDEO_AVCLEVELTYPE */ ACodec::getAVCLevelFor(
2801        int width, int height, int rate, int bitrate,
2802        OMX_VIDEO_AVCPROFILETYPE profile) {
2803    // convert bitrate to main/baseline profile kbps equivalent
2804    switch (profile) {
2805        case OMX_VIDEO_AVCProfileHigh10:
2806            bitrate = divUp(bitrate, 3000); break;
2807        case OMX_VIDEO_AVCProfileHigh:
2808            bitrate = divUp(bitrate, 1250); break;
2809        default:
2810            bitrate = divUp(bitrate, 1000); break;
2811    }
2812
2813    // convert size and rate to MBs
2814    width = divUp(width, 16);
2815    height = divUp(height, 16);
2816    int mbs = width * height;
2817    rate *= mbs;
2818    int maxDimension = max(width, height);
2819
2820    static const int limits[][5] = {
2821        /*   MBps     MB   dim  bitrate        level */
2822        {    1485,    99,  28,     64, OMX_VIDEO_AVCLevel1  },
2823        {    1485,    99,  28,    128, OMX_VIDEO_AVCLevel1b },
2824        {    3000,   396,  56,    192, OMX_VIDEO_AVCLevel11 },
2825        {    6000,   396,  56,    384, OMX_VIDEO_AVCLevel12 },
2826        {   11880,   396,  56,    768, OMX_VIDEO_AVCLevel13 },
2827        {   11880,   396,  56,   2000, OMX_VIDEO_AVCLevel2  },
2828        {   19800,   792,  79,   4000, OMX_VIDEO_AVCLevel21 },
2829        {   20250,  1620, 113,   4000, OMX_VIDEO_AVCLevel22 },
2830        {   40500,  1620, 113,  10000, OMX_VIDEO_AVCLevel3  },
2831        {  108000,  3600, 169,  14000, OMX_VIDEO_AVCLevel31 },
2832        {  216000,  5120, 202,  20000, OMX_VIDEO_AVCLevel32 },
2833        {  245760,  8192, 256,  20000, OMX_VIDEO_AVCLevel4  },
2834        {  245760,  8192, 256,  50000, OMX_VIDEO_AVCLevel41 },
2835        {  522240,  8704, 263,  50000, OMX_VIDEO_AVCLevel42 },
2836        {  589824, 22080, 420, 135000, OMX_VIDEO_AVCLevel5  },
2837        {  983040, 36864, 543, 240000, OMX_VIDEO_AVCLevel51 },
2838        { 2073600, 36864, 543, 240000, OMX_VIDEO_AVCLevel52 },
2839    };
2840
2841    for (size_t i = 0; i < ARRAY_SIZE(limits); i++) {
2842        const int (&limit)[5] = limits[i];
2843        if (rate <= limit[0] && mbs <= limit[1] && maxDimension <= limit[2]
2844                && bitrate <= limit[3]) {
2845            return limit[4];
2846        }
2847    }
2848    return 0;
2849}
2850
2851status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) {
2852    int32_t bitrate, iFrameInterval;
2853    if (!msg->findInt32("bitrate", &bitrate)
2854            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
2855        return INVALID_OPERATION;
2856    }
2857
2858    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
2859
2860    float frameRate;
2861    if (!msg->findFloat("frame-rate", &frameRate)) {
2862        int32_t tmp;
2863        if (!msg->findInt32("frame-rate", &tmp)) {
2864            return INVALID_OPERATION;
2865        }
2866        frameRate = (float)tmp;
2867    }
2868
2869    status_t err = OK;
2870    int32_t intraRefreshMode = 0;
2871    if (msg->findInt32("intra-refresh-mode", &intraRefreshMode)) {
2872        err = setCyclicIntraMacroblockRefresh(msg, intraRefreshMode);
2873        if (err != OK) {
2874            ALOGE("Setting intra macroblock refresh mode (%d) failed: 0x%x",
2875                    err, intraRefreshMode);
2876            return err;
2877        }
2878    }
2879
2880    OMX_VIDEO_PARAM_AVCTYPE h264type;
2881    InitOMXParams(&h264type);
2882    h264type.nPortIndex = kPortIndexOutput;
2883
2884    err = mOMX->getParameter(
2885            mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
2886
2887    if (err != OK) {
2888        return err;
2889    }
2890
2891    h264type.nAllowedPictureTypes =
2892        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
2893
2894    int32_t profile;
2895    if (msg->findInt32("profile", &profile)) {
2896        int32_t level;
2897        if (!msg->findInt32("level", &level)) {
2898            return INVALID_OPERATION;
2899        }
2900
2901        err = verifySupportForProfileAndLevel(profile, level);
2902
2903        if (err != OK) {
2904            return err;
2905        }
2906
2907        h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile);
2908        h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level);
2909    }
2910
2911    // XXX
2912    if (h264type.eProfile != OMX_VIDEO_AVCProfileBaseline) {
2913        ALOGW("Use baseline profile instead of %d for AVC recording",
2914            h264type.eProfile);
2915        h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
2916    }
2917
2918    if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
2919        h264type.nSliceHeaderSpacing = 0;
2920        h264type.bUseHadamard = OMX_TRUE;
2921        h264type.nRefFrames = 1;
2922        h264type.nBFrames = 0;
2923        h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
2924        if (h264type.nPFrames == 0) {
2925            h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
2926        }
2927        h264type.nRefIdx10ActiveMinus1 = 0;
2928        h264type.nRefIdx11ActiveMinus1 = 0;
2929        h264type.bEntropyCodingCABAC = OMX_FALSE;
2930        h264type.bWeightedPPrediction = OMX_FALSE;
2931        h264type.bconstIpred = OMX_FALSE;
2932        h264type.bDirect8x8Inference = OMX_FALSE;
2933        h264type.bDirectSpatialTemporal = OMX_FALSE;
2934        h264type.nCabacInitIdc = 0;
2935    }
2936
2937    if (h264type.nBFrames != 0) {
2938        h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
2939    }
2940
2941    h264type.bEnableUEP = OMX_FALSE;
2942    h264type.bEnableFMO = OMX_FALSE;
2943    h264type.bEnableASO = OMX_FALSE;
2944    h264type.bEnableRS = OMX_FALSE;
2945    h264type.bFrameMBsOnly = OMX_TRUE;
2946    h264type.bMBAFF = OMX_FALSE;
2947    h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
2948
2949    err = mOMX->setParameter(
2950            mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
2951
2952    if (err != OK) {
2953        return err;
2954    }
2955
2956    return configureBitrate(bitrate, bitrateMode);
2957}
2958
2959status_t ACodec::setupHEVCEncoderParameters(const sp<AMessage> &msg) {
2960    int32_t bitrate, iFrameInterval;
2961    if (!msg->findInt32("bitrate", &bitrate)
2962            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
2963        return INVALID_OPERATION;
2964    }
2965
2966    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
2967
2968    float frameRate;
2969    if (!msg->findFloat("frame-rate", &frameRate)) {
2970        int32_t tmp;
2971        if (!msg->findInt32("frame-rate", &tmp)) {
2972            return INVALID_OPERATION;
2973        }
2974        frameRate = (float)tmp;
2975    }
2976
2977    OMX_VIDEO_PARAM_HEVCTYPE hevcType;
2978    InitOMXParams(&hevcType);
2979    hevcType.nPortIndex = kPortIndexOutput;
2980
2981    status_t err = OK;
2982    err = mOMX->getParameter(
2983            mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
2984    if (err != OK) {
2985        return err;
2986    }
2987
2988    int32_t profile;
2989    if (msg->findInt32("profile", &profile)) {
2990        int32_t level;
2991        if (!msg->findInt32("level", &level)) {
2992            return INVALID_OPERATION;
2993        }
2994
2995        err = verifySupportForProfileAndLevel(profile, level);
2996        if (err != OK) {
2997            return err;
2998        }
2999
3000        hevcType.eProfile = static_cast<OMX_VIDEO_HEVCPROFILETYPE>(profile);
3001        hevcType.eLevel = static_cast<OMX_VIDEO_HEVCLEVELTYPE>(level);
3002    }
3003
3004    // TODO: Need OMX structure definition for setting iFrameInterval
3005
3006    err = mOMX->setParameter(
3007            mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
3008    if (err != OK) {
3009        return err;
3010    }
3011
3012    return configureBitrate(bitrate, bitrateMode);
3013}
3014
3015status_t ACodec::setupVPXEncoderParameters(const sp<AMessage> &msg) {
3016    int32_t bitrate;
3017    int32_t iFrameInterval = 0;
3018    size_t tsLayers = 0;
3019    OMX_VIDEO_ANDROID_VPXTEMPORALLAYERPATTERNTYPE pattern =
3020        OMX_VIDEO_VPXTemporalLayerPatternNone;
3021    static const uint32_t kVp8LayerRateAlloction
3022        [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS]
3023        [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS] = {
3024        {100, 100, 100},  // 1 layer
3025        { 60, 100, 100},  // 2 layers {60%, 40%}
3026        { 40,  60, 100},  // 3 layers {40%, 20%, 40%}
3027    };
3028    if (!msg->findInt32("bitrate", &bitrate)) {
3029        return INVALID_OPERATION;
3030    }
3031    msg->findInt32("i-frame-interval", &iFrameInterval);
3032
3033    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
3034
3035    float frameRate;
3036    if (!msg->findFloat("frame-rate", &frameRate)) {
3037        int32_t tmp;
3038        if (!msg->findInt32("frame-rate", &tmp)) {
3039            return INVALID_OPERATION;
3040        }
3041        frameRate = (float)tmp;
3042    }
3043
3044    AString tsSchema;
3045    if (msg->findString("ts-schema", &tsSchema)) {
3046        if (tsSchema == "webrtc.vp8.1-layer") {
3047            pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
3048            tsLayers = 1;
3049        } else if (tsSchema == "webrtc.vp8.2-layer") {
3050            pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
3051            tsLayers = 2;
3052        } else if (tsSchema == "webrtc.vp8.3-layer") {
3053            pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
3054            tsLayers = 3;
3055        } else {
3056            ALOGW("Unsupported ts-schema [%s]", tsSchema.c_str());
3057        }
3058    }
3059
3060    OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type;
3061    InitOMXParams(&vp8type);
3062    vp8type.nPortIndex = kPortIndexOutput;
3063    status_t err = mOMX->getParameter(
3064            mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
3065            &vp8type, sizeof(vp8type));
3066
3067    if (err == OK) {
3068        if (iFrameInterval > 0) {
3069            vp8type.nKeyFrameInterval = setPFramesSpacing(iFrameInterval, frameRate);
3070        }
3071        vp8type.eTemporalPattern = pattern;
3072        vp8type.nTemporalLayerCount = tsLayers;
3073        if (tsLayers > 0) {
3074            for (size_t i = 0; i < OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS; i++) {
3075                vp8type.nTemporalLayerBitrateRatio[i] =
3076                    kVp8LayerRateAlloction[tsLayers - 1][i];
3077            }
3078        }
3079        if (bitrateMode == OMX_Video_ControlRateConstant) {
3080            vp8type.nMinQuantizer = 2;
3081            vp8type.nMaxQuantizer = 63;
3082        }
3083
3084        err = mOMX->setParameter(
3085                mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
3086                &vp8type, sizeof(vp8type));
3087        if (err != OK) {
3088            ALOGW("Extended VP8 parameters set failed: %d", err);
3089        }
3090    }
3091
3092    return configureBitrate(bitrate, bitrateMode);
3093}
3094
3095status_t ACodec::verifySupportForProfileAndLevel(
3096        int32_t profile, int32_t level) {
3097    OMX_VIDEO_PARAM_PROFILELEVELTYPE params;
3098    InitOMXParams(&params);
3099    params.nPortIndex = kPortIndexOutput;
3100
3101    for (params.nProfileIndex = 0;; ++params.nProfileIndex) {
3102        status_t err = mOMX->getParameter(
3103                mNode,
3104                OMX_IndexParamVideoProfileLevelQuerySupported,
3105                &params,
3106                sizeof(params));
3107
3108        if (err != OK) {
3109            return err;
3110        }
3111
3112        int32_t supportedProfile = static_cast<int32_t>(params.eProfile);
3113        int32_t supportedLevel = static_cast<int32_t>(params.eLevel);
3114
3115        if (profile == supportedProfile && level <= supportedLevel) {
3116            return OK;
3117        }
3118    }
3119}
3120
3121status_t ACodec::configureBitrate(
3122        int32_t bitrate, OMX_VIDEO_CONTROLRATETYPE bitrateMode) {
3123    OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
3124    InitOMXParams(&bitrateType);
3125    bitrateType.nPortIndex = kPortIndexOutput;
3126
3127    status_t err = mOMX->getParameter(
3128            mNode, OMX_IndexParamVideoBitrate,
3129            &bitrateType, sizeof(bitrateType));
3130
3131    if (err != OK) {
3132        return err;
3133    }
3134
3135    bitrateType.eControlRate = bitrateMode;
3136    bitrateType.nTargetBitrate = bitrate;
3137
3138    return mOMX->setParameter(
3139            mNode, OMX_IndexParamVideoBitrate,
3140            &bitrateType, sizeof(bitrateType));
3141}
3142
3143status_t ACodec::setupErrorCorrectionParameters() {
3144    OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
3145    InitOMXParams(&errorCorrectionType);
3146    errorCorrectionType.nPortIndex = kPortIndexOutput;
3147
3148    status_t err = mOMX->getParameter(
3149            mNode, OMX_IndexParamVideoErrorCorrection,
3150            &errorCorrectionType, sizeof(errorCorrectionType));
3151
3152    if (err != OK) {
3153        return OK;  // Optional feature. Ignore this failure
3154    }
3155
3156    errorCorrectionType.bEnableHEC = OMX_FALSE;
3157    errorCorrectionType.bEnableResync = OMX_TRUE;
3158    errorCorrectionType.nResynchMarkerSpacing = 256;
3159    errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
3160    errorCorrectionType.bEnableRVLC = OMX_FALSE;
3161
3162    return mOMX->setParameter(
3163            mNode, OMX_IndexParamVideoErrorCorrection,
3164            &errorCorrectionType, sizeof(errorCorrectionType));
3165}
3166
3167status_t ACodec::setVideoFormatOnPort(
3168        OMX_U32 portIndex,
3169        int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat,
3170        float frameRate) {
3171    OMX_PARAM_PORTDEFINITIONTYPE def;
3172    InitOMXParams(&def);
3173    def.nPortIndex = portIndex;
3174
3175    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
3176
3177    status_t err = mOMX->getParameter(
3178            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
3179
3180    CHECK_EQ(err, (status_t)OK);
3181
3182    if (portIndex == kPortIndexInput) {
3183        // XXX Need a (much) better heuristic to compute input buffer sizes.
3184        const size_t X = 64 * 1024;
3185        if (def.nBufferSize < X) {
3186            def.nBufferSize = X;
3187        }
3188    }
3189
3190    CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
3191
3192    video_def->nFrameWidth = width;
3193    video_def->nFrameHeight = height;
3194
3195    if (portIndex == kPortIndexInput) {
3196        video_def->eCompressionFormat = compressionFormat;
3197        video_def->eColorFormat = OMX_COLOR_FormatUnused;
3198        if (frameRate >= 0) {
3199            video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f);
3200        }
3201    }
3202
3203    err = mOMX->setParameter(
3204            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
3205
3206    return err;
3207}
3208
3209status_t ACodec::initNativeWindow() {
3210    if (mNativeWindow != NULL) {
3211        return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE);
3212    }
3213
3214    mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE);
3215    return OK;
3216}
3217
3218size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const {
3219    size_t n = 0;
3220
3221    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
3222        const BufferInfo &info = mBuffers[portIndex].itemAt(i);
3223
3224        if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) {
3225            ++n;
3226        }
3227    }
3228
3229    return n;
3230}
3231
3232size_t ACodec::countBuffersOwnedByNativeWindow() const {
3233    size_t n = 0;
3234
3235    for (size_t i = 0; i < mBuffers[kPortIndexOutput].size(); ++i) {
3236        const BufferInfo &info = mBuffers[kPortIndexOutput].itemAt(i);
3237
3238        if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
3239            ++n;
3240        }
3241    }
3242
3243    return n;
3244}
3245
3246void ACodec::waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs() {
3247    if (mNativeWindow == NULL) {
3248        return;
3249    }
3250
3251    while (countBuffersOwnedByNativeWindow() > mNumUndequeuedBuffers
3252            && dequeueBufferFromNativeWindow() != NULL) {
3253        // these buffers will be submitted as regular buffers; account for this
3254        if (mStoreMetaDataInOutputBuffers && mMetaDataBuffersToSubmit > 0) {
3255            --mMetaDataBuffersToSubmit;
3256        }
3257    }
3258}
3259
3260bool ACodec::allYourBuffersAreBelongToUs(
3261        OMX_U32 portIndex) {
3262    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
3263        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
3264
3265        if (info->mStatus != BufferInfo::OWNED_BY_US
3266                && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
3267            ALOGV("[%s] Buffer %u on port %u still has status %d",
3268                    mComponentName.c_str(),
3269                    info->mBufferID, portIndex, info->mStatus);
3270            return false;
3271        }
3272    }
3273
3274    return true;
3275}
3276
3277bool ACodec::allYourBuffersAreBelongToUs() {
3278    return allYourBuffersAreBelongToUs(kPortIndexInput)
3279        && allYourBuffersAreBelongToUs(kPortIndexOutput);
3280}
3281
3282void ACodec::deferMessage(const sp<AMessage> &msg) {
3283    mDeferredQueue.push_back(msg);
3284}
3285
3286void ACodec::processDeferredMessages() {
3287    List<sp<AMessage> > queue = mDeferredQueue;
3288    mDeferredQueue.clear();
3289
3290    List<sp<AMessage> >::iterator it = queue.begin();
3291    while (it != queue.end()) {
3292        onMessageReceived(*it++);
3293    }
3294}
3295
3296// static
3297bool ACodec::describeDefaultColorFormat(DescribeColorFormatParams &params) {
3298    MediaImage &image = params.sMediaImage;
3299    memset(&image, 0, sizeof(image));
3300
3301    image.mType = MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
3302    image.mNumPlanes = 0;
3303
3304    const OMX_COLOR_FORMATTYPE fmt = params.eColorFormat;
3305    image.mWidth = params.nFrameWidth;
3306    image.mHeight = params.nFrameHeight;
3307
3308    // only supporting YUV420
3309    if (fmt != OMX_COLOR_FormatYUV420Planar &&
3310        fmt != OMX_COLOR_FormatYUV420PackedPlanar &&
3311        fmt != OMX_COLOR_FormatYUV420SemiPlanar &&
3312        fmt != OMX_COLOR_FormatYUV420PackedSemiPlanar &&
3313        fmt != HAL_PIXEL_FORMAT_YV12) {
3314        ALOGW("do not know color format 0x%x = %d", fmt, fmt);
3315        return false;
3316    }
3317
3318    // TEMPORARY FIX for some vendors that advertise sliceHeight as 0
3319    if (params.nStride != 0 && params.nSliceHeight == 0) {
3320        ALOGW("using sliceHeight=%u instead of what codec advertised (=0)",
3321                params.nFrameHeight);
3322        params.nSliceHeight = params.nFrameHeight;
3323    }
3324
3325    // we need stride and slice-height to be non-zero
3326    if (params.nStride == 0 || params.nSliceHeight == 0) {
3327        ALOGW("cannot describe color format 0x%x = %d with stride=%u and sliceHeight=%u",
3328                fmt, fmt, params.nStride, params.nSliceHeight);
3329        return false;
3330    }
3331
3332    // set-up YUV format
3333    image.mType = MediaImage::MEDIA_IMAGE_TYPE_YUV;
3334    image.mNumPlanes = 3;
3335    image.mBitDepth = 8;
3336    image.mPlane[image.Y].mOffset = 0;
3337    image.mPlane[image.Y].mColInc = 1;
3338    image.mPlane[image.Y].mRowInc = params.nStride;
3339    image.mPlane[image.Y].mHorizSubsampling = 1;
3340    image.mPlane[image.Y].mVertSubsampling = 1;
3341
3342    switch ((int)fmt) {
3343        case HAL_PIXEL_FORMAT_YV12:
3344            if (params.bUsingNativeBuffers) {
3345                size_t ystride = align(params.nStride, 16);
3346                size_t cstride = align(params.nStride / 2, 16);
3347                image.mPlane[image.Y].mRowInc = ystride;
3348
3349                image.mPlane[image.V].mOffset = ystride * params.nSliceHeight;
3350                image.mPlane[image.V].mColInc = 1;
3351                image.mPlane[image.V].mRowInc = cstride;
3352                image.mPlane[image.V].mHorizSubsampling = 2;
3353                image.mPlane[image.V].mVertSubsampling = 2;
3354
3355                image.mPlane[image.U].mOffset = image.mPlane[image.V].mOffset
3356                        + (cstride * params.nSliceHeight / 2);
3357                image.mPlane[image.U].mColInc = 1;
3358                image.mPlane[image.U].mRowInc = cstride;
3359                image.mPlane[image.U].mHorizSubsampling = 2;
3360                image.mPlane[image.U].mVertSubsampling = 2;
3361                break;
3362            } else {
3363                // fall through as YV12 is used for YUV420Planar by some codecs
3364            }
3365
3366        case OMX_COLOR_FormatYUV420Planar:
3367        case OMX_COLOR_FormatYUV420PackedPlanar:
3368            image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight;
3369            image.mPlane[image.U].mColInc = 1;
3370            image.mPlane[image.U].mRowInc = params.nStride / 2;
3371            image.mPlane[image.U].mHorizSubsampling = 2;
3372            image.mPlane[image.U].mVertSubsampling = 2;
3373
3374            image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset
3375                    + (params.nStride * params.nSliceHeight / 4);
3376            image.mPlane[image.V].mColInc = 1;
3377            image.mPlane[image.V].mRowInc = params.nStride / 2;
3378            image.mPlane[image.V].mHorizSubsampling = 2;
3379            image.mPlane[image.V].mVertSubsampling = 2;
3380            break;
3381
3382        case OMX_COLOR_FormatYUV420SemiPlanar:
3383            // FIXME: NV21 for sw-encoder, NV12 for decoder and hw-encoder
3384        case OMX_COLOR_FormatYUV420PackedSemiPlanar:
3385            // NV12
3386            image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight;
3387            image.mPlane[image.U].mColInc = 2;
3388            image.mPlane[image.U].mRowInc = params.nStride;
3389            image.mPlane[image.U].mHorizSubsampling = 2;
3390            image.mPlane[image.U].mVertSubsampling = 2;
3391
3392            image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset + 1;
3393            image.mPlane[image.V].mColInc = 2;
3394            image.mPlane[image.V].mRowInc = params.nStride;
3395            image.mPlane[image.V].mHorizSubsampling = 2;
3396            image.mPlane[image.V].mVertSubsampling = 2;
3397            break;
3398
3399        default:
3400            TRESPASS();
3401    }
3402    return true;
3403}
3404
3405// static
3406bool ACodec::describeColorFormat(
3407        const sp<IOMX> &omx, IOMX::node_id node,
3408        DescribeColorFormatParams &describeParams)
3409{
3410    OMX_INDEXTYPE describeColorFormatIndex;
3411    if (omx->getExtensionIndex(
3412            node, "OMX.google.android.index.describeColorFormat",
3413            &describeColorFormatIndex) != OK ||
3414        omx->getParameter(
3415            node, describeColorFormatIndex,
3416            &describeParams, sizeof(describeParams)) != OK) {
3417        return describeDefaultColorFormat(describeParams);
3418    }
3419    return describeParams.sMediaImage.mType !=
3420            MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
3421}
3422
3423// static
3424bool ACodec::isFlexibleColorFormat(
3425         const sp<IOMX> &omx, IOMX::node_id node,
3426         uint32_t colorFormat, bool usingNativeBuffers, OMX_U32 *flexibleEquivalent) {
3427    DescribeColorFormatParams describeParams;
3428    InitOMXParams(&describeParams);
3429    describeParams.eColorFormat = (OMX_COLOR_FORMATTYPE)colorFormat;
3430    // reasonable dummy values
3431    describeParams.nFrameWidth = 128;
3432    describeParams.nFrameHeight = 128;
3433    describeParams.nStride = 128;
3434    describeParams.nSliceHeight = 128;
3435    describeParams.bUsingNativeBuffers = (OMX_BOOL)usingNativeBuffers;
3436
3437    CHECK(flexibleEquivalent != NULL);
3438
3439    if (!describeColorFormat(omx, node, describeParams)) {
3440        return false;
3441    }
3442
3443    const MediaImage &img = describeParams.sMediaImage;
3444    if (img.mType == MediaImage::MEDIA_IMAGE_TYPE_YUV) {
3445        if (img.mNumPlanes != 3 ||
3446            img.mPlane[img.Y].mHorizSubsampling != 1 ||
3447            img.mPlane[img.Y].mVertSubsampling != 1) {
3448            return false;
3449        }
3450
3451        // YUV 420
3452        if (img.mPlane[img.U].mHorizSubsampling == 2
3453                && img.mPlane[img.U].mVertSubsampling == 2
3454                && img.mPlane[img.V].mHorizSubsampling == 2
3455                && img.mPlane[img.V].mVertSubsampling == 2) {
3456            // possible flexible YUV420 format
3457            if (img.mBitDepth <= 8) {
3458               *flexibleEquivalent = OMX_COLOR_FormatYUV420Flexible;
3459               return true;
3460            }
3461        }
3462    }
3463    return false;
3464}
3465
3466status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> &notify) {
3467    // TODO: catch errors an return them instead of using CHECK
3468    OMX_PARAM_PORTDEFINITIONTYPE def;
3469    InitOMXParams(&def);
3470    def.nPortIndex = portIndex;
3471
3472    CHECK_EQ(mOMX->getParameter(
3473                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)),
3474             (status_t)OK);
3475
3476    CHECK_EQ((int)def.eDir,
3477            (int)(portIndex == kPortIndexOutput ? OMX_DirOutput : OMX_DirInput));
3478
3479    switch (def.eDomain) {
3480        case OMX_PortDomainVideo:
3481        {
3482            OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
3483            switch ((int)videoDef->eCompressionFormat) {
3484                case OMX_VIDEO_CodingUnused:
3485                {
3486                    CHECK(mIsEncoder ^ (portIndex == kPortIndexOutput));
3487                    notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW);
3488
3489                    notify->setInt32("stride", videoDef->nStride);
3490                    notify->setInt32("slice-height", videoDef->nSliceHeight);
3491                    notify->setInt32("color-format", videoDef->eColorFormat);
3492
3493                    if (mNativeWindow == NULL) {
3494                        DescribeColorFormatParams describeParams;
3495                        InitOMXParams(&describeParams);
3496                        describeParams.eColorFormat = videoDef->eColorFormat;
3497                        describeParams.nFrameWidth = videoDef->nFrameWidth;
3498                        describeParams.nFrameHeight = videoDef->nFrameHeight;
3499                        describeParams.nStride = videoDef->nStride;
3500                        describeParams.nSliceHeight = videoDef->nSliceHeight;
3501                        describeParams.bUsingNativeBuffers = OMX_FALSE;
3502
3503                        if (describeColorFormat(mOMX, mNode, describeParams)) {
3504                            notify->setBuffer(
3505                                    "image-data",
3506                                    ABuffer::CreateAsCopy(
3507                                            &describeParams.sMediaImage,
3508                                            sizeof(describeParams.sMediaImage)));
3509
3510                            MediaImage *img = &describeParams.sMediaImage;
3511                            ALOGV("[%s] MediaImage { F(%zux%zu) @%zu+%zu+%zu @%zu+%zu+%zu @%zu+%zu+%zu }",
3512                                    mComponentName.c_str(), img->mWidth, img->mHeight,
3513                                    img->mPlane[0].mOffset, img->mPlane[0].mColInc, img->mPlane[0].mRowInc,
3514                                    img->mPlane[1].mOffset, img->mPlane[1].mColInc, img->mPlane[1].mRowInc,
3515                                    img->mPlane[2].mOffset, img->mPlane[2].mColInc, img->mPlane[2].mRowInc);
3516                        }
3517                    }
3518
3519                    if (portIndex != kPortIndexOutput) {
3520                        // TODO: also get input crop
3521                        break;
3522                    }
3523
3524                    OMX_CONFIG_RECTTYPE rect;
3525                    InitOMXParams(&rect);
3526                    rect.nPortIndex = portIndex;
3527
3528                    if (mOMX->getConfig(
3529                                mNode,
3530                                (portIndex == kPortIndexOutput ?
3531                                        OMX_IndexConfigCommonOutputCrop :
3532                                        OMX_IndexConfigCommonInputCrop),
3533                                &rect, sizeof(rect)) != OK) {
3534                        rect.nLeft = 0;
3535                        rect.nTop = 0;
3536                        rect.nWidth = videoDef->nFrameWidth;
3537                        rect.nHeight = videoDef->nFrameHeight;
3538                    }
3539
3540                    CHECK_GE(rect.nLeft, 0);
3541                    CHECK_GE(rect.nTop, 0);
3542                    CHECK_GE(rect.nWidth, 0u);
3543                    CHECK_GE(rect.nHeight, 0u);
3544                    CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth);
3545                    CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight);
3546
3547                    notify->setRect(
3548                            "crop",
3549                            rect.nLeft,
3550                            rect.nTop,
3551                            rect.nLeft + rect.nWidth - 1,
3552                            rect.nTop + rect.nHeight - 1);
3553
3554                    break;
3555                }
3556
3557                case OMX_VIDEO_CodingVP8:
3558                case OMX_VIDEO_CodingVP9:
3559                {
3560                    OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type;
3561                    InitOMXParams(&vp8type);
3562                    vp8type.nPortIndex = kPortIndexOutput;
3563                    status_t err = mOMX->getParameter(
3564                            mNode,
3565                            (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
3566                            &vp8type,
3567                            sizeof(vp8type));
3568
3569                    if (err == OK) {
3570                        AString tsSchema = "none";
3571                        if (vp8type.eTemporalPattern
3572                                == OMX_VIDEO_VPXTemporalLayerPatternWebRTC) {
3573                            switch (vp8type.nTemporalLayerCount) {
3574                                case 1:
3575                                {
3576                                    tsSchema = "webrtc.vp8.1-layer";
3577                                    break;
3578                                }
3579                                case 2:
3580                                {
3581                                    tsSchema = "webrtc.vp8.2-layer";
3582                                    break;
3583                                }
3584                                case 3:
3585                                {
3586                                    tsSchema = "webrtc.vp8.3-layer";
3587                                    break;
3588                                }
3589                                default:
3590                                {
3591                                    break;
3592                                }
3593                            }
3594                        }
3595                        notify->setString("ts-schema", tsSchema);
3596                    }
3597                    // Fall through to set up mime.
3598                }
3599
3600                default:
3601                {
3602                    CHECK(mIsEncoder ^ (portIndex == kPortIndexInput));
3603                    AString mime;
3604                    if (GetMimeTypeForVideoCoding(
3605                        videoDef->eCompressionFormat, &mime) != OK) {
3606                        notify->setString("mime", "application/octet-stream");
3607                    } else {
3608                        notify->setString("mime", mime.c_str());
3609                    }
3610                    break;
3611                }
3612            }
3613            notify->setInt32("width", videoDef->nFrameWidth);
3614            notify->setInt32("height", videoDef->nFrameHeight);
3615            ALOGV("[%s] %s format is %s", mComponentName.c_str(),
3616                    portIndex == kPortIndexInput ? "input" : "output",
3617                    notify->debugString().c_str());
3618
3619            break;
3620        }
3621
3622        case OMX_PortDomainAudio:
3623        {
3624            OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
3625
3626            switch ((int)audioDef->eEncoding) {
3627                case OMX_AUDIO_CodingPCM:
3628                {
3629                    OMX_AUDIO_PARAM_PCMMODETYPE params;
3630                    InitOMXParams(&params);
3631                    params.nPortIndex = portIndex;
3632
3633                    CHECK_EQ(mOMX->getParameter(
3634                                mNode, OMX_IndexParamAudioPcm,
3635                                &params, sizeof(params)),
3636                             (status_t)OK);
3637
3638                    CHECK_GT(params.nChannels, 0);
3639                    CHECK(params.nChannels == 1 || params.bInterleaved);
3640                    CHECK_EQ(params.nBitPerSample, 16u);
3641
3642                    CHECK_EQ((int)params.eNumData,
3643                             (int)OMX_NumericalDataSigned);
3644
3645                    CHECK_EQ((int)params.ePCMMode,
3646                             (int)OMX_AUDIO_PCMModeLinear);
3647
3648                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
3649                    notify->setInt32("channel-count", params.nChannels);
3650                    notify->setInt32("sample-rate", params.nSamplingRate);
3651
3652                    if (mChannelMaskPresent) {
3653                        notify->setInt32("channel-mask", mChannelMask);
3654                    }
3655                    break;
3656                }
3657
3658                case OMX_AUDIO_CodingAAC:
3659                {
3660                    OMX_AUDIO_PARAM_AACPROFILETYPE params;
3661                    InitOMXParams(&params);
3662                    params.nPortIndex = portIndex;
3663
3664                    CHECK_EQ(mOMX->getParameter(
3665                                mNode, OMX_IndexParamAudioAac,
3666                                &params, sizeof(params)),
3667                             (status_t)OK);
3668
3669                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
3670                    notify->setInt32("channel-count", params.nChannels);
3671                    notify->setInt32("sample-rate", params.nSampleRate);
3672                    break;
3673                }
3674
3675                case OMX_AUDIO_CodingAMR:
3676                {
3677                    OMX_AUDIO_PARAM_AMRTYPE params;
3678                    InitOMXParams(&params);
3679                    params.nPortIndex = portIndex;
3680
3681                    CHECK_EQ(mOMX->getParameter(
3682                                mNode, OMX_IndexParamAudioAmr,
3683                                &params, sizeof(params)),
3684                             (status_t)OK);
3685
3686                    notify->setInt32("channel-count", 1);
3687                    if (params.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0) {
3688                        notify->setString(
3689                                "mime", MEDIA_MIMETYPE_AUDIO_AMR_WB);
3690
3691                        notify->setInt32("sample-rate", 16000);
3692                    } else {
3693                        notify->setString(
3694                                "mime", MEDIA_MIMETYPE_AUDIO_AMR_NB);
3695
3696                        notify->setInt32("sample-rate", 8000);
3697                    }
3698                    break;
3699                }
3700
3701                case OMX_AUDIO_CodingFLAC:
3702                {
3703                    OMX_AUDIO_PARAM_FLACTYPE params;
3704                    InitOMXParams(&params);
3705                    params.nPortIndex = portIndex;
3706
3707                    CHECK_EQ(mOMX->getParameter(
3708                                mNode, OMX_IndexParamAudioFlac,
3709                                &params, sizeof(params)),
3710                             (status_t)OK);
3711
3712                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_FLAC);
3713                    notify->setInt32("channel-count", params.nChannels);
3714                    notify->setInt32("sample-rate", params.nSampleRate);
3715                    break;
3716                }
3717
3718                case OMX_AUDIO_CodingMP3:
3719                {
3720                    OMX_AUDIO_PARAM_MP3TYPE params;
3721                    InitOMXParams(&params);
3722                    params.nPortIndex = portIndex;
3723
3724                    CHECK_EQ(mOMX->getParameter(
3725                                mNode, OMX_IndexParamAudioMp3,
3726                                &params, sizeof(params)),
3727                             (status_t)OK);
3728
3729                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MPEG);
3730                    notify->setInt32("channel-count", params.nChannels);
3731                    notify->setInt32("sample-rate", params.nSampleRate);
3732                    break;
3733                }
3734
3735                case OMX_AUDIO_CodingVORBIS:
3736                {
3737                    OMX_AUDIO_PARAM_VORBISTYPE params;
3738                    InitOMXParams(&params);
3739                    params.nPortIndex = portIndex;
3740
3741                    CHECK_EQ(mOMX->getParameter(
3742                                mNode, OMX_IndexParamAudioVorbis,
3743                                &params, sizeof(params)),
3744                             (status_t)OK);
3745
3746                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_VORBIS);
3747                    notify->setInt32("channel-count", params.nChannels);
3748                    notify->setInt32("sample-rate", params.nSampleRate);
3749                    break;
3750                }
3751
3752                case OMX_AUDIO_CodingAndroidAC3:
3753                {
3754                    OMX_AUDIO_PARAM_ANDROID_AC3TYPE params;
3755                    InitOMXParams(&params);
3756                    params.nPortIndex = portIndex;
3757
3758                    CHECK_EQ((status_t)OK, mOMX->getParameter(
3759                            mNode,
3760                            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
3761                            &params,
3762                            sizeof(params)));
3763
3764                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AC3);
3765                    notify->setInt32("channel-count", params.nChannels);
3766                    notify->setInt32("sample-rate", params.nSampleRate);
3767                    break;
3768                }
3769
3770                case OMX_AUDIO_CodingAndroidEAC3:
3771                {
3772                    OMX_AUDIO_PARAM_ANDROID_EAC3TYPE params;
3773                    InitOMXParams(&params);
3774                    params.nPortIndex = portIndex;
3775
3776                    CHECK_EQ((status_t)OK, mOMX->getParameter(
3777                            mNode,
3778                            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
3779                            &params,
3780                            sizeof(params)));
3781
3782                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_EAC3);
3783                    notify->setInt32("channel-count", params.nChannels);
3784                    notify->setInt32("sample-rate", params.nSampleRate);
3785                    break;
3786                }
3787
3788                case OMX_AUDIO_CodingAndroidOPUS:
3789                {
3790                    OMX_AUDIO_PARAM_ANDROID_OPUSTYPE params;
3791                    InitOMXParams(&params);
3792                    params.nPortIndex = portIndex;
3793
3794                    CHECK_EQ((status_t)OK, mOMX->getParameter(
3795                            mNode,
3796                            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus,
3797                            &params,
3798                            sizeof(params)));
3799
3800                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_OPUS);
3801                    notify->setInt32("channel-count", params.nChannels);
3802                    notify->setInt32("sample-rate", params.nSampleRate);
3803                    break;
3804                }
3805
3806                case OMX_AUDIO_CodingG711:
3807                {
3808                    OMX_AUDIO_PARAM_PCMMODETYPE params;
3809                    InitOMXParams(&params);
3810                    params.nPortIndex = portIndex;
3811
3812                    CHECK_EQ((status_t)OK, mOMX->getParameter(
3813                            mNode,
3814                            (OMX_INDEXTYPE)OMX_IndexParamAudioPcm,
3815                            &params,
3816                            sizeof(params)));
3817
3818                    const char *mime = NULL;
3819                    if (params.ePCMMode == OMX_AUDIO_PCMModeMULaw) {
3820                        mime = MEDIA_MIMETYPE_AUDIO_G711_MLAW;
3821                    } else if (params.ePCMMode == OMX_AUDIO_PCMModeALaw) {
3822                        mime = MEDIA_MIMETYPE_AUDIO_G711_ALAW;
3823                    } else { // params.ePCMMode == OMX_AUDIO_PCMModeLinear
3824                        mime = MEDIA_MIMETYPE_AUDIO_RAW;
3825                    }
3826                    notify->setString("mime", mime);
3827                    notify->setInt32("channel-count", params.nChannels);
3828                    notify->setInt32("sample-rate", params.nSamplingRate);
3829                    break;
3830                }
3831
3832                case OMX_AUDIO_CodingGSMFR:
3833                {
3834                    OMX_AUDIO_PARAM_MP3TYPE params;
3835                    InitOMXParams(&params);
3836                    params.nPortIndex = portIndex;
3837
3838                    CHECK_EQ(mOMX->getParameter(
3839                                mNode, OMX_IndexParamAudioPcm,
3840                                &params, sizeof(params)),
3841                             (status_t)OK);
3842
3843                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MSGSM);
3844                    notify->setInt32("channel-count", params.nChannels);
3845                    notify->setInt32("sample-rate", params.nSampleRate);
3846                    break;
3847                }
3848
3849                default:
3850                    ALOGE("UNKNOWN AUDIO CODING: %d\n", audioDef->eEncoding);
3851                    TRESPASS();
3852            }
3853            break;
3854        }
3855
3856        default:
3857            TRESPASS();
3858    }
3859
3860    return OK;
3861}
3862
3863void ACodec::sendFormatChange(const sp<AMessage> &reply) {
3864    sp<AMessage> notify = mBaseOutputFormat->dup();
3865    notify->setInt32("what", kWhatOutputFormatChanged);
3866
3867    CHECK_EQ(getPortFormat(kPortIndexOutput, notify), (status_t)OK);
3868
3869    AString mime;
3870    CHECK(notify->findString("mime", &mime));
3871
3872    int32_t left, top, right, bottom;
3873    if (mime == MEDIA_MIMETYPE_VIDEO_RAW &&
3874        mNativeWindow != NULL &&
3875        notify->findRect("crop", &left, &top, &right, &bottom)) {
3876        // notify renderer of the crop change
3877        // NOTE: native window uses extended right-bottom coordinate
3878        reply->setRect("crop", left, top, right + 1, bottom + 1);
3879    } else if (mime == MEDIA_MIMETYPE_AUDIO_RAW &&
3880               (mEncoderDelay || mEncoderPadding)) {
3881        int32_t channelCount;
3882        CHECK(notify->findInt32("channel-count", &channelCount));
3883        size_t frameSize = channelCount * sizeof(int16_t);
3884        if (mSkipCutBuffer != NULL) {
3885            size_t prevbufsize = mSkipCutBuffer->size();
3886            if (prevbufsize != 0) {
3887                ALOGW("Replacing SkipCutBuffer holding %d "
3888                      "bytes",
3889                      prevbufsize);
3890            }
3891        }
3892        mSkipCutBuffer = new SkipCutBuffer(
3893                mEncoderDelay * frameSize,
3894                mEncoderPadding * frameSize);
3895    }
3896
3897    notify->post();
3898
3899    mSentFormat = true;
3900}
3901
3902void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) {
3903    sp<AMessage> notify = mNotify->dup();
3904    notify->setInt32("what", CodecBase::kWhatError);
3905    ALOGE("signalError(omxError %#x, internalError %d)", error, internalError);
3906
3907    if (internalError == UNKNOWN_ERROR) { // find better error code
3908        const status_t omxStatus = statusFromOMXError(error);
3909        if (omxStatus != 0) {
3910            internalError = omxStatus;
3911        } else {
3912            ALOGW("Invalid OMX error %#x", error);
3913        }
3914    }
3915    notify->setInt32("err", internalError);
3916    notify->setInt32("actionCode", ACTION_CODE_FATAL); // could translate from OMX error.
3917    notify->post();
3918}
3919
3920status_t ACodec::pushBlankBuffersToNativeWindow() {
3921    status_t err = NO_ERROR;
3922    ANativeWindowBuffer* anb = NULL;
3923    int numBufs = 0;
3924    int minUndequeuedBufs = 0;
3925
3926    // We need to reconnect to the ANativeWindow as a CPU client to ensure that
3927    // no frames get dropped by SurfaceFlinger assuming that these are video
3928    // frames.
3929    err = native_window_api_disconnect(mNativeWindow.get(),
3930            NATIVE_WINDOW_API_MEDIA);
3931    if (err != NO_ERROR) {
3932        ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
3933                strerror(-err), -err);
3934        return err;
3935    }
3936
3937    err = native_window_api_connect(mNativeWindow.get(),
3938            NATIVE_WINDOW_API_CPU);
3939    if (err != NO_ERROR) {
3940        ALOGE("error pushing blank frames: api_connect failed: %s (%d)",
3941                strerror(-err), -err);
3942        return err;
3943    }
3944
3945    err = native_window_set_buffers_geometry(mNativeWindow.get(), 1, 1,
3946            HAL_PIXEL_FORMAT_RGBX_8888);
3947    if (err != NO_ERROR) {
3948        ALOGE("error pushing blank frames: set_buffers_geometry failed: %s (%d)",
3949                strerror(-err), -err);
3950        goto error;
3951    }
3952
3953    err = native_window_set_scaling_mode(mNativeWindow.get(),
3954                NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
3955    if (err != NO_ERROR) {
3956        ALOGE("error pushing blank_frames: set_scaling_mode failed: %s (%d)",
3957              strerror(-err), -err);
3958        goto error;
3959    }
3960
3961    err = native_window_set_usage(mNativeWindow.get(),
3962            GRALLOC_USAGE_SW_WRITE_OFTEN);
3963    if (err != NO_ERROR) {
3964        ALOGE("error pushing blank frames: set_usage failed: %s (%d)",
3965                strerror(-err), -err);
3966        goto error;
3967    }
3968
3969    err = mNativeWindow->query(mNativeWindow.get(),
3970            NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs);
3971    if (err != NO_ERROR) {
3972        ALOGE("error pushing blank frames: MIN_UNDEQUEUED_BUFFERS query "
3973                "failed: %s (%d)", strerror(-err), -err);
3974        goto error;
3975    }
3976
3977    numBufs = minUndequeuedBufs + 1;
3978    err = native_window_set_buffer_count(mNativeWindow.get(), numBufs);
3979    if (err != NO_ERROR) {
3980        ALOGE("error pushing blank frames: set_buffer_count failed: %s (%d)",
3981                strerror(-err), -err);
3982        goto error;
3983    }
3984
3985    // We  push numBufs + 1 buffers to ensure that we've drawn into the same
3986    // buffer twice.  This should guarantee that the buffer has been displayed
3987    // on the screen and then been replaced, so an previous video frames are
3988    // guaranteed NOT to be currently displayed.
3989    for (int i = 0; i < numBufs + 1; i++) {
3990        err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &anb);
3991        if (err != NO_ERROR) {
3992            ALOGE("error pushing blank frames: dequeueBuffer failed: %s (%d)",
3993                    strerror(-err), -err);
3994            goto error;
3995        }
3996
3997        sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
3998
3999        // Fill the buffer with the a 1x1 checkerboard pattern ;)
4000        uint32_t* img = NULL;
4001        err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
4002        if (err != NO_ERROR) {
4003            ALOGE("error pushing blank frames: lock failed: %s (%d)",
4004                    strerror(-err), -err);
4005            goto error;
4006        }
4007
4008        *img = 0;
4009
4010        err = buf->unlock();
4011        if (err != NO_ERROR) {
4012            ALOGE("error pushing blank frames: unlock failed: %s (%d)",
4013                    strerror(-err), -err);
4014            goto error;
4015        }
4016
4017        err = mNativeWindow->queueBuffer(mNativeWindow.get(),
4018                buf->getNativeBuffer(), -1);
4019        if (err != NO_ERROR) {
4020            ALOGE("error pushing blank frames: queueBuffer failed: %s (%d)",
4021                    strerror(-err), -err);
4022            goto error;
4023        }
4024
4025        anb = NULL;
4026    }
4027
4028error:
4029
4030    if (err != NO_ERROR) {
4031        // Clean up after an error.
4032        if (anb != NULL) {
4033            mNativeWindow->cancelBuffer(mNativeWindow.get(), anb, -1);
4034        }
4035
4036        native_window_api_disconnect(mNativeWindow.get(),
4037                NATIVE_WINDOW_API_CPU);
4038        native_window_api_connect(mNativeWindow.get(),
4039                NATIVE_WINDOW_API_MEDIA);
4040
4041        return err;
4042    } else {
4043        // Clean up after success.
4044        err = native_window_api_disconnect(mNativeWindow.get(),
4045                NATIVE_WINDOW_API_CPU);
4046        if (err != NO_ERROR) {
4047            ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
4048                    strerror(-err), -err);
4049            return err;
4050        }
4051
4052        err = native_window_api_connect(mNativeWindow.get(),
4053                NATIVE_WINDOW_API_MEDIA);
4054        if (err != NO_ERROR) {
4055            ALOGE("error pushing blank frames: api_connect failed: %s (%d)",
4056                    strerror(-err), -err);
4057            return err;
4058        }
4059
4060        return NO_ERROR;
4061    }
4062}
4063
4064////////////////////////////////////////////////////////////////////////////////
4065
4066ACodec::PortDescription::PortDescription() {
4067}
4068
4069status_t ACodec::requestIDRFrame() {
4070    if (!mIsEncoder) {
4071        return ERROR_UNSUPPORTED;
4072    }
4073
4074    OMX_CONFIG_INTRAREFRESHVOPTYPE params;
4075    InitOMXParams(&params);
4076
4077    params.nPortIndex = kPortIndexOutput;
4078    params.IntraRefreshVOP = OMX_TRUE;
4079
4080    return mOMX->setConfig(
4081            mNode,
4082            OMX_IndexConfigVideoIntraVOPRefresh,
4083            &params,
4084            sizeof(params));
4085}
4086
4087void ACodec::PortDescription::addBuffer(
4088        IOMX::buffer_id id, const sp<ABuffer> &buffer) {
4089    mBufferIDs.push_back(id);
4090    mBuffers.push_back(buffer);
4091}
4092
4093size_t ACodec::PortDescription::countBuffers() {
4094    return mBufferIDs.size();
4095}
4096
4097IOMX::buffer_id ACodec::PortDescription::bufferIDAt(size_t index) const {
4098    return mBufferIDs.itemAt(index);
4099}
4100
4101sp<ABuffer> ACodec::PortDescription::bufferAt(size_t index) const {
4102    return mBuffers.itemAt(index);
4103}
4104
4105////////////////////////////////////////////////////////////////////////////////
4106
4107ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
4108    : AState(parentState),
4109      mCodec(codec) {
4110}
4111
4112ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(
4113        OMX_U32 /* portIndex */) {
4114    return KEEP_BUFFERS;
4115}
4116
4117bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) {
4118    switch (msg->what()) {
4119        case kWhatInputBufferFilled:
4120        {
4121            onInputBufferFilled(msg);
4122            break;
4123        }
4124
4125        case kWhatOutputBufferDrained:
4126        {
4127            onOutputBufferDrained(msg);
4128            break;
4129        }
4130
4131        case ACodec::kWhatOMXMessage:
4132        {
4133            return onOMXMessage(msg);
4134        }
4135
4136        case ACodec::kWhatCreateInputSurface:
4137        case ACodec::kWhatSignalEndOfInputStream:
4138        {
4139            // This may result in an app illegal state exception.
4140            ALOGE("Message 0x%x was not handled", msg->what());
4141            mCodec->signalError(OMX_ErrorUndefined, INVALID_OPERATION);
4142            return true;
4143        }
4144
4145        case ACodec::kWhatOMXDied:
4146        {
4147            // This will result in kFlagSawMediaServerDie handling in MediaCodec.
4148            ALOGE("OMX/mediaserver died, signalling error!");
4149            mCodec->signalError(OMX_ErrorResourcesLost, DEAD_OBJECT);
4150            break;
4151        }
4152
4153        case ACodec::kWhatReleaseCodecInstance:
4154        {
4155            ALOGI("[%s] forcing the release of codec",
4156                    mCodec->mComponentName.c_str());
4157            status_t err = mCodec->mOMX->freeNode(mCodec->mNode);
4158            ALOGE_IF("[%s] failed to release codec instance: err=%d",
4159                       mCodec->mComponentName.c_str(), err);
4160            sp<AMessage> notify = mCodec->mNotify->dup();
4161            notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
4162            notify->post();
4163            break;
4164        }
4165
4166        default:
4167            return false;
4168    }
4169
4170    return true;
4171}
4172
4173bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) {
4174    int32_t type;
4175    CHECK(msg->findInt32("type", &type));
4176
4177    // there is a possibility that this is an outstanding message for a
4178    // codec that we have already destroyed
4179    if (mCodec->mNode == NULL) {
4180        ALOGI("ignoring message as already freed component: %s",
4181                msg->debugString().c_str());
4182        return true;
4183    }
4184
4185    IOMX::node_id nodeID;
4186    CHECK(msg->findInt32("node", (int32_t*)&nodeID));
4187    CHECK_EQ(nodeID, mCodec->mNode);
4188
4189    switch (type) {
4190        case omx_message::EVENT:
4191        {
4192            int32_t event, data1, data2;
4193            CHECK(msg->findInt32("event", &event));
4194            CHECK(msg->findInt32("data1", &data1));
4195            CHECK(msg->findInt32("data2", &data2));
4196
4197            if (event == OMX_EventCmdComplete
4198                    && data1 == OMX_CommandFlush
4199                    && data2 == (int32_t)OMX_ALL) {
4200                // Use of this notification is not consistent across
4201                // implementations. We'll drop this notification and rely
4202                // on flush-complete notifications on the individual port
4203                // indices instead.
4204
4205                return true;
4206            }
4207
4208            return onOMXEvent(
4209                    static_cast<OMX_EVENTTYPE>(event),
4210                    static_cast<OMX_U32>(data1),
4211                    static_cast<OMX_U32>(data2));
4212        }
4213
4214        case omx_message::EMPTY_BUFFER_DONE:
4215        {
4216            IOMX::buffer_id bufferID;
4217            CHECK(msg->findInt32("buffer", (int32_t*)&bufferID));
4218
4219            return onOMXEmptyBufferDone(bufferID);
4220        }
4221
4222        case omx_message::FILL_BUFFER_DONE:
4223        {
4224            IOMX::buffer_id bufferID;
4225            CHECK(msg->findInt32("buffer", (int32_t*)&bufferID));
4226
4227            int32_t rangeOffset, rangeLength, flags;
4228            int64_t timeUs;
4229
4230            CHECK(msg->findInt32("range_offset", &rangeOffset));
4231            CHECK(msg->findInt32("range_length", &rangeLength));
4232            CHECK(msg->findInt32("flags", &flags));
4233            CHECK(msg->findInt64("timestamp", &timeUs));
4234
4235            return onOMXFillBufferDone(
4236                    bufferID,
4237                    (size_t)rangeOffset, (size_t)rangeLength,
4238                    (OMX_U32)flags,
4239                    timeUs);
4240        }
4241
4242        default:
4243            TRESPASS();
4244            break;
4245    }
4246}
4247
4248bool ACodec::BaseState::onOMXEvent(
4249        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
4250    if (event != OMX_EventError) {
4251        ALOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)",
4252             mCodec->mComponentName.c_str(), event, data1, data2);
4253
4254        return false;
4255    }
4256
4257    ALOGE("[%s] ERROR(0x%08lx)", mCodec->mComponentName.c_str(), data1);
4258
4259    // verify OMX component sends back an error we expect.
4260    OMX_ERRORTYPE omxError = (OMX_ERRORTYPE)data1;
4261    if (!isOMXError(omxError)) {
4262        ALOGW("Invalid OMX error %#x", omxError);
4263        omxError = OMX_ErrorUndefined;
4264    }
4265    mCodec->signalError(omxError);
4266
4267    return true;
4268}
4269
4270bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) {
4271    ALOGV("[%s] onOMXEmptyBufferDone %p",
4272         mCodec->mComponentName.c_str(), bufferID);
4273
4274    BufferInfo *info =
4275        mCodec->findBufferByID(kPortIndexInput, bufferID);
4276
4277    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
4278    info->mStatus = BufferInfo::OWNED_BY_US;
4279
4280    // We're in "store-metadata-in-buffers" mode, the underlying
4281    // OMX component had access to data that's implicitly refcounted
4282    // by this "MediaBuffer" object. Now that the OMX component has
4283    // told us that it's done with the input buffer, we can decrement
4284    // the mediaBuffer's reference count.
4285    info->mData->setMediaBufferBase(NULL);
4286
4287    PortMode mode = getPortMode(kPortIndexInput);
4288
4289    switch (mode) {
4290        case KEEP_BUFFERS:
4291            break;
4292
4293        case RESUBMIT_BUFFERS:
4294            postFillThisBuffer(info);
4295            break;
4296
4297        default:
4298        {
4299            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
4300            TRESPASS();  // Not currently used
4301            break;
4302        }
4303    }
4304
4305    return true;
4306}
4307
4308void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) {
4309    if (mCodec->mPortEOS[kPortIndexInput]) {
4310        return;
4311    }
4312
4313    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
4314
4315    sp<AMessage> notify = mCodec->mNotify->dup();
4316    notify->setInt32("what", CodecBase::kWhatFillThisBuffer);
4317    notify->setInt32("buffer-id", info->mBufferID);
4318
4319    info->mData->meta()->clear();
4320    notify->setBuffer("buffer", info->mData);
4321
4322    sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec);
4323    reply->setInt32("buffer-id", info->mBufferID);
4324
4325    notify->setMessage("reply", reply);
4326
4327    notify->post();
4328
4329    info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
4330}
4331
4332void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
4333    IOMX::buffer_id bufferID;
4334    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
4335    sp<ABuffer> buffer;
4336    int32_t err = OK;
4337    bool eos = false;
4338    PortMode mode = getPortMode(kPortIndexInput);
4339
4340    if (!msg->findBuffer("buffer", &buffer)) {
4341        /* these are unfilled buffers returned by client */
4342        CHECK(msg->findInt32("err", &err));
4343
4344        if (err == OK) {
4345            /* buffers with no errors are returned on MediaCodec.flush */
4346            mode = KEEP_BUFFERS;
4347        } else {
4348            ALOGV("[%s] saw error %d instead of an input buffer",
4349                 mCodec->mComponentName.c_str(), err);
4350            eos = true;
4351        }
4352
4353        buffer.clear();
4354    }
4355
4356    int32_t tmp;
4357    if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) {
4358        eos = true;
4359        err = ERROR_END_OF_STREAM;
4360    }
4361
4362    BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
4363    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM);
4364
4365    info->mStatus = BufferInfo::OWNED_BY_US;
4366
4367    switch (mode) {
4368        case KEEP_BUFFERS:
4369        {
4370            if (eos) {
4371                if (!mCodec->mPortEOS[kPortIndexInput]) {
4372                    mCodec->mPortEOS[kPortIndexInput] = true;
4373                    mCodec->mInputEOSResult = err;
4374                }
4375            }
4376            break;
4377        }
4378
4379        case RESUBMIT_BUFFERS:
4380        {
4381            if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) {
4382                int64_t timeUs;
4383                CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
4384
4385                OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
4386
4387                int32_t isCSD;
4388                if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) {
4389                    flags |= OMX_BUFFERFLAG_CODECCONFIG;
4390                }
4391
4392                if (eos) {
4393                    flags |= OMX_BUFFERFLAG_EOS;
4394                }
4395
4396                if (buffer != info->mData) {
4397                    ALOGV("[%s] Needs to copy input data for buffer %p. (%p != %p)",
4398                         mCodec->mComponentName.c_str(),
4399                         bufferID,
4400                         buffer.get(), info->mData.get());
4401
4402                    CHECK_LE(buffer->size(), info->mData->capacity());
4403                    memcpy(info->mData->data(), buffer->data(), buffer->size());
4404                }
4405
4406                if (flags & OMX_BUFFERFLAG_CODECCONFIG) {
4407                    ALOGV("[%s] calling emptyBuffer %p w/ codec specific data",
4408                         mCodec->mComponentName.c_str(), bufferID);
4409                } else if (flags & OMX_BUFFERFLAG_EOS) {
4410                    ALOGV("[%s] calling emptyBuffer %p w/ EOS",
4411                         mCodec->mComponentName.c_str(), bufferID);
4412                } else {
4413#if TRACK_BUFFER_TIMING
4414                    ALOGI("[%s] calling emptyBuffer %p w/ time %lld us",
4415                         mCodec->mComponentName.c_str(), bufferID, timeUs);
4416#else
4417                    ALOGV("[%s] calling emptyBuffer %p w/ time %lld us",
4418                         mCodec->mComponentName.c_str(), bufferID, timeUs);
4419#endif
4420                }
4421
4422#if TRACK_BUFFER_TIMING
4423                ACodec::BufferStats stats;
4424                stats.mEmptyBufferTimeUs = ALooper::GetNowUs();
4425                stats.mFillBufferDoneTimeUs = -1ll;
4426                mCodec->mBufferStats.add(timeUs, stats);
4427#endif
4428
4429                if (mCodec->mStoreMetaDataInOutputBuffers) {
4430                    // try to submit an output buffer for each input buffer
4431                    PortMode outputMode = getPortMode(kPortIndexOutput);
4432
4433                    ALOGV("MetaDataBuffersToSubmit=%u portMode=%s",
4434                            mCodec->mMetaDataBuffersToSubmit,
4435                            (outputMode == FREE_BUFFERS ? "FREE" :
4436                             outputMode == KEEP_BUFFERS ? "KEEP" : "RESUBMIT"));
4437                    if (outputMode == RESUBMIT_BUFFERS) {
4438                        mCodec->submitOutputMetaDataBuffer();
4439                    }
4440                }
4441
4442                CHECK_EQ(mCodec->mOMX->emptyBuffer(
4443                            mCodec->mNode,
4444                            bufferID,
4445                            0,
4446                            buffer->size(),
4447                            flags,
4448                            timeUs),
4449                         (status_t)OK);
4450
4451                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4452
4453                if (!eos) {
4454                    getMoreInputDataIfPossible();
4455                } else {
4456                    ALOGV("[%s] Signalled EOS on the input port",
4457                         mCodec->mComponentName.c_str());
4458
4459                    mCodec->mPortEOS[kPortIndexInput] = true;
4460                    mCodec->mInputEOSResult = err;
4461                }
4462            } else if (!mCodec->mPortEOS[kPortIndexInput]) {
4463                if (err != ERROR_END_OF_STREAM) {
4464                    ALOGV("[%s] Signalling EOS on the input port "
4465                         "due to error %d",
4466                         mCodec->mComponentName.c_str(), err);
4467                } else {
4468                    ALOGV("[%s] Signalling EOS on the input port",
4469                         mCodec->mComponentName.c_str());
4470                }
4471
4472                ALOGV("[%s] calling emptyBuffer %p signalling EOS",
4473                     mCodec->mComponentName.c_str(), bufferID);
4474
4475                CHECK_EQ(mCodec->mOMX->emptyBuffer(
4476                            mCodec->mNode,
4477                            bufferID,
4478                            0,
4479                            0,
4480                            OMX_BUFFERFLAG_EOS,
4481                            0),
4482                         (status_t)OK);
4483
4484                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4485
4486                mCodec->mPortEOS[kPortIndexInput] = true;
4487                mCodec->mInputEOSResult = err;
4488            }
4489            break;
4490        }
4491
4492        default:
4493            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
4494            break;
4495    }
4496}
4497
4498void ACodec::BaseState::getMoreInputDataIfPossible() {
4499    if (mCodec->mPortEOS[kPortIndexInput]) {
4500        return;
4501    }
4502
4503    BufferInfo *eligible = NULL;
4504
4505    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
4506        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
4507
4508#if 0
4509        if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) {
4510            // There's already a "read" pending.
4511            return;
4512        }
4513#endif
4514
4515        if (info->mStatus == BufferInfo::OWNED_BY_US) {
4516            eligible = info;
4517        }
4518    }
4519
4520    if (eligible == NULL) {
4521        return;
4522    }
4523
4524    postFillThisBuffer(eligible);
4525}
4526
4527bool ACodec::BaseState::onOMXFillBufferDone(
4528        IOMX::buffer_id bufferID,
4529        size_t rangeOffset, size_t rangeLength,
4530        OMX_U32 flags,
4531        int64_t timeUs) {
4532    ALOGV("[%s] onOMXFillBufferDone %u time %" PRId64 " us, flags = 0x%08x",
4533         mCodec->mComponentName.c_str(), bufferID, timeUs, flags);
4534
4535    ssize_t index;
4536
4537#if TRACK_BUFFER_TIMING
4538    index = mCodec->mBufferStats.indexOfKey(timeUs);
4539    if (index >= 0) {
4540        ACodec::BufferStats *stats = &mCodec->mBufferStats.editValueAt(index);
4541        stats->mFillBufferDoneTimeUs = ALooper::GetNowUs();
4542
4543        ALOGI("frame PTS %lld: %lld",
4544                timeUs,
4545                stats->mFillBufferDoneTimeUs - stats->mEmptyBufferTimeUs);
4546
4547        mCodec->mBufferStats.removeItemsAt(index);
4548        stats = NULL;
4549    }
4550#endif
4551
4552    BufferInfo *info =
4553        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
4554
4555    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
4556
4557    info->mDequeuedAt = ++mCodec->mDequeueCounter;
4558    info->mStatus = BufferInfo::OWNED_BY_US;
4559
4560    PortMode mode = getPortMode(kPortIndexOutput);
4561
4562    switch (mode) {
4563        case KEEP_BUFFERS:
4564            break;
4565
4566        case RESUBMIT_BUFFERS:
4567        {
4568            if (rangeLength == 0 && (!(flags & OMX_BUFFERFLAG_EOS)
4569                    || mCodec->mPortEOS[kPortIndexOutput])) {
4570                ALOGV("[%s] calling fillBuffer %u",
4571                     mCodec->mComponentName.c_str(), info->mBufferID);
4572
4573                CHECK_EQ(mCodec->mOMX->fillBuffer(
4574                            mCodec->mNode, info->mBufferID),
4575                         (status_t)OK);
4576
4577                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4578                break;
4579            }
4580
4581            sp<AMessage> reply =
4582                new AMessage(kWhatOutputBufferDrained, mCodec);
4583
4584            if (!mCodec->mSentFormat && rangeLength > 0) {
4585                mCodec->sendFormatChange(reply);
4586            }
4587
4588            if (mCodec->mUseMetadataOnEncoderOutput) {
4589                native_handle_t* handle =
4590                        *(native_handle_t**)(info->mData->data() + 4);
4591                info->mData->meta()->setPointer("handle", handle);
4592                info->mData->meta()->setInt32("rangeOffset", rangeOffset);
4593                info->mData->meta()->setInt32("rangeLength", rangeLength);
4594            } else {
4595                info->mData->setRange(rangeOffset, rangeLength);
4596            }
4597#if 0
4598            if (mCodec->mNativeWindow == NULL) {
4599                if (IsIDR(info->mData)) {
4600                    ALOGI("IDR frame");
4601                }
4602            }
4603#endif
4604
4605            if (mCodec->mSkipCutBuffer != NULL) {
4606                mCodec->mSkipCutBuffer->submit(info->mData);
4607            }
4608            info->mData->meta()->setInt64("timeUs", timeUs);
4609
4610            sp<AMessage> notify = mCodec->mNotify->dup();
4611            notify->setInt32("what", CodecBase::kWhatDrainThisBuffer);
4612            notify->setInt32("buffer-id", info->mBufferID);
4613            notify->setBuffer("buffer", info->mData);
4614            notify->setInt32("flags", flags);
4615
4616            reply->setInt32("buffer-id", info->mBufferID);
4617
4618            notify->setMessage("reply", reply);
4619
4620            notify->post();
4621
4622            info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;
4623
4624            if (flags & OMX_BUFFERFLAG_EOS) {
4625                ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str());
4626
4627                sp<AMessage> notify = mCodec->mNotify->dup();
4628                notify->setInt32("what", CodecBase::kWhatEOS);
4629                notify->setInt32("err", mCodec->mInputEOSResult);
4630                notify->post();
4631
4632                mCodec->mPortEOS[kPortIndexOutput] = true;
4633            }
4634            break;
4635        }
4636
4637        default:
4638        {
4639            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
4640
4641            CHECK_EQ((status_t)OK,
4642                     mCodec->freeBuffer(kPortIndexOutput, index));
4643            break;
4644        }
4645    }
4646
4647    return true;
4648}
4649
4650void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
4651    IOMX::buffer_id bufferID;
4652    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
4653    ssize_t index;
4654    BufferInfo *info =
4655        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
4656    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
4657
4658    android_native_rect_t crop;
4659    if (msg->findRect("crop",
4660            &crop.left, &crop.top, &crop.right, &crop.bottom)) {
4661        CHECK_EQ(0, native_window_set_crop(
4662                mCodec->mNativeWindow.get(), &crop));
4663    }
4664
4665    int32_t render;
4666    if (mCodec->mNativeWindow != NULL
4667            && msg->findInt32("render", &render) && render != 0
4668            && info->mData != NULL && info->mData->size() != 0) {
4669        ATRACE_NAME("render");
4670        // The client wants this buffer to be rendered.
4671
4672        int64_t timestampNs = 0;
4673        if (!msg->findInt64("timestampNs", &timestampNs)) {
4674            // TODO: it seems like we should use the timestamp
4675            // in the (media)buffer as it potentially came from
4676            // an input surface, but we did not propagate it prior to
4677            // API 20.  Perhaps check for target SDK version.
4678#if 0
4679            if (info->mData->meta()->findInt64("timeUs", &timestampNs)) {
4680                ALOGV("using buffer PTS of %" PRId64, timestampNs);
4681                timestampNs *= 1000;
4682            }
4683#endif
4684        }
4685
4686        status_t err;
4687        err = native_window_set_buffers_timestamp(mCodec->mNativeWindow.get(), timestampNs);
4688        if (err != OK) {
4689            ALOGW("failed to set buffer timestamp: %d", err);
4690        }
4691
4692        if ((err = mCodec->mNativeWindow->queueBuffer(
4693                    mCodec->mNativeWindow.get(),
4694                    info->mGraphicBuffer.get(), -1)) == OK) {
4695            info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
4696        } else {
4697            mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
4698            info->mStatus = BufferInfo::OWNED_BY_US;
4699        }
4700    } else {
4701        if (mCodec->mNativeWindow != NULL &&
4702            (info->mData == NULL || info->mData->size() != 0)) {
4703            ATRACE_NAME("frame-drop");
4704        }
4705        info->mStatus = BufferInfo::OWNED_BY_US;
4706    }
4707
4708    PortMode mode = getPortMode(kPortIndexOutput);
4709
4710    switch (mode) {
4711        case KEEP_BUFFERS:
4712        {
4713            // XXX fishy, revisit!!! What about the FREE_BUFFERS case below?
4714
4715            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
4716                // We cannot resubmit the buffer we just rendered, dequeue
4717                // the spare instead.
4718
4719                info = mCodec->dequeueBufferFromNativeWindow();
4720            }
4721            break;
4722        }
4723
4724        case RESUBMIT_BUFFERS:
4725        {
4726            if (!mCodec->mPortEOS[kPortIndexOutput]) {
4727                if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
4728                    // We cannot resubmit the buffer we just rendered, dequeue
4729                    // the spare instead.
4730
4731                    info = mCodec->dequeueBufferFromNativeWindow();
4732                }
4733
4734                if (info != NULL) {
4735                    ALOGV("[%s] calling fillBuffer %u",
4736                         mCodec->mComponentName.c_str(), info->mBufferID);
4737
4738                    CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
4739                             (status_t)OK);
4740
4741                    info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4742                }
4743            }
4744            break;
4745        }
4746
4747        default:
4748        {
4749            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
4750
4751            CHECK_EQ((status_t)OK,
4752                     mCodec->freeBuffer(kPortIndexOutput, index));
4753            break;
4754        }
4755    }
4756}
4757
4758////////////////////////////////////////////////////////////////////////////////
4759
4760ACodec::UninitializedState::UninitializedState(ACodec *codec)
4761    : BaseState(codec) {
4762}
4763
4764void ACodec::UninitializedState::stateEntered() {
4765    ALOGV("Now uninitialized");
4766
4767    if (mDeathNotifier != NULL) {
4768        IInterface::asBinder(mCodec->mOMX)->unlinkToDeath(mDeathNotifier);
4769        mDeathNotifier.clear();
4770    }
4771
4772    mCodec->mNativeWindow.clear();
4773    mCodec->mNode = NULL;
4774    mCodec->mOMX.clear();
4775    mCodec->mQuirks = 0;
4776    mCodec->mFlags = 0;
4777    mCodec->mUseMetadataOnEncoderOutput = 0;
4778    mCodec->mComponentName.clear();
4779}
4780
4781bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
4782    bool handled = false;
4783
4784    switch (msg->what()) {
4785        case ACodec::kWhatSetup:
4786        {
4787            onSetup(msg);
4788
4789            handled = true;
4790            break;
4791        }
4792
4793        case ACodec::kWhatAllocateComponent:
4794        {
4795            onAllocateComponent(msg);
4796            handled = true;
4797            break;
4798        }
4799
4800        case ACodec::kWhatShutdown:
4801        {
4802            int32_t keepComponentAllocated;
4803            CHECK(msg->findInt32(
4804                        "keepComponentAllocated", &keepComponentAllocated));
4805            ALOGW_IF(keepComponentAllocated,
4806                     "cannot keep component allocated on shutdown in Uninitialized state");
4807
4808            sp<AMessage> notify = mCodec->mNotify->dup();
4809            notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
4810            notify->post();
4811
4812            handled = true;
4813            break;
4814        }
4815
4816        case ACodec::kWhatFlush:
4817        {
4818            sp<AMessage> notify = mCodec->mNotify->dup();
4819            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
4820            notify->post();
4821
4822            handled = true;
4823            break;
4824        }
4825
4826        case ACodec::kWhatReleaseCodecInstance:
4827        {
4828            // nothing to do, as we have already signaled shutdown
4829            handled = true;
4830            break;
4831        }
4832
4833        default:
4834            return BaseState::onMessageReceived(msg);
4835    }
4836
4837    return handled;
4838}
4839
4840void ACodec::UninitializedState::onSetup(
4841        const sp<AMessage> &msg) {
4842    if (onAllocateComponent(msg)
4843            && mCodec->mLoadedState->onConfigureComponent(msg)) {
4844        mCodec->mLoadedState->onStart();
4845    }
4846}
4847
4848bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
4849    ALOGV("onAllocateComponent");
4850
4851    CHECK(mCodec->mNode == NULL);
4852
4853    OMXClient client;
4854    CHECK_EQ(client.connect(), (status_t)OK);
4855
4856    sp<IOMX> omx = client.interface();
4857
4858    sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec);
4859
4860    mDeathNotifier = new DeathNotifier(notify);
4861    if (IInterface::asBinder(omx)->linkToDeath(mDeathNotifier) != OK) {
4862        // This was a local binder, if it dies so do we, we won't care
4863        // about any notifications in the afterlife.
4864        mDeathNotifier.clear();
4865    }
4866
4867    Vector<OMXCodec::CodecNameAndQuirks> matchingCodecs;
4868
4869    AString mime;
4870
4871    AString componentName;
4872    uint32_t quirks = 0;
4873    int32_t encoder = false;
4874    if (msg->findString("componentName", &componentName)) {
4875        ssize_t index = matchingCodecs.add();
4876        OMXCodec::CodecNameAndQuirks *entry = &matchingCodecs.editItemAt(index);
4877        entry->mName = String8(componentName.c_str());
4878
4879        if (!OMXCodec::findCodecQuirks(
4880                    componentName.c_str(), &entry->mQuirks)) {
4881            entry->mQuirks = 0;
4882        }
4883    } else {
4884        CHECK(msg->findString("mime", &mime));
4885
4886        if (!msg->findInt32("encoder", &encoder)) {
4887            encoder = false;
4888        }
4889
4890        OMXCodec::findMatchingCodecs(
4891                mime.c_str(),
4892                encoder, // createEncoder
4893                NULL,  // matchComponentName
4894                0,     // flags
4895                &matchingCodecs);
4896    }
4897
4898    sp<CodecObserver> observer = new CodecObserver;
4899    IOMX::node_id node = NULL;
4900
4901    for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
4902            ++matchIndex) {
4903        componentName = matchingCodecs.itemAt(matchIndex).mName.string();
4904        quirks = matchingCodecs.itemAt(matchIndex).mQuirks;
4905
4906        pid_t tid = gettid();
4907        int prevPriority = androidGetThreadPriority(tid);
4908        androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
4909        status_t err = omx->allocateNode(componentName.c_str(), observer, &node);
4910        androidSetThreadPriority(tid, prevPriority);
4911
4912        if (err == OK) {
4913            break;
4914        } else {
4915            ALOGW("Allocating component '%s' failed, try next one.", componentName.c_str());
4916        }
4917
4918        node = NULL;
4919    }
4920
4921    if (node == NULL) {
4922        if (!mime.empty()) {
4923            ALOGE("Unable to instantiate a %scoder for type '%s'.",
4924                    encoder ? "en" : "de", mime.c_str());
4925        } else {
4926            ALOGE("Unable to instantiate codec '%s'.", componentName.c_str());
4927        }
4928
4929        mCodec->signalError(OMX_ErrorComponentNotFound);
4930        return false;
4931    }
4932
4933    notify = new AMessage(kWhatOMXMessage, mCodec);
4934    observer->setNotificationMessage(notify);
4935
4936    mCodec->mComponentName = componentName;
4937    mCodec->mFlags = 0;
4938
4939    if (componentName.endsWith(".secure")) {
4940        mCodec->mFlags |= kFlagIsSecure;
4941        mCodec->mFlags |= kFlagIsGrallocUsageProtected;
4942        mCodec->mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
4943    }
4944
4945    mCodec->mQuirks = quirks;
4946    mCodec->mOMX = omx;
4947    mCodec->mNode = node;
4948
4949    {
4950        sp<AMessage> notify = mCodec->mNotify->dup();
4951        notify->setInt32("what", CodecBase::kWhatComponentAllocated);
4952        notify->setString("componentName", mCodec->mComponentName.c_str());
4953        notify->post();
4954    }
4955
4956    mCodec->changeState(mCodec->mLoadedState);
4957
4958    return true;
4959}
4960
4961////////////////////////////////////////////////////////////////////////////////
4962
4963ACodec::LoadedState::LoadedState(ACodec *codec)
4964    : BaseState(codec) {
4965}
4966
4967void ACodec::LoadedState::stateEntered() {
4968    ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
4969
4970    mCodec->mPortEOS[kPortIndexInput] =
4971        mCodec->mPortEOS[kPortIndexOutput] = false;
4972
4973    mCodec->mInputEOSResult = OK;
4974
4975    mCodec->mDequeueCounter = 0;
4976    mCodec->mMetaDataBuffersToSubmit = 0;
4977    mCodec->mRepeatFrameDelayUs = -1ll;
4978    mCodec->mInputFormat.clear();
4979    mCodec->mOutputFormat.clear();
4980    mCodec->mBaseOutputFormat.clear();
4981
4982    if (mCodec->mShutdownInProgress) {
4983        bool keepComponentAllocated = mCodec->mKeepComponentAllocated;
4984
4985        mCodec->mShutdownInProgress = false;
4986        mCodec->mKeepComponentAllocated = false;
4987
4988        onShutdown(keepComponentAllocated);
4989    }
4990    mCodec->mExplicitShutdown = false;
4991
4992    mCodec->processDeferredMessages();
4993}
4994
4995void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) {
4996    if (!keepComponentAllocated) {
4997        CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
4998
4999        mCodec->changeState(mCodec->mUninitializedState);
5000    }
5001
5002    if (mCodec->mExplicitShutdown) {
5003        sp<AMessage> notify = mCodec->mNotify->dup();
5004        notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
5005        notify->post();
5006        mCodec->mExplicitShutdown = false;
5007    }
5008}
5009
5010bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) {
5011    bool handled = false;
5012
5013    switch (msg->what()) {
5014        case ACodec::kWhatConfigureComponent:
5015        {
5016            onConfigureComponent(msg);
5017            handled = true;
5018            break;
5019        }
5020
5021        case ACodec::kWhatCreateInputSurface:
5022        {
5023            onCreateInputSurface(msg);
5024            handled = true;
5025            break;
5026        }
5027
5028        case ACodec::kWhatStart:
5029        {
5030            onStart();
5031            handled = true;
5032            break;
5033        }
5034
5035        case ACodec::kWhatShutdown:
5036        {
5037            int32_t keepComponentAllocated;
5038            CHECK(msg->findInt32(
5039                        "keepComponentAllocated", &keepComponentAllocated));
5040
5041            mCodec->mExplicitShutdown = true;
5042            onShutdown(keepComponentAllocated);
5043
5044            handled = true;
5045            break;
5046        }
5047
5048        case ACodec::kWhatFlush:
5049        {
5050            sp<AMessage> notify = mCodec->mNotify->dup();
5051            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
5052            notify->post();
5053
5054            handled = true;
5055            break;
5056        }
5057
5058        default:
5059            return BaseState::onMessageReceived(msg);
5060    }
5061
5062    return handled;
5063}
5064
5065bool ACodec::LoadedState::onConfigureComponent(
5066        const sp<AMessage> &msg) {
5067    ALOGV("onConfigureComponent");
5068
5069    CHECK(mCodec->mNode != NULL);
5070
5071    AString mime;
5072    CHECK(msg->findString("mime", &mime));
5073
5074    status_t err = mCodec->configureCodec(mime.c_str(), msg);
5075
5076    if (err != OK) {
5077        ALOGE("[%s] configureCodec returning error %d",
5078              mCodec->mComponentName.c_str(), err);
5079
5080        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5081        return false;
5082    }
5083
5084    {
5085        sp<AMessage> notify = mCodec->mNotify->dup();
5086        notify->setInt32("what", CodecBase::kWhatComponentConfigured);
5087        notify->setMessage("input-format", mCodec->mInputFormat);
5088        notify->setMessage("output-format", mCodec->mOutputFormat);
5089        notify->post();
5090    }
5091
5092    return true;
5093}
5094
5095void ACodec::LoadedState::onCreateInputSurface(
5096        const sp<AMessage> & /* msg */) {
5097    ALOGV("onCreateInputSurface");
5098
5099    sp<AMessage> notify = mCodec->mNotify->dup();
5100    notify->setInt32("what", CodecBase::kWhatInputSurfaceCreated);
5101
5102    sp<IGraphicBufferProducer> bufferProducer;
5103    status_t err;
5104
5105    err = mCodec->mOMX->createInputSurface(mCodec->mNode, kPortIndexInput,
5106            &bufferProducer);
5107
5108    if (err == OK && mCodec->mRepeatFrameDelayUs > 0ll) {
5109        err = mCodec->mOMX->setInternalOption(
5110                mCodec->mNode,
5111                kPortIndexInput,
5112                IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY,
5113                &mCodec->mRepeatFrameDelayUs,
5114                sizeof(mCodec->mRepeatFrameDelayUs));
5115
5116        if (err != OK) {
5117            ALOGE("[%s] Unable to configure option to repeat previous "
5118                  "frames (err %d)",
5119                  mCodec->mComponentName.c_str(),
5120                  err);
5121        }
5122    }
5123
5124    if (err == OK && mCodec->mMaxPtsGapUs > 0ll) {
5125        err = mCodec->mOMX->setInternalOption(
5126                mCodec->mNode,
5127                kPortIndexInput,
5128                IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP,
5129                &mCodec->mMaxPtsGapUs,
5130                sizeof(mCodec->mMaxPtsGapUs));
5131
5132        if (err != OK) {
5133            ALOGE("[%s] Unable to configure max timestamp gap (err %d)",
5134                    mCodec->mComponentName.c_str(),
5135                    err);
5136        }
5137    }
5138
5139    if (err == OK && mCodec->mMaxFps > 0) {
5140        err = mCodec->mOMX->setInternalOption(
5141                mCodec->mNode,
5142                kPortIndexInput,
5143                IOMX::INTERNAL_OPTION_MAX_FPS,
5144                &mCodec->mMaxFps,
5145                sizeof(mCodec->mMaxFps));
5146
5147        if (err != OK) {
5148            ALOGE("[%s] Unable to configure max fps (err %d)",
5149                    mCodec->mComponentName.c_str(),
5150                    err);
5151        }
5152    }
5153
5154    if (err == OK && mCodec->mTimePerCaptureUs > 0ll
5155            && mCodec->mTimePerFrameUs > 0ll) {
5156        int64_t timeLapse[2];
5157        timeLapse[0] = mCodec->mTimePerFrameUs;
5158        timeLapse[1] = mCodec->mTimePerCaptureUs;
5159        err = mCodec->mOMX->setInternalOption(
5160                mCodec->mNode,
5161                kPortIndexInput,
5162                IOMX::INTERNAL_OPTION_TIME_LAPSE,
5163                &timeLapse[0],
5164                sizeof(timeLapse));
5165
5166        if (err != OK) {
5167            ALOGE("[%s] Unable to configure time lapse (err %d)",
5168                    mCodec->mComponentName.c_str(),
5169                    err);
5170        }
5171    }
5172
5173    if (err == OK && mCodec->mCreateInputBuffersSuspended) {
5174        bool suspend = true;
5175        err = mCodec->mOMX->setInternalOption(
5176                mCodec->mNode,
5177                kPortIndexInput,
5178                IOMX::INTERNAL_OPTION_SUSPEND,
5179                &suspend,
5180                sizeof(suspend));
5181
5182        if (err != OK) {
5183            ALOGE("[%s] Unable to configure option to suspend (err %d)",
5184                  mCodec->mComponentName.c_str(),
5185                  err);
5186        }
5187    }
5188
5189    if (err == OK) {
5190        notify->setObject("input-surface",
5191                new BufferProducerWrapper(bufferProducer));
5192    } else {
5193        // Can't use mCodec->signalError() here -- MediaCodec won't forward
5194        // the error through because it's in the "configured" state.  We
5195        // send a kWhatInputSurfaceCreated with an error value instead.
5196        ALOGE("[%s] onCreateInputSurface returning error %d",
5197                mCodec->mComponentName.c_str(), err);
5198        notify->setInt32("err", err);
5199    }
5200    notify->post();
5201}
5202
5203void ACodec::LoadedState::onStart() {
5204    ALOGV("onStart");
5205
5206    CHECK_EQ(mCodec->mOMX->sendCommand(
5207                mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
5208             (status_t)OK);
5209
5210    mCodec->changeState(mCodec->mLoadedToIdleState);
5211}
5212
5213////////////////////////////////////////////////////////////////////////////////
5214
5215ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec)
5216    : BaseState(codec) {
5217}
5218
5219void ACodec::LoadedToIdleState::stateEntered() {
5220    ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
5221
5222    status_t err;
5223    if ((err = allocateBuffers()) != OK) {
5224        ALOGE("Failed to allocate buffers after transitioning to IDLE state "
5225             "(error 0x%08x)",
5226             err);
5227
5228        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5229
5230        mCodec->changeState(mCodec->mLoadedState);
5231    }
5232}
5233
5234status_t ACodec::LoadedToIdleState::allocateBuffers() {
5235    status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput);
5236
5237    if (err != OK) {
5238        return err;
5239    }
5240
5241    return mCodec->allocateBuffersOnPort(kPortIndexOutput);
5242}
5243
5244bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
5245    switch (msg->what()) {
5246        case kWhatSetParameters:
5247        case kWhatShutdown:
5248        {
5249            mCodec->deferMessage(msg);
5250            return true;
5251        }
5252
5253        case kWhatSignalEndOfInputStream:
5254        {
5255            mCodec->onSignalEndOfInputStream();
5256            return true;
5257        }
5258
5259        case kWhatResume:
5260        {
5261            // We'll be active soon enough.
5262            return true;
5263        }
5264
5265        case kWhatFlush:
5266        {
5267            // We haven't even started yet, so we're flushed alright...
5268            sp<AMessage> notify = mCodec->mNotify->dup();
5269            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
5270            notify->post();
5271            return true;
5272        }
5273
5274        default:
5275            return BaseState::onMessageReceived(msg);
5276    }
5277}
5278
5279bool ACodec::LoadedToIdleState::onOMXEvent(
5280        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5281    switch (event) {
5282        case OMX_EventCmdComplete:
5283        {
5284            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
5285            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
5286
5287            CHECK_EQ(mCodec->mOMX->sendCommand(
5288                        mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting),
5289                     (status_t)OK);
5290
5291            mCodec->changeState(mCodec->mIdleToExecutingState);
5292
5293            return true;
5294        }
5295
5296        default:
5297            return BaseState::onOMXEvent(event, data1, data2);
5298    }
5299}
5300
5301////////////////////////////////////////////////////////////////////////////////
5302
5303ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec)
5304    : BaseState(codec) {
5305}
5306
5307void ACodec::IdleToExecutingState::stateEntered() {
5308    ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
5309}
5310
5311bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
5312    switch (msg->what()) {
5313        case kWhatSetParameters:
5314        case kWhatShutdown:
5315        {
5316            mCodec->deferMessage(msg);
5317            return true;
5318        }
5319
5320        case kWhatResume:
5321        {
5322            // We'll be active soon enough.
5323            return true;
5324        }
5325
5326        case kWhatFlush:
5327        {
5328            // We haven't even started yet, so we're flushed alright...
5329            sp<AMessage> notify = mCodec->mNotify->dup();
5330            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
5331            notify->post();
5332
5333            return true;
5334        }
5335
5336        case kWhatSignalEndOfInputStream:
5337        {
5338            mCodec->onSignalEndOfInputStream();
5339            return true;
5340        }
5341
5342        default:
5343            return BaseState::onMessageReceived(msg);
5344    }
5345}
5346
5347bool ACodec::IdleToExecutingState::onOMXEvent(
5348        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5349    switch (event) {
5350        case OMX_EventCmdComplete:
5351        {
5352            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
5353            CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting);
5354
5355            mCodec->mExecutingState->resume();
5356            mCodec->changeState(mCodec->mExecutingState);
5357
5358            return true;
5359        }
5360
5361        default:
5362            return BaseState::onOMXEvent(event, data1, data2);
5363    }
5364}
5365
5366////////////////////////////////////////////////////////////////////////////////
5367
5368ACodec::ExecutingState::ExecutingState(ACodec *codec)
5369    : BaseState(codec),
5370      mActive(false) {
5371}
5372
5373ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode(
5374        OMX_U32 /* portIndex */) {
5375    return RESUBMIT_BUFFERS;
5376}
5377
5378void ACodec::ExecutingState::submitOutputMetaBuffers() {
5379    // submit as many buffers as there are input buffers with the codec
5380    // in case we are in port reconfiguring
5381    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
5382        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
5383
5384        if (info->mStatus == BufferInfo::OWNED_BY_COMPONENT) {
5385            if (mCodec->submitOutputMetaDataBuffer() != OK)
5386                break;
5387        }
5388    }
5389
5390    // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
5391    mCodec->signalSubmitOutputMetaDataBufferIfEOS_workaround();
5392}
5393
5394void ACodec::ExecutingState::submitRegularOutputBuffers() {
5395    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
5396        BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
5397
5398        if (mCodec->mNativeWindow != NULL) {
5399            CHECK(info->mStatus == BufferInfo::OWNED_BY_US
5400                    || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
5401
5402            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
5403                continue;
5404            }
5405        } else {
5406            CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
5407        }
5408
5409        ALOGV("[%s] calling fillBuffer %p",
5410             mCodec->mComponentName.c_str(), info->mBufferID);
5411
5412        CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
5413                 (status_t)OK);
5414
5415        info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
5416    }
5417}
5418
5419void ACodec::ExecutingState::submitOutputBuffers() {
5420    submitRegularOutputBuffers();
5421    if (mCodec->mStoreMetaDataInOutputBuffers) {
5422        submitOutputMetaBuffers();
5423    }
5424}
5425
5426void ACodec::ExecutingState::resume() {
5427    if (mActive) {
5428        ALOGV("[%s] We're already active, no need to resume.",
5429             mCodec->mComponentName.c_str());
5430
5431        return;
5432    }
5433
5434    submitOutputBuffers();
5435
5436    // Post all available input buffers
5437    CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u);
5438    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); i++) {
5439        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
5440        if (info->mStatus == BufferInfo::OWNED_BY_US) {
5441            postFillThisBuffer(info);
5442        }
5443    }
5444
5445    mActive = true;
5446}
5447
5448void ACodec::ExecutingState::stateEntered() {
5449    ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
5450
5451    mCodec->processDeferredMessages();
5452}
5453
5454bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) {
5455    bool handled = false;
5456
5457    switch (msg->what()) {
5458        case kWhatShutdown:
5459        {
5460            int32_t keepComponentAllocated;
5461            CHECK(msg->findInt32(
5462                        "keepComponentAllocated", &keepComponentAllocated));
5463
5464            mCodec->mShutdownInProgress = true;
5465            mCodec->mExplicitShutdown = true;
5466            mCodec->mKeepComponentAllocated = keepComponentAllocated;
5467
5468            mActive = false;
5469
5470            CHECK_EQ(mCodec->mOMX->sendCommand(
5471                        mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
5472                     (status_t)OK);
5473
5474            mCodec->changeState(mCodec->mExecutingToIdleState);
5475
5476            handled = true;
5477            break;
5478        }
5479
5480        case kWhatFlush:
5481        {
5482            ALOGV("[%s] ExecutingState flushing now "
5483                 "(codec owns %d/%d input, %d/%d output).",
5484                    mCodec->mComponentName.c_str(),
5485                    mCodec->countBuffersOwnedByComponent(kPortIndexInput),
5486                    mCodec->mBuffers[kPortIndexInput].size(),
5487                    mCodec->countBuffersOwnedByComponent(kPortIndexOutput),
5488                    mCodec->mBuffers[kPortIndexOutput].size());
5489
5490            mActive = false;
5491
5492            CHECK_EQ(mCodec->mOMX->sendCommand(
5493                        mCodec->mNode, OMX_CommandFlush, OMX_ALL),
5494                     (status_t)OK);
5495
5496            mCodec->changeState(mCodec->mFlushingState);
5497            handled = true;
5498            break;
5499        }
5500
5501        case kWhatResume:
5502        {
5503            resume();
5504
5505            handled = true;
5506            break;
5507        }
5508
5509        case kWhatRequestIDRFrame:
5510        {
5511            status_t err = mCodec->requestIDRFrame();
5512            if (err != OK) {
5513                ALOGW("Requesting an IDR frame failed.");
5514            }
5515
5516            handled = true;
5517            break;
5518        }
5519
5520        case kWhatSetParameters:
5521        {
5522            sp<AMessage> params;
5523            CHECK(msg->findMessage("params", &params));
5524
5525            status_t err = mCodec->setParameters(params);
5526
5527            sp<AMessage> reply;
5528            if (msg->findMessage("reply", &reply)) {
5529                reply->setInt32("err", err);
5530                reply->post();
5531            }
5532
5533            handled = true;
5534            break;
5535        }
5536
5537        case ACodec::kWhatSignalEndOfInputStream:
5538        {
5539            mCodec->onSignalEndOfInputStream();
5540            handled = true;
5541            break;
5542        }
5543
5544        // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
5545        case kWhatSubmitOutputMetaDataBufferIfEOS:
5546        {
5547            if (mCodec->mPortEOS[kPortIndexInput] &&
5548                    !mCodec->mPortEOS[kPortIndexOutput]) {
5549                status_t err = mCodec->submitOutputMetaDataBuffer();
5550                if (err == OK) {
5551                    mCodec->signalSubmitOutputMetaDataBufferIfEOS_workaround();
5552                }
5553            }
5554            return true;
5555        }
5556
5557        default:
5558            handled = BaseState::onMessageReceived(msg);
5559            break;
5560    }
5561
5562    return handled;
5563}
5564
5565status_t ACodec::setParameters(const sp<AMessage> &params) {
5566    int32_t videoBitrate;
5567    if (params->findInt32("video-bitrate", &videoBitrate)) {
5568        OMX_VIDEO_CONFIG_BITRATETYPE configParams;
5569        InitOMXParams(&configParams);
5570        configParams.nPortIndex = kPortIndexOutput;
5571        configParams.nEncodeBitrate = videoBitrate;
5572
5573        status_t err = mOMX->setConfig(
5574                mNode,
5575                OMX_IndexConfigVideoBitrate,
5576                &configParams,
5577                sizeof(configParams));
5578
5579        if (err != OK) {
5580            ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d",
5581                   videoBitrate, err);
5582
5583            return err;
5584        }
5585    }
5586
5587    int64_t skipFramesBeforeUs;
5588    if (params->findInt64("skip-frames-before", &skipFramesBeforeUs)) {
5589        status_t err =
5590            mOMX->setInternalOption(
5591                     mNode,
5592                     kPortIndexInput,
5593                     IOMX::INTERNAL_OPTION_START_TIME,
5594                     &skipFramesBeforeUs,
5595                     sizeof(skipFramesBeforeUs));
5596
5597        if (err != OK) {
5598            ALOGE("Failed to set parameter 'skip-frames-before' (err %d)", err);
5599            return err;
5600        }
5601    }
5602
5603    int32_t dropInputFrames;
5604    if (params->findInt32("drop-input-frames", &dropInputFrames)) {
5605        bool suspend = dropInputFrames != 0;
5606
5607        status_t err =
5608            mOMX->setInternalOption(
5609                     mNode,
5610                     kPortIndexInput,
5611                     IOMX::INTERNAL_OPTION_SUSPEND,
5612                     &suspend,
5613                     sizeof(suspend));
5614
5615        if (err != OK) {
5616            ALOGE("Failed to set parameter 'drop-input-frames' (err %d)", err);
5617            return err;
5618        }
5619    }
5620
5621    int32_t dummy;
5622    if (params->findInt32("request-sync", &dummy)) {
5623        status_t err = requestIDRFrame();
5624
5625        if (err != OK) {
5626            ALOGE("Requesting a sync frame failed w/ err %d", err);
5627            return err;
5628        }
5629    }
5630
5631    return OK;
5632}
5633
5634void ACodec::onSignalEndOfInputStream() {
5635    sp<AMessage> notify = mNotify->dup();
5636    notify->setInt32("what", CodecBase::kWhatSignaledInputEOS);
5637
5638    status_t err = mOMX->signalEndOfInputStream(mNode);
5639    if (err != OK) {
5640        notify->setInt32("err", err);
5641    }
5642    notify->post();
5643}
5644
5645bool ACodec::ExecutingState::onOMXEvent(
5646        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5647    switch (event) {
5648        case OMX_EventPortSettingsChanged:
5649        {
5650            CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
5651
5652            if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
5653                mCodec->mMetaDataBuffersToSubmit = 0;
5654                CHECK_EQ(mCodec->mOMX->sendCommand(
5655                            mCodec->mNode,
5656                            OMX_CommandPortDisable, kPortIndexOutput),
5657                         (status_t)OK);
5658
5659                mCodec->freeOutputBuffersNotOwnedByComponent();
5660
5661                mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
5662            } else if (data2 == OMX_IndexConfigCommonOutputCrop) {
5663                mCodec->mSentFormat = false;
5664            } else {
5665                ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx",
5666                     mCodec->mComponentName.c_str(), data2);
5667            }
5668
5669            return true;
5670        }
5671
5672        case OMX_EventBufferFlag:
5673        {
5674            return true;
5675        }
5676
5677        default:
5678            return BaseState::onOMXEvent(event, data1, data2);
5679    }
5680}
5681
5682////////////////////////////////////////////////////////////////////////////////
5683
5684ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState(
5685        ACodec *codec)
5686    : BaseState(codec) {
5687}
5688
5689ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode(
5690        OMX_U32 portIndex) {
5691    if (portIndex == kPortIndexOutput) {
5692        return FREE_BUFFERS;
5693    }
5694
5695    CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput);
5696
5697    return RESUBMIT_BUFFERS;
5698}
5699
5700bool ACodec::OutputPortSettingsChangedState::onMessageReceived(
5701        const sp<AMessage> &msg) {
5702    bool handled = false;
5703
5704    switch (msg->what()) {
5705        case kWhatFlush:
5706        case kWhatShutdown:
5707        case kWhatResume:
5708        case kWhatSetParameters:
5709        {
5710            if (msg->what() == kWhatResume) {
5711                ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
5712            }
5713
5714            mCodec->deferMessage(msg);
5715            handled = true;
5716            break;
5717        }
5718
5719        default:
5720            handled = BaseState::onMessageReceived(msg);
5721            break;
5722    }
5723
5724    return handled;
5725}
5726
5727void ACodec::OutputPortSettingsChangedState::stateEntered() {
5728    ALOGV("[%s] Now handling output port settings change",
5729         mCodec->mComponentName.c_str());
5730}
5731
5732bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
5733        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5734    switch (event) {
5735        case OMX_EventCmdComplete:
5736        {
5737            if (data1 == (OMX_U32)OMX_CommandPortDisable) {
5738                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
5739
5740                ALOGV("[%s] Output port now disabled.",
5741                        mCodec->mComponentName.c_str());
5742
5743                CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty());
5744                mCodec->mDealer[kPortIndexOutput].clear();
5745
5746                CHECK_EQ(mCodec->mOMX->sendCommand(
5747                            mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput),
5748                         (status_t)OK);
5749
5750                status_t err;
5751                if ((err = mCodec->allocateBuffersOnPort(
5752                                kPortIndexOutput)) != OK) {
5753                    ALOGE("Failed to allocate output port buffers after "
5754                         "port reconfiguration (error 0x%08x)",
5755                         err);
5756
5757                    mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5758
5759                    // This is technically not correct, but appears to be
5760                    // the only way to free the component instance.
5761                    // Controlled transitioning from excecuting->idle
5762                    // and idle->loaded seem impossible probably because
5763                    // the output port never finishes re-enabling.
5764                    mCodec->mShutdownInProgress = true;
5765                    mCodec->mKeepComponentAllocated = false;
5766                    mCodec->changeState(mCodec->mLoadedState);
5767                }
5768
5769                return true;
5770            } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
5771                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
5772
5773                mCodec->mSentFormat = false;
5774
5775                ALOGV("[%s] Output port now reenabled.",
5776                        mCodec->mComponentName.c_str());
5777
5778                if (mCodec->mExecutingState->active()) {
5779                    mCodec->mExecutingState->submitOutputBuffers();
5780                }
5781
5782                mCodec->changeState(mCodec->mExecutingState);
5783
5784                return true;
5785            }
5786
5787            return false;
5788        }
5789
5790        default:
5791            return false;
5792    }
5793}
5794
5795////////////////////////////////////////////////////////////////////////////////
5796
5797ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec)
5798    : BaseState(codec),
5799      mComponentNowIdle(false) {
5800}
5801
5802bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) {
5803    bool handled = false;
5804
5805    switch (msg->what()) {
5806        case kWhatFlush:
5807        {
5808            // Don't send me a flush request if you previously wanted me
5809            // to shutdown.
5810            TRESPASS();
5811            break;
5812        }
5813
5814        case kWhatShutdown:
5815        {
5816            // We're already doing that...
5817
5818            handled = true;
5819            break;
5820        }
5821
5822        default:
5823            handled = BaseState::onMessageReceived(msg);
5824            break;
5825    }
5826
5827    return handled;
5828}
5829
5830void ACodec::ExecutingToIdleState::stateEntered() {
5831    ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
5832
5833    mComponentNowIdle = false;
5834    mCodec->mSentFormat = false;
5835}
5836
5837bool ACodec::ExecutingToIdleState::onOMXEvent(
5838        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5839    switch (event) {
5840        case OMX_EventCmdComplete:
5841        {
5842            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
5843            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
5844
5845            mComponentNowIdle = true;
5846
5847            changeStateIfWeOwnAllBuffers();
5848
5849            return true;
5850        }
5851
5852        case OMX_EventPortSettingsChanged:
5853        case OMX_EventBufferFlag:
5854        {
5855            // We're shutting down and don't care about this anymore.
5856            return true;
5857        }
5858
5859        default:
5860            return BaseState::onOMXEvent(event, data1, data2);
5861    }
5862}
5863
5864void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
5865    if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) {
5866        CHECK_EQ(mCodec->mOMX->sendCommand(
5867                    mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded),
5868                 (status_t)OK);
5869
5870        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK);
5871        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK);
5872
5873        if ((mCodec->mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown)
5874                && mCodec->mNativeWindow != NULL) {
5875            // We push enough 1x1 blank buffers to ensure that one of
5876            // them has made it to the display.  This allows the OMX
5877            // component teardown to zero out any protected buffers
5878            // without the risk of scanning out one of those buffers.
5879            mCodec->pushBlankBuffersToNativeWindow();
5880        }
5881
5882        mCodec->changeState(mCodec->mIdleToLoadedState);
5883    }
5884}
5885
5886void ACodec::ExecutingToIdleState::onInputBufferFilled(
5887        const sp<AMessage> &msg) {
5888    BaseState::onInputBufferFilled(msg);
5889
5890    changeStateIfWeOwnAllBuffers();
5891}
5892
5893void ACodec::ExecutingToIdleState::onOutputBufferDrained(
5894        const sp<AMessage> &msg) {
5895    BaseState::onOutputBufferDrained(msg);
5896
5897    changeStateIfWeOwnAllBuffers();
5898}
5899
5900////////////////////////////////////////////////////////////////////////////////
5901
5902ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec)
5903    : BaseState(codec) {
5904}
5905
5906bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) {
5907    bool handled = false;
5908
5909    switch (msg->what()) {
5910        case kWhatShutdown:
5911        {
5912            // We're already doing that...
5913
5914            handled = true;
5915            break;
5916        }
5917
5918        case kWhatFlush:
5919        {
5920            // Don't send me a flush request if you previously wanted me
5921            // to shutdown.
5922            TRESPASS();
5923            break;
5924        }
5925
5926        default:
5927            handled = BaseState::onMessageReceived(msg);
5928            break;
5929    }
5930
5931    return handled;
5932}
5933
5934void ACodec::IdleToLoadedState::stateEntered() {
5935    ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
5936}
5937
5938bool ACodec::IdleToLoadedState::onOMXEvent(
5939        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5940    switch (event) {
5941        case OMX_EventCmdComplete:
5942        {
5943            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
5944            CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded);
5945
5946            mCodec->changeState(mCodec->mLoadedState);
5947
5948            return true;
5949        }
5950
5951        default:
5952            return BaseState::onOMXEvent(event, data1, data2);
5953    }
5954}
5955
5956////////////////////////////////////////////////////////////////////////////////
5957
5958ACodec::FlushingState::FlushingState(ACodec *codec)
5959    : BaseState(codec) {
5960}
5961
5962void ACodec::FlushingState::stateEntered() {
5963    ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());
5964
5965    mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
5966}
5967
5968bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) {
5969    bool handled = false;
5970
5971    switch (msg->what()) {
5972        case kWhatShutdown:
5973        {
5974            mCodec->deferMessage(msg);
5975            break;
5976        }
5977
5978        case kWhatFlush:
5979        {
5980            // We're already doing this right now.
5981            handled = true;
5982            break;
5983        }
5984
5985        default:
5986            handled = BaseState::onMessageReceived(msg);
5987            break;
5988    }
5989
5990    return handled;
5991}
5992
5993bool ACodec::FlushingState::onOMXEvent(
5994        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5995    ALOGV("[%s] FlushingState onOMXEvent(%d,%ld)",
5996            mCodec->mComponentName.c_str(), event, data1);
5997
5998    switch (event) {
5999        case OMX_EventCmdComplete:
6000        {
6001            CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush);
6002
6003            if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
6004                CHECK(!mFlushComplete[data2]);
6005                mFlushComplete[data2] = true;
6006
6007                if (mFlushComplete[kPortIndexInput]
6008                        && mFlushComplete[kPortIndexOutput]) {
6009                    changeStateIfWeOwnAllBuffers();
6010                }
6011            } else {
6012                CHECK_EQ(data2, OMX_ALL);
6013                CHECK(mFlushComplete[kPortIndexInput]);
6014                CHECK(mFlushComplete[kPortIndexOutput]);
6015
6016                changeStateIfWeOwnAllBuffers();
6017            }
6018
6019            return true;
6020        }
6021
6022        case OMX_EventPortSettingsChanged:
6023        {
6024            sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec);
6025            msg->setInt32("type", omx_message::EVENT);
6026            msg->setInt32("node", mCodec->mNode);
6027            msg->setInt32("event", event);
6028            msg->setInt32("data1", data1);
6029            msg->setInt32("data2", data2);
6030
6031            ALOGV("[%s] Deferring OMX_EventPortSettingsChanged",
6032                 mCodec->mComponentName.c_str());
6033
6034            mCodec->deferMessage(msg);
6035
6036            return true;
6037        }
6038
6039        default:
6040            return BaseState::onOMXEvent(event, data1, data2);
6041    }
6042
6043    return true;
6044}
6045
6046void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) {
6047    BaseState::onOutputBufferDrained(msg);
6048
6049    changeStateIfWeOwnAllBuffers();
6050}
6051
6052void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) {
6053    BaseState::onInputBufferFilled(msg);
6054
6055    changeStateIfWeOwnAllBuffers();
6056}
6057
6058void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() {
6059    if (mFlushComplete[kPortIndexInput]
6060            && mFlushComplete[kPortIndexOutput]
6061            && mCodec->allYourBuffersAreBelongToUs()) {
6062        // We now own all buffers except possibly those still queued with
6063        // the native window for rendering. Let's get those back as well.
6064        mCodec->waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs();
6065
6066        sp<AMessage> notify = mCodec->mNotify->dup();
6067        notify->setInt32("what", CodecBase::kWhatFlushCompleted);
6068        notify->post();
6069
6070        mCodec->mPortEOS[kPortIndexInput] =
6071            mCodec->mPortEOS[kPortIndexOutput] = false;
6072
6073        mCodec->mInputEOSResult = OK;
6074
6075        if (mCodec->mSkipCutBuffer != NULL) {
6076            mCodec->mSkipCutBuffer->clear();
6077        }
6078
6079        mCodec->changeState(mCodec->mExecutingState);
6080    }
6081}
6082
6083}  // namespace android
6084