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