ACodec.cpp revision e6eea3a6b6e0cf92287ec1ceb8350f201d17e1ac
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                    if (portIndex != kPortIndexOutput) {
3204                        // TODO: also get input crop
3205                        break;
3206                    }
3207
3208                    OMX_CONFIG_RECTTYPE rect;
3209                    InitOMXParams(&rect);
3210                    rect.nPortIndex = portIndex;
3211
3212                    if (mOMX->getConfig(
3213                                mNode,
3214                                (portIndex == kPortIndexOutput ?
3215                                        OMX_IndexConfigCommonOutputCrop :
3216                                        OMX_IndexConfigCommonInputCrop),
3217                                &rect, sizeof(rect)) != OK) {
3218                        rect.nLeft = 0;
3219                        rect.nTop = 0;
3220                        rect.nWidth = videoDef->nFrameWidth;
3221                        rect.nHeight = videoDef->nFrameHeight;
3222                    }
3223
3224                    CHECK_GE(rect.nLeft, 0);
3225                    CHECK_GE(rect.nTop, 0);
3226                    CHECK_GE(rect.nWidth, 0u);
3227                    CHECK_GE(rect.nHeight, 0u);
3228                    CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth);
3229                    CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight);
3230
3231                    notify->setRect(
3232                            "crop",
3233                            rect.nLeft,
3234                            rect.nTop,
3235                            rect.nLeft + rect.nWidth - 1,
3236                            rect.nTop + rect.nHeight - 1);
3237
3238                    break;
3239                }
3240
3241                case OMX_VIDEO_CodingVP8:
3242                case OMX_VIDEO_CodingVP9:
3243                {
3244                    OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type;
3245                    InitOMXParams(&vp8type);
3246                    vp8type.nPortIndex = kPortIndexOutput;
3247                    status_t err = mOMX->getParameter(
3248                            mNode,
3249                            (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
3250                            &vp8type,
3251                            sizeof(vp8type));
3252
3253                    if (err == OK) {
3254                        AString tsSchema = "none";
3255                        if (vp8type.eTemporalPattern
3256                                == OMX_VIDEO_VPXTemporalLayerPatternWebRTC) {
3257                            switch (vp8type.nTemporalLayerCount) {
3258                                case 1:
3259                                {
3260                                    tsSchema = "webrtc.vp8.1-layer";
3261                                    break;
3262                                }
3263                                case 2:
3264                                {
3265                                    tsSchema = "webrtc.vp8.2-layer";
3266                                    break;
3267                                }
3268                                case 3:
3269                                {
3270                                    tsSchema = "webrtc.vp8.3-layer";
3271                                    break;
3272                                }
3273                                default:
3274                                {
3275                                    break;
3276                                }
3277                            }
3278                        }
3279                        notify->setString("ts-schema", tsSchema);
3280                    }
3281                    // Fall through to set up mime.
3282                }
3283
3284                default:
3285                {
3286                    CHECK(mIsEncoder ^ (portIndex == kPortIndexInput));
3287                    AString mime;
3288                    if (GetMimeTypeForVideoCoding(
3289                        videoDef->eCompressionFormat, &mime) != OK) {
3290                        notify->setString("mime", "application/octet-stream");
3291                    } else {
3292                        notify->setString("mime", mime.c_str());
3293                    }
3294                    break;
3295                }
3296            }
3297
3298            notify->setInt32("width", videoDef->nFrameWidth);
3299            notify->setInt32("height", videoDef->nFrameHeight);
3300            break;
3301        }
3302
3303        case OMX_PortDomainAudio:
3304        {
3305            OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
3306
3307            switch ((int)audioDef->eEncoding) {
3308                case OMX_AUDIO_CodingPCM:
3309                {
3310                    OMX_AUDIO_PARAM_PCMMODETYPE params;
3311                    InitOMXParams(&params);
3312                    params.nPortIndex = portIndex;
3313
3314                    CHECK_EQ(mOMX->getParameter(
3315                                mNode, OMX_IndexParamAudioPcm,
3316                                &params, sizeof(params)),
3317                             (status_t)OK);
3318
3319                    CHECK_GT(params.nChannels, 0);
3320                    CHECK(params.nChannels == 1 || params.bInterleaved);
3321                    CHECK_EQ(params.nBitPerSample, 16u);
3322
3323                    CHECK_EQ((int)params.eNumData,
3324                             (int)OMX_NumericalDataSigned);
3325
3326                    CHECK_EQ((int)params.ePCMMode,
3327                             (int)OMX_AUDIO_PCMModeLinear);
3328
3329                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
3330                    notify->setInt32("channel-count", params.nChannels);
3331                    notify->setInt32("sample-rate", params.nSamplingRate);
3332
3333                    if (mChannelMaskPresent) {
3334                        notify->setInt32("channel-mask", mChannelMask);
3335                    }
3336                    break;
3337                }
3338
3339                case OMX_AUDIO_CodingAAC:
3340                {
3341                    OMX_AUDIO_PARAM_AACPROFILETYPE params;
3342                    InitOMXParams(&params);
3343                    params.nPortIndex = portIndex;
3344
3345                    CHECK_EQ(mOMX->getParameter(
3346                                mNode, OMX_IndexParamAudioAac,
3347                                &params, sizeof(params)),
3348                             (status_t)OK);
3349
3350                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
3351                    notify->setInt32("channel-count", params.nChannels);
3352                    notify->setInt32("sample-rate", params.nSampleRate);
3353                    break;
3354                }
3355
3356                case OMX_AUDIO_CodingAMR:
3357                {
3358                    OMX_AUDIO_PARAM_AMRTYPE params;
3359                    InitOMXParams(&params);
3360                    params.nPortIndex = portIndex;
3361
3362                    CHECK_EQ(mOMX->getParameter(
3363                                mNode, OMX_IndexParamAudioAmr,
3364                                &params, sizeof(params)),
3365                             (status_t)OK);
3366
3367                    notify->setInt32("channel-count", 1);
3368                    if (params.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0) {
3369                        notify->setString(
3370                                "mime", MEDIA_MIMETYPE_AUDIO_AMR_WB);
3371
3372                        notify->setInt32("sample-rate", 16000);
3373                    } else {
3374                        notify->setString(
3375                                "mime", MEDIA_MIMETYPE_AUDIO_AMR_NB);
3376
3377                        notify->setInt32("sample-rate", 8000);
3378                    }
3379                    break;
3380                }
3381
3382                case OMX_AUDIO_CodingFLAC:
3383                {
3384                    OMX_AUDIO_PARAM_FLACTYPE params;
3385                    InitOMXParams(&params);
3386                    params.nPortIndex = portIndex;
3387
3388                    CHECK_EQ(mOMX->getParameter(
3389                                mNode, OMX_IndexParamAudioFlac,
3390                                &params, sizeof(params)),
3391                             (status_t)OK);
3392
3393                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_FLAC);
3394                    notify->setInt32("channel-count", params.nChannels);
3395                    notify->setInt32("sample-rate", params.nSampleRate);
3396                    break;
3397                }
3398
3399                case OMX_AUDIO_CodingMP3:
3400                {
3401                    OMX_AUDIO_PARAM_MP3TYPE params;
3402                    InitOMXParams(&params);
3403                    params.nPortIndex = portIndex;
3404
3405                    CHECK_EQ(mOMX->getParameter(
3406                                mNode, OMX_IndexParamAudioMp3,
3407                                &params, sizeof(params)),
3408                             (status_t)OK);
3409
3410                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MPEG);
3411                    notify->setInt32("channel-count", params.nChannels);
3412                    notify->setInt32("sample-rate", params.nSampleRate);
3413                    break;
3414                }
3415
3416                case OMX_AUDIO_CodingVORBIS:
3417                {
3418                    OMX_AUDIO_PARAM_VORBISTYPE params;
3419                    InitOMXParams(&params);
3420                    params.nPortIndex = portIndex;
3421
3422                    CHECK_EQ(mOMX->getParameter(
3423                                mNode, OMX_IndexParamAudioVorbis,
3424                                &params, sizeof(params)),
3425                             (status_t)OK);
3426
3427                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_VORBIS);
3428                    notify->setInt32("channel-count", params.nChannels);
3429                    notify->setInt32("sample-rate", params.nSampleRate);
3430                    break;
3431                }
3432
3433                case OMX_AUDIO_CodingAndroidAC3:
3434                {
3435                    OMX_AUDIO_PARAM_ANDROID_AC3TYPE params;
3436                    InitOMXParams(&params);
3437                    params.nPortIndex = portIndex;
3438
3439                    CHECK_EQ((status_t)OK, mOMX->getParameter(
3440                            mNode,
3441                            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
3442                            &params,
3443                            sizeof(params)));
3444
3445                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AC3);
3446                    notify->setInt32("channel-count", params.nChannels);
3447                    notify->setInt32("sample-rate", params.nSampleRate);
3448                    break;
3449                }
3450
3451                case OMX_AUDIO_CodingAndroidOPUS:
3452                {
3453                    OMX_AUDIO_PARAM_ANDROID_OPUSTYPE params;
3454                    InitOMXParams(&params);
3455                    params.nPortIndex = portIndex;
3456
3457                    CHECK_EQ((status_t)OK, mOMX->getParameter(
3458                            mNode,
3459                            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus,
3460                            &params,
3461                            sizeof(params)));
3462
3463                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_OPUS);
3464                    notify->setInt32("channel-count", params.nChannels);
3465                    notify->setInt32("sample-rate", params.nSampleRate);
3466                    break;
3467                }
3468
3469                case OMX_AUDIO_CodingG711:
3470                {
3471                    OMX_AUDIO_PARAM_PCMMODETYPE params;
3472                    InitOMXParams(&params);
3473                    params.nPortIndex = portIndex;
3474
3475                    CHECK_EQ((status_t)OK, mOMX->getParameter(
3476                            mNode,
3477                            (OMX_INDEXTYPE)OMX_IndexParamAudioPcm,
3478                            &params,
3479                            sizeof(params)));
3480
3481                    const char *mime = NULL;
3482                    if (params.ePCMMode == OMX_AUDIO_PCMModeMULaw) {
3483                        mime = MEDIA_MIMETYPE_AUDIO_G711_MLAW;
3484                    } else if (params.ePCMMode == OMX_AUDIO_PCMModeALaw) {
3485                        mime = MEDIA_MIMETYPE_AUDIO_G711_ALAW;
3486                    } else { // params.ePCMMode == OMX_AUDIO_PCMModeLinear
3487                        mime = MEDIA_MIMETYPE_AUDIO_RAW;
3488                    }
3489                    notify->setString("mime", mime);
3490                    notify->setInt32("channel-count", params.nChannels);
3491                    notify->setInt32("sample-rate", params.nSamplingRate);
3492                    break;
3493                }
3494
3495                default:
3496                    ALOGE("UNKNOWN AUDIO CODING: %d\n", audioDef->eEncoding);
3497                    TRESPASS();
3498            }
3499            break;
3500        }
3501
3502        default:
3503            TRESPASS();
3504    }
3505
3506    return OK;
3507}
3508
3509void ACodec::sendFormatChange(const sp<AMessage> &reply) {
3510    sp<AMessage> notify = mNotify->dup();
3511    notify->setInt32("what", kWhatOutputFormatChanged);
3512
3513    CHECK_EQ(getPortFormat(kPortIndexOutput, notify), (status_t)OK);
3514
3515    AString mime;
3516    CHECK(notify->findString("mime", &mime));
3517
3518    int32_t left, top, right, bottom;
3519    if (mime == MEDIA_MIMETYPE_VIDEO_RAW &&
3520        mNativeWindow != NULL &&
3521        notify->findRect("crop", &left, &top, &right, &bottom)) {
3522        // notify renderer of the crop change
3523        // NOTE: native window uses extended right-bottom coordinate
3524        reply->setRect("crop", left, top, right + 1, bottom + 1);
3525    } else if (mime == MEDIA_MIMETYPE_AUDIO_RAW &&
3526               (mEncoderDelay || mEncoderPadding)) {
3527        int32_t channelCount;
3528        CHECK(notify->findInt32("channel-count", &channelCount));
3529        size_t frameSize = channelCount * sizeof(int16_t);
3530        if (mSkipCutBuffer != NULL) {
3531            size_t prevbufsize = mSkipCutBuffer->size();
3532            if (prevbufsize != 0) {
3533                ALOGW("Replacing SkipCutBuffer holding %d "
3534                      "bytes",
3535                      prevbufsize);
3536            }
3537        }
3538        mSkipCutBuffer = new SkipCutBuffer(
3539                mEncoderDelay * frameSize,
3540                mEncoderPadding * frameSize);
3541    }
3542
3543    notify->post();
3544
3545    mSentFormat = true;
3546}
3547
3548void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) {
3549    sp<AMessage> notify = mNotify->dup();
3550    notify->setInt32("what", CodecBase::kWhatError);
3551    ALOGE("signalError(omxError %#x, internalError %d)", error, internalError);
3552
3553    if (internalError == UNKNOWN_ERROR) { // find better error code
3554        const status_t omxStatus = statusFromOMXError(error);
3555        if (omxStatus != 0) {
3556            internalError = omxStatus;
3557        } else {
3558            ALOGW("Invalid OMX error %#x", error);
3559        }
3560    }
3561    notify->setInt32("err", internalError);
3562    notify->setInt32("actionCode", ACTION_CODE_FATAL); // could translate from OMX error.
3563    notify->post();
3564}
3565
3566status_t ACodec::pushBlankBuffersToNativeWindow() {
3567    status_t err = NO_ERROR;
3568    ANativeWindowBuffer* anb = NULL;
3569    int numBufs = 0;
3570    int minUndequeuedBufs = 0;
3571
3572    // We need to reconnect to the ANativeWindow as a CPU client to ensure that
3573    // no frames get dropped by SurfaceFlinger assuming that these are video
3574    // frames.
3575    err = native_window_api_disconnect(mNativeWindow.get(),
3576            NATIVE_WINDOW_API_MEDIA);
3577    if (err != NO_ERROR) {
3578        ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
3579                strerror(-err), -err);
3580        return err;
3581    }
3582
3583    err = native_window_api_connect(mNativeWindow.get(),
3584            NATIVE_WINDOW_API_CPU);
3585    if (err != NO_ERROR) {
3586        ALOGE("error pushing blank frames: api_connect failed: %s (%d)",
3587                strerror(-err), -err);
3588        return err;
3589    }
3590
3591    err = native_window_set_buffers_geometry(mNativeWindow.get(), 1, 1,
3592            HAL_PIXEL_FORMAT_RGBX_8888);
3593    if (err != NO_ERROR) {
3594        ALOGE("error pushing blank frames: set_buffers_geometry failed: %s (%d)",
3595                strerror(-err), -err);
3596        goto error;
3597    }
3598
3599    err = native_window_set_scaling_mode(mNativeWindow.get(),
3600                NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
3601    if (err != NO_ERROR) {
3602        ALOGE("error pushing blank_frames: set_scaling_mode failed: %s (%d)",
3603              strerror(-err), -err);
3604        goto error;
3605    }
3606
3607    err = native_window_set_usage(mNativeWindow.get(),
3608            GRALLOC_USAGE_SW_WRITE_OFTEN);
3609    if (err != NO_ERROR) {
3610        ALOGE("error pushing blank frames: set_usage failed: %s (%d)",
3611                strerror(-err), -err);
3612        goto error;
3613    }
3614
3615    err = mNativeWindow->query(mNativeWindow.get(),
3616            NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs);
3617    if (err != NO_ERROR) {
3618        ALOGE("error pushing blank frames: MIN_UNDEQUEUED_BUFFERS query "
3619                "failed: %s (%d)", strerror(-err), -err);
3620        goto error;
3621    }
3622
3623    numBufs = minUndequeuedBufs + 1;
3624    err = native_window_set_buffer_count(mNativeWindow.get(), numBufs);
3625    if (err != NO_ERROR) {
3626        ALOGE("error pushing blank frames: set_buffer_count failed: %s (%d)",
3627                strerror(-err), -err);
3628        goto error;
3629    }
3630
3631    // We  push numBufs + 1 buffers to ensure that we've drawn into the same
3632    // buffer twice.  This should guarantee that the buffer has been displayed
3633    // on the screen and then been replaced, so an previous video frames are
3634    // guaranteed NOT to be currently displayed.
3635    for (int i = 0; i < numBufs + 1; i++) {
3636        int fenceFd = -1;
3637        err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &anb);
3638        if (err != NO_ERROR) {
3639            ALOGE("error pushing blank frames: dequeueBuffer failed: %s (%d)",
3640                    strerror(-err), -err);
3641            goto error;
3642        }
3643
3644        sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
3645
3646        // Fill the buffer with the a 1x1 checkerboard pattern ;)
3647        uint32_t* img = NULL;
3648        err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
3649        if (err != NO_ERROR) {
3650            ALOGE("error pushing blank frames: lock failed: %s (%d)",
3651                    strerror(-err), -err);
3652            goto error;
3653        }
3654
3655        *img = 0;
3656
3657        err = buf->unlock();
3658        if (err != NO_ERROR) {
3659            ALOGE("error pushing blank frames: unlock failed: %s (%d)",
3660                    strerror(-err), -err);
3661            goto error;
3662        }
3663
3664        err = mNativeWindow->queueBuffer(mNativeWindow.get(),
3665                buf->getNativeBuffer(), -1);
3666        if (err != NO_ERROR) {
3667            ALOGE("error pushing blank frames: queueBuffer failed: %s (%d)",
3668                    strerror(-err), -err);
3669            goto error;
3670        }
3671
3672        anb = NULL;
3673    }
3674
3675error:
3676
3677    if (err != NO_ERROR) {
3678        // Clean up after an error.
3679        if (anb != NULL) {
3680            mNativeWindow->cancelBuffer(mNativeWindow.get(), anb, -1);
3681        }
3682
3683        native_window_api_disconnect(mNativeWindow.get(),
3684                NATIVE_WINDOW_API_CPU);
3685        native_window_api_connect(mNativeWindow.get(),
3686                NATIVE_WINDOW_API_MEDIA);
3687
3688        return err;
3689    } else {
3690        // Clean up after success.
3691        err = native_window_api_disconnect(mNativeWindow.get(),
3692                NATIVE_WINDOW_API_CPU);
3693        if (err != NO_ERROR) {
3694            ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
3695                    strerror(-err), -err);
3696            return err;
3697        }
3698
3699        err = native_window_api_connect(mNativeWindow.get(),
3700                NATIVE_WINDOW_API_MEDIA);
3701        if (err != NO_ERROR) {
3702            ALOGE("error pushing blank frames: api_connect failed: %s (%d)",
3703                    strerror(-err), -err);
3704            return err;
3705        }
3706
3707        return NO_ERROR;
3708    }
3709}
3710
3711////////////////////////////////////////////////////////////////////////////////
3712
3713ACodec::PortDescription::PortDescription() {
3714}
3715
3716status_t ACodec::requestIDRFrame() {
3717    if (!mIsEncoder) {
3718        return ERROR_UNSUPPORTED;
3719    }
3720
3721    OMX_CONFIG_INTRAREFRESHVOPTYPE params;
3722    InitOMXParams(&params);
3723
3724    params.nPortIndex = kPortIndexOutput;
3725    params.IntraRefreshVOP = OMX_TRUE;
3726
3727    return mOMX->setConfig(
3728            mNode,
3729            OMX_IndexConfigVideoIntraVOPRefresh,
3730            &params,
3731            sizeof(params));
3732}
3733
3734void ACodec::PortDescription::addBuffer(
3735        IOMX::buffer_id id, const sp<ABuffer> &buffer) {
3736    mBufferIDs.push_back(id);
3737    mBuffers.push_back(buffer);
3738}
3739
3740size_t ACodec::PortDescription::countBuffers() {
3741    return mBufferIDs.size();
3742}
3743
3744IOMX::buffer_id ACodec::PortDescription::bufferIDAt(size_t index) const {
3745    return mBufferIDs.itemAt(index);
3746}
3747
3748sp<ABuffer> ACodec::PortDescription::bufferAt(size_t index) const {
3749    return mBuffers.itemAt(index);
3750}
3751
3752////////////////////////////////////////////////////////////////////////////////
3753
3754ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
3755    : AState(parentState),
3756      mCodec(codec) {
3757}
3758
3759ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(
3760        OMX_U32 /* portIndex */) {
3761    return KEEP_BUFFERS;
3762}
3763
3764bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) {
3765    switch (msg->what()) {
3766        case kWhatInputBufferFilled:
3767        {
3768            onInputBufferFilled(msg);
3769            break;
3770        }
3771
3772        case kWhatOutputBufferDrained:
3773        {
3774            onOutputBufferDrained(msg);
3775            break;
3776        }
3777
3778        case ACodec::kWhatOMXMessage:
3779        {
3780            return onOMXMessage(msg);
3781        }
3782
3783        case ACodec::kWhatCreateInputSurface:
3784        case ACodec::kWhatSignalEndOfInputStream:
3785        {
3786            // This may result in an app illegal state exception.
3787            ALOGE("Message 0x%x was not handled", msg->what());
3788            mCodec->signalError(OMX_ErrorUndefined, INVALID_OPERATION);
3789            return true;
3790        }
3791
3792        case ACodec::kWhatOMXDied:
3793        {
3794            // This will result in kFlagSawMediaServerDie handling in MediaCodec.
3795            ALOGE("OMX/mediaserver died, signalling error!");
3796            mCodec->signalError(OMX_ErrorResourcesLost, DEAD_OBJECT);
3797            break;
3798        }
3799
3800        default:
3801            return false;
3802    }
3803
3804    return true;
3805}
3806
3807bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) {
3808    int32_t type;
3809    CHECK(msg->findInt32("type", &type));
3810
3811    // there is a possibility that this is an outstanding message for a
3812    // codec that we have already destroyed
3813    if (mCodec->mNode == NULL) {
3814        ALOGI("ignoring message as already freed component: %s",
3815                msg->debugString().c_str());
3816        return true;
3817    }
3818
3819    IOMX::node_id nodeID;
3820    CHECK(msg->findInt32("node", (int32_t*)&nodeID));
3821    CHECK_EQ(nodeID, mCodec->mNode);
3822
3823    switch (type) {
3824        case omx_message::EVENT:
3825        {
3826            int32_t event, data1, data2;
3827            CHECK(msg->findInt32("event", &event));
3828            CHECK(msg->findInt32("data1", &data1));
3829            CHECK(msg->findInt32("data2", &data2));
3830
3831            if (event == OMX_EventCmdComplete
3832                    && data1 == OMX_CommandFlush
3833                    && data2 == (int32_t)OMX_ALL) {
3834                // Use of this notification is not consistent across
3835                // implementations. We'll drop this notification and rely
3836                // on flush-complete notifications on the individual port
3837                // indices instead.
3838
3839                return true;
3840            }
3841
3842            return onOMXEvent(
3843                    static_cast<OMX_EVENTTYPE>(event),
3844                    static_cast<OMX_U32>(data1),
3845                    static_cast<OMX_U32>(data2));
3846        }
3847
3848        case omx_message::EMPTY_BUFFER_DONE:
3849        {
3850            IOMX::buffer_id bufferID;
3851            CHECK(msg->findInt32("buffer", (int32_t*)&bufferID));
3852
3853            return onOMXEmptyBufferDone(bufferID);
3854        }
3855
3856        case omx_message::FILL_BUFFER_DONE:
3857        {
3858            IOMX::buffer_id bufferID;
3859            CHECK(msg->findInt32("buffer", (int32_t*)&bufferID));
3860
3861            int32_t rangeOffset, rangeLength, flags;
3862            int64_t timeUs;
3863
3864            CHECK(msg->findInt32("range_offset", &rangeOffset));
3865            CHECK(msg->findInt32("range_length", &rangeLength));
3866            CHECK(msg->findInt32("flags", &flags));
3867            CHECK(msg->findInt64("timestamp", &timeUs));
3868
3869            return onOMXFillBufferDone(
3870                    bufferID,
3871                    (size_t)rangeOffset, (size_t)rangeLength,
3872                    (OMX_U32)flags,
3873                    timeUs);
3874        }
3875
3876        default:
3877            TRESPASS();
3878            break;
3879    }
3880}
3881
3882bool ACodec::BaseState::onOMXEvent(
3883        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3884    if (event != OMX_EventError) {
3885        ALOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)",
3886             mCodec->mComponentName.c_str(), event, data1, data2);
3887
3888        return false;
3889    }
3890
3891    ALOGE("[%s] ERROR(0x%08lx)", mCodec->mComponentName.c_str(), data1);
3892
3893    // verify OMX component sends back an error we expect.
3894    OMX_ERRORTYPE omxError = (OMX_ERRORTYPE)data1;
3895    if (!isOMXError(omxError)) {
3896        ALOGW("Invalid OMX error %#x", omxError);
3897        omxError = OMX_ErrorUndefined;
3898    }
3899    mCodec->signalError(omxError);
3900
3901    return true;
3902}
3903
3904bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) {
3905    ALOGV("[%s] onOMXEmptyBufferDone %p",
3906         mCodec->mComponentName.c_str(), bufferID);
3907
3908    BufferInfo *info =
3909        mCodec->findBufferByID(kPortIndexInput, bufferID);
3910
3911    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
3912    info->mStatus = BufferInfo::OWNED_BY_US;
3913
3914    // We're in "store-metadata-in-buffers" mode, the underlying
3915    // OMX component had access to data that's implicitly refcounted
3916    // by this "MediaBuffer" object. Now that the OMX component has
3917    // told us that it's done with the input buffer, we can decrement
3918    // the mediaBuffer's reference count.
3919    info->mData->setMediaBufferBase(NULL);
3920
3921    PortMode mode = getPortMode(kPortIndexInput);
3922
3923    switch (mode) {
3924        case KEEP_BUFFERS:
3925            break;
3926
3927        case RESUBMIT_BUFFERS:
3928            postFillThisBuffer(info);
3929            break;
3930
3931        default:
3932        {
3933            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
3934            TRESPASS();  // Not currently used
3935            break;
3936        }
3937    }
3938
3939    return true;
3940}
3941
3942void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) {
3943    if (mCodec->mPortEOS[kPortIndexInput]) {
3944        return;
3945    }
3946
3947    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
3948
3949    sp<AMessage> notify = mCodec->mNotify->dup();
3950    notify->setInt32("what", CodecBase::kWhatFillThisBuffer);
3951    notify->setInt32("buffer-id", info->mBufferID);
3952
3953    info->mData->meta()->clear();
3954    notify->setBuffer("buffer", info->mData);
3955
3956    sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id());
3957    reply->setInt32("buffer-id", info->mBufferID);
3958
3959    notify->setMessage("reply", reply);
3960
3961    notify->post();
3962
3963    info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
3964}
3965
3966void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
3967    IOMX::buffer_id bufferID;
3968    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
3969    sp<ABuffer> buffer;
3970    int32_t err = OK;
3971    bool eos = false;
3972    PortMode mode = getPortMode(kPortIndexInput);
3973
3974    if (!msg->findBuffer("buffer", &buffer)) {
3975        /* these are unfilled buffers returned by client */
3976        CHECK(msg->findInt32("err", &err));
3977
3978        if (err == OK) {
3979            /* buffers with no errors are returned on MediaCodec.flush */
3980            mode = KEEP_BUFFERS;
3981        } else {
3982            ALOGV("[%s] saw error %d instead of an input buffer",
3983                 mCodec->mComponentName.c_str(), err);
3984            eos = true;
3985        }
3986
3987        buffer.clear();
3988    }
3989
3990    int32_t tmp;
3991    if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) {
3992        eos = true;
3993        err = ERROR_END_OF_STREAM;
3994    }
3995
3996    BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
3997    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM);
3998
3999    info->mStatus = BufferInfo::OWNED_BY_US;
4000
4001    switch (mode) {
4002        case KEEP_BUFFERS:
4003        {
4004            if (eos) {
4005                if (!mCodec->mPortEOS[kPortIndexInput]) {
4006                    mCodec->mPortEOS[kPortIndexInput] = true;
4007                    mCodec->mInputEOSResult = err;
4008                }
4009            }
4010            break;
4011        }
4012
4013        case RESUBMIT_BUFFERS:
4014        {
4015            if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) {
4016                int64_t timeUs;
4017                CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
4018
4019                OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
4020
4021                int32_t isCSD;
4022                if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) {
4023                    flags |= OMX_BUFFERFLAG_CODECCONFIG;
4024                }
4025
4026                if (eos) {
4027                    flags |= OMX_BUFFERFLAG_EOS;
4028                }
4029
4030                if (buffer != info->mData) {
4031                    ALOGV("[%s] Needs to copy input data for buffer %p. (%p != %p)",
4032                         mCodec->mComponentName.c_str(),
4033                         bufferID,
4034                         buffer.get(), info->mData.get());
4035
4036                    CHECK_LE(buffer->size(), info->mData->capacity());
4037                    memcpy(info->mData->data(), buffer->data(), buffer->size());
4038                }
4039
4040                if (flags & OMX_BUFFERFLAG_CODECCONFIG) {
4041                    ALOGV("[%s] calling emptyBuffer %p w/ codec specific data",
4042                         mCodec->mComponentName.c_str(), bufferID);
4043                } else if (flags & OMX_BUFFERFLAG_EOS) {
4044                    ALOGV("[%s] calling emptyBuffer %p w/ EOS",
4045                         mCodec->mComponentName.c_str(), bufferID);
4046                } else {
4047#if TRACK_BUFFER_TIMING
4048                    ALOGI("[%s] calling emptyBuffer %p w/ time %lld us",
4049                         mCodec->mComponentName.c_str(), bufferID, timeUs);
4050#else
4051                    ALOGV("[%s] calling emptyBuffer %p w/ time %lld us",
4052                         mCodec->mComponentName.c_str(), bufferID, timeUs);
4053#endif
4054                }
4055
4056#if TRACK_BUFFER_TIMING
4057                ACodec::BufferStats stats;
4058                stats.mEmptyBufferTimeUs = ALooper::GetNowUs();
4059                stats.mFillBufferDoneTimeUs = -1ll;
4060                mCodec->mBufferStats.add(timeUs, stats);
4061#endif
4062
4063                if (mCodec->mStoreMetaDataInOutputBuffers) {
4064                    // try to submit an output buffer for each input buffer
4065                    PortMode outputMode = getPortMode(kPortIndexOutput);
4066
4067                    ALOGV("MetaDataBuffersToSubmit=%u portMode=%s",
4068                            mCodec->mMetaDataBuffersToSubmit,
4069                            (outputMode == FREE_BUFFERS ? "FREE" :
4070                             outputMode == KEEP_BUFFERS ? "KEEP" : "RESUBMIT"));
4071                    if (outputMode == RESUBMIT_BUFFERS) {
4072                        mCodec->submitOutputMetaDataBuffer();
4073                    }
4074                }
4075
4076                CHECK_EQ(mCodec->mOMX->emptyBuffer(
4077                            mCodec->mNode,
4078                            bufferID,
4079                            0,
4080                            buffer->size(),
4081                            flags,
4082                            timeUs),
4083                         (status_t)OK);
4084
4085                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4086
4087                if (!eos) {
4088                    getMoreInputDataIfPossible();
4089                } else {
4090                    ALOGV("[%s] Signalled EOS on the input port",
4091                         mCodec->mComponentName.c_str());
4092
4093                    mCodec->mPortEOS[kPortIndexInput] = true;
4094                    mCodec->mInputEOSResult = err;
4095                }
4096            } else if (!mCodec->mPortEOS[kPortIndexInput]) {
4097                if (err != ERROR_END_OF_STREAM) {
4098                    ALOGV("[%s] Signalling EOS on the input port "
4099                         "due to error %d",
4100                         mCodec->mComponentName.c_str(), err);
4101                } else {
4102                    ALOGV("[%s] Signalling EOS on the input port",
4103                         mCodec->mComponentName.c_str());
4104                }
4105
4106                ALOGV("[%s] calling emptyBuffer %p signalling EOS",
4107                     mCodec->mComponentName.c_str(), bufferID);
4108
4109                CHECK_EQ(mCodec->mOMX->emptyBuffer(
4110                            mCodec->mNode,
4111                            bufferID,
4112                            0,
4113                            0,
4114                            OMX_BUFFERFLAG_EOS,
4115                            0),
4116                         (status_t)OK);
4117
4118                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4119
4120                mCodec->mPortEOS[kPortIndexInput] = true;
4121                mCodec->mInputEOSResult = err;
4122            }
4123            break;
4124        }
4125
4126        default:
4127            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
4128            break;
4129    }
4130}
4131
4132void ACodec::BaseState::getMoreInputDataIfPossible() {
4133    if (mCodec->mPortEOS[kPortIndexInput]) {
4134        return;
4135    }
4136
4137    BufferInfo *eligible = NULL;
4138
4139    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
4140        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
4141
4142#if 0
4143        if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) {
4144            // There's already a "read" pending.
4145            return;
4146        }
4147#endif
4148
4149        if (info->mStatus == BufferInfo::OWNED_BY_US) {
4150            eligible = info;
4151        }
4152    }
4153
4154    if (eligible == NULL) {
4155        return;
4156    }
4157
4158    postFillThisBuffer(eligible);
4159}
4160
4161bool ACodec::BaseState::onOMXFillBufferDone(
4162        IOMX::buffer_id bufferID,
4163        size_t rangeOffset, size_t rangeLength,
4164        OMX_U32 flags,
4165        int64_t timeUs) {
4166    ALOGV("[%s] onOMXFillBufferDone %u time %" PRId64 " us, flags = 0x%08x",
4167         mCodec->mComponentName.c_str(), bufferID, timeUs, flags);
4168
4169    ssize_t index;
4170
4171#if TRACK_BUFFER_TIMING
4172    index = mCodec->mBufferStats.indexOfKey(timeUs);
4173    if (index >= 0) {
4174        ACodec::BufferStats *stats = &mCodec->mBufferStats.editValueAt(index);
4175        stats->mFillBufferDoneTimeUs = ALooper::GetNowUs();
4176
4177        ALOGI("frame PTS %lld: %lld",
4178                timeUs,
4179                stats->mFillBufferDoneTimeUs - stats->mEmptyBufferTimeUs);
4180
4181        mCodec->mBufferStats.removeItemsAt(index);
4182        stats = NULL;
4183    }
4184#endif
4185
4186    BufferInfo *info =
4187        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
4188
4189    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
4190
4191    info->mDequeuedAt = ++mCodec->mDequeueCounter;
4192    info->mStatus = BufferInfo::OWNED_BY_US;
4193
4194    PortMode mode = getPortMode(kPortIndexOutput);
4195
4196    switch (mode) {
4197        case KEEP_BUFFERS:
4198            break;
4199
4200        case RESUBMIT_BUFFERS:
4201        {
4202            if (rangeLength == 0 && !(flags & OMX_BUFFERFLAG_EOS)) {
4203                ALOGV("[%s] calling fillBuffer %u",
4204                     mCodec->mComponentName.c_str(), info->mBufferID);
4205
4206                CHECK_EQ(mCodec->mOMX->fillBuffer(
4207                            mCodec->mNode, info->mBufferID),
4208                         (status_t)OK);
4209
4210                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4211                break;
4212            }
4213
4214            sp<AMessage> reply =
4215                new AMessage(kWhatOutputBufferDrained, mCodec->id());
4216
4217            if (!mCodec->mSentFormat && rangeLength > 0) {
4218                mCodec->sendFormatChange(reply);
4219            }
4220
4221            if (mCodec->mUseMetadataOnEncoderOutput) {
4222                native_handle_t* handle =
4223                        *(native_handle_t**)(info->mData->data() + 4);
4224                info->mData->meta()->setPointer("handle", handle);
4225                info->mData->meta()->setInt32("rangeOffset", rangeOffset);
4226                info->mData->meta()->setInt32("rangeLength", rangeLength);
4227            } else {
4228                info->mData->setRange(rangeOffset, rangeLength);
4229            }
4230#if 0
4231            if (mCodec->mNativeWindow == NULL) {
4232                if (IsIDR(info->mData)) {
4233                    ALOGI("IDR frame");
4234                }
4235            }
4236#endif
4237
4238            if (mCodec->mSkipCutBuffer != NULL) {
4239                mCodec->mSkipCutBuffer->submit(info->mData);
4240            }
4241            info->mData->meta()->setInt64("timeUs", timeUs);
4242
4243            sp<AMessage> notify = mCodec->mNotify->dup();
4244            notify->setInt32("what", CodecBase::kWhatDrainThisBuffer);
4245            notify->setInt32("buffer-id", info->mBufferID);
4246            notify->setBuffer("buffer", info->mData);
4247            notify->setInt32("flags", flags);
4248
4249            reply->setInt32("buffer-id", info->mBufferID);
4250
4251            notify->setMessage("reply", reply);
4252
4253            notify->post();
4254
4255            info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;
4256
4257            if (flags & OMX_BUFFERFLAG_EOS) {
4258                ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str());
4259
4260                sp<AMessage> notify = mCodec->mNotify->dup();
4261                notify->setInt32("what", CodecBase::kWhatEOS);
4262                notify->setInt32("err", mCodec->mInputEOSResult);
4263                notify->post();
4264
4265                mCodec->mPortEOS[kPortIndexOutput] = true;
4266            }
4267            break;
4268        }
4269
4270        default:
4271        {
4272            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
4273
4274            CHECK_EQ((status_t)OK,
4275                     mCodec->freeBuffer(kPortIndexOutput, index));
4276            break;
4277        }
4278    }
4279
4280    return true;
4281}
4282
4283void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
4284    IOMX::buffer_id bufferID;
4285    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
4286    ssize_t index;
4287    BufferInfo *info =
4288        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
4289    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
4290
4291    android_native_rect_t crop;
4292    if (msg->findRect("crop",
4293            &crop.left, &crop.top, &crop.right, &crop.bottom)) {
4294        CHECK_EQ(0, native_window_set_crop(
4295                mCodec->mNativeWindow.get(), &crop));
4296    }
4297
4298    int32_t render;
4299    if (mCodec->mNativeWindow != NULL
4300            && msg->findInt32("render", &render) && render != 0
4301            && info->mData != NULL && info->mData->size() != 0) {
4302        ATRACE_NAME("render");
4303        // The client wants this buffer to be rendered.
4304
4305        int64_t timestampNs = 0;
4306        if (!msg->findInt64("timestampNs", &timestampNs)) {
4307            // TODO: it seems like we should use the timestamp
4308            // in the (media)buffer as it potentially came from
4309            // an input surface, but we did not propagate it prior to
4310            // API 20.  Perhaps check for target SDK version.
4311#if 0
4312            if (info->mData->meta()->findInt64("timeUs", &timestampNs)) {
4313                ALOGV("using buffer PTS of %" PRId64, timestampNs);
4314                timestampNs *= 1000;
4315            }
4316#endif
4317        }
4318
4319        status_t err;
4320        err = native_window_set_buffers_timestamp(mCodec->mNativeWindow.get(), timestampNs);
4321        if (err != OK) {
4322            ALOGW("failed to set buffer timestamp: %d", err);
4323        }
4324
4325        if ((err = mCodec->mNativeWindow->queueBuffer(
4326                    mCodec->mNativeWindow.get(),
4327                    info->mGraphicBuffer.get(), -1)) == OK) {
4328            info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
4329        } else {
4330            mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
4331            info->mStatus = BufferInfo::OWNED_BY_US;
4332        }
4333    } else {
4334        if (mCodec->mNativeWindow != NULL &&
4335            (info->mData == NULL || info->mData->size() != 0)) {
4336            ATRACE_NAME("frame-drop");
4337        }
4338        info->mStatus = BufferInfo::OWNED_BY_US;
4339    }
4340
4341    PortMode mode = getPortMode(kPortIndexOutput);
4342
4343    switch (mode) {
4344        case KEEP_BUFFERS:
4345        {
4346            // XXX fishy, revisit!!! What about the FREE_BUFFERS case below?
4347
4348            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
4349                // We cannot resubmit the buffer we just rendered, dequeue
4350                // the spare instead.
4351
4352                info = mCodec->dequeueBufferFromNativeWindow();
4353            }
4354            break;
4355        }
4356
4357        case RESUBMIT_BUFFERS:
4358        {
4359            if (!mCodec->mPortEOS[kPortIndexOutput]) {
4360                if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
4361                    // We cannot resubmit the buffer we just rendered, dequeue
4362                    // the spare instead.
4363
4364                    info = mCodec->dequeueBufferFromNativeWindow();
4365                }
4366
4367                if (info != NULL) {
4368                    ALOGV("[%s] calling fillBuffer %u",
4369                         mCodec->mComponentName.c_str(), info->mBufferID);
4370
4371                    CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
4372                             (status_t)OK);
4373
4374                    info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4375                }
4376            }
4377            break;
4378        }
4379
4380        default:
4381        {
4382            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
4383
4384            CHECK_EQ((status_t)OK,
4385                     mCodec->freeBuffer(kPortIndexOutput, index));
4386            break;
4387        }
4388    }
4389}
4390
4391////////////////////////////////////////////////////////////////////////////////
4392
4393ACodec::UninitializedState::UninitializedState(ACodec *codec)
4394    : BaseState(codec) {
4395}
4396
4397void ACodec::UninitializedState::stateEntered() {
4398    ALOGV("Now uninitialized");
4399
4400    if (mDeathNotifier != NULL) {
4401        mCodec->mOMX->asBinder()->unlinkToDeath(mDeathNotifier);
4402        mDeathNotifier.clear();
4403    }
4404
4405    mCodec->mNativeWindow.clear();
4406    mCodec->mNode = NULL;
4407    mCodec->mOMX.clear();
4408    mCodec->mQuirks = 0;
4409    mCodec->mFlags = 0;
4410    mCodec->mUseMetadataOnEncoderOutput = 0;
4411    mCodec->mComponentName.clear();
4412}
4413
4414bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
4415    bool handled = false;
4416
4417    switch (msg->what()) {
4418        case ACodec::kWhatSetup:
4419        {
4420            onSetup(msg);
4421
4422            handled = true;
4423            break;
4424        }
4425
4426        case ACodec::kWhatAllocateComponent:
4427        {
4428            onAllocateComponent(msg);
4429            handled = true;
4430            break;
4431        }
4432
4433        case ACodec::kWhatShutdown:
4434        {
4435            int32_t keepComponentAllocated;
4436            CHECK(msg->findInt32(
4437                        "keepComponentAllocated", &keepComponentAllocated));
4438            ALOGW_IF(keepComponentAllocated,
4439                     "cannot keep component allocated on shutdown in Uninitialized state");
4440
4441            sp<AMessage> notify = mCodec->mNotify->dup();
4442            notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
4443            notify->post();
4444
4445            handled = true;
4446            break;
4447        }
4448
4449        case ACodec::kWhatFlush:
4450        {
4451            sp<AMessage> notify = mCodec->mNotify->dup();
4452            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
4453            notify->post();
4454
4455            handled = true;
4456            break;
4457        }
4458
4459        default:
4460            return BaseState::onMessageReceived(msg);
4461    }
4462
4463    return handled;
4464}
4465
4466void ACodec::UninitializedState::onSetup(
4467        const sp<AMessage> &msg) {
4468    if (onAllocateComponent(msg)
4469            && mCodec->mLoadedState->onConfigureComponent(msg)) {
4470        mCodec->mLoadedState->onStart();
4471    }
4472}
4473
4474bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
4475    ALOGV("onAllocateComponent");
4476
4477    CHECK(mCodec->mNode == NULL);
4478
4479    OMXClient client;
4480    CHECK_EQ(client.connect(), (status_t)OK);
4481
4482    sp<IOMX> omx = client.interface();
4483
4484    sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec->id());
4485
4486    mDeathNotifier = new DeathNotifier(notify);
4487    if (omx->asBinder()->linkToDeath(mDeathNotifier) != OK) {
4488        // This was a local binder, if it dies so do we, we won't care
4489        // about any notifications in the afterlife.
4490        mDeathNotifier.clear();
4491    }
4492
4493    Vector<OMXCodec::CodecNameAndQuirks> matchingCodecs;
4494
4495    AString mime;
4496
4497    AString componentName;
4498    uint32_t quirks = 0;
4499    int32_t encoder = false;
4500    if (msg->findString("componentName", &componentName)) {
4501        ssize_t index = matchingCodecs.add();
4502        OMXCodec::CodecNameAndQuirks *entry = &matchingCodecs.editItemAt(index);
4503        entry->mName = String8(componentName.c_str());
4504
4505        if (!OMXCodec::findCodecQuirks(
4506                    componentName.c_str(), &entry->mQuirks)) {
4507            entry->mQuirks = 0;
4508        }
4509    } else {
4510        CHECK(msg->findString("mime", &mime));
4511
4512        if (!msg->findInt32("encoder", &encoder)) {
4513            encoder = false;
4514        }
4515
4516        OMXCodec::findMatchingCodecs(
4517                mime.c_str(),
4518                encoder, // createEncoder
4519                NULL,  // matchComponentName
4520                0,     // flags
4521                &matchingCodecs);
4522    }
4523
4524    sp<CodecObserver> observer = new CodecObserver;
4525    IOMX::node_id node = NULL;
4526
4527    for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
4528            ++matchIndex) {
4529        componentName = matchingCodecs.itemAt(matchIndex).mName.string();
4530        quirks = matchingCodecs.itemAt(matchIndex).mQuirks;
4531
4532        pid_t tid = gettid();
4533        int prevPriority = androidGetThreadPriority(tid);
4534        androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
4535        status_t err = omx->allocateNode(componentName.c_str(), observer, &node);
4536        androidSetThreadPriority(tid, prevPriority);
4537
4538        if (err == OK) {
4539            break;
4540        } else {
4541            ALOGW("Allocating component '%s' failed, try next one.", componentName.c_str());
4542        }
4543
4544        node = NULL;
4545    }
4546
4547    if (node == NULL) {
4548        if (!mime.empty()) {
4549            ALOGE("Unable to instantiate a %scoder for type '%s'.",
4550                    encoder ? "en" : "de", mime.c_str());
4551        } else {
4552            ALOGE("Unable to instantiate codec '%s'.", componentName.c_str());
4553        }
4554
4555        mCodec->signalError(OMX_ErrorComponentNotFound);
4556        return false;
4557    }
4558
4559    notify = new AMessage(kWhatOMXMessage, mCodec->id());
4560    observer->setNotificationMessage(notify);
4561
4562    mCodec->mComponentName = componentName;
4563    mCodec->mFlags = 0;
4564
4565    if (componentName.endsWith(".secure")) {
4566        mCodec->mFlags |= kFlagIsSecure;
4567        mCodec->mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
4568    }
4569
4570    mCodec->mQuirks = quirks;
4571    mCodec->mOMX = omx;
4572    mCodec->mNode = node;
4573
4574    {
4575        sp<AMessage> notify = mCodec->mNotify->dup();
4576        notify->setInt32("what", CodecBase::kWhatComponentAllocated);
4577        notify->setString("componentName", mCodec->mComponentName.c_str());
4578        notify->post();
4579    }
4580
4581    mCodec->changeState(mCodec->mLoadedState);
4582
4583    return true;
4584}
4585
4586////////////////////////////////////////////////////////////////////////////////
4587
4588ACodec::LoadedState::LoadedState(ACodec *codec)
4589    : BaseState(codec) {
4590}
4591
4592void ACodec::LoadedState::stateEntered() {
4593    ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
4594
4595    mCodec->mPortEOS[kPortIndexInput] =
4596        mCodec->mPortEOS[kPortIndexOutput] = false;
4597
4598    mCodec->mInputEOSResult = OK;
4599
4600    mCodec->mDequeueCounter = 0;
4601    mCodec->mMetaDataBuffersToSubmit = 0;
4602    mCodec->mRepeatFrameDelayUs = -1ll;
4603    mCodec->mInputFormat.clear();
4604    mCodec->mOutputFormat.clear();
4605
4606    if (mCodec->mShutdownInProgress) {
4607        bool keepComponentAllocated = mCodec->mKeepComponentAllocated;
4608
4609        mCodec->mShutdownInProgress = false;
4610        mCodec->mKeepComponentAllocated = false;
4611
4612        onShutdown(keepComponentAllocated);
4613    }
4614    mCodec->mExplicitShutdown = false;
4615
4616    mCodec->processDeferredMessages();
4617}
4618
4619void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) {
4620    if (!keepComponentAllocated) {
4621        CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
4622
4623        mCodec->changeState(mCodec->mUninitializedState);
4624    }
4625
4626    if (mCodec->mExplicitShutdown) {
4627        sp<AMessage> notify = mCodec->mNotify->dup();
4628        notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
4629        notify->post();
4630        mCodec->mExplicitShutdown = false;
4631    }
4632}
4633
4634bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) {
4635    bool handled = false;
4636
4637    switch (msg->what()) {
4638        case ACodec::kWhatConfigureComponent:
4639        {
4640            onConfigureComponent(msg);
4641            handled = true;
4642            break;
4643        }
4644
4645        case ACodec::kWhatCreateInputSurface:
4646        {
4647            onCreateInputSurface(msg);
4648            handled = true;
4649            break;
4650        }
4651
4652        case ACodec::kWhatStart:
4653        {
4654            onStart();
4655            handled = true;
4656            break;
4657        }
4658
4659        case ACodec::kWhatShutdown:
4660        {
4661            int32_t keepComponentAllocated;
4662            CHECK(msg->findInt32(
4663                        "keepComponentAllocated", &keepComponentAllocated));
4664
4665            mCodec->mExplicitShutdown = true;
4666            onShutdown(keepComponentAllocated);
4667
4668            handled = true;
4669            break;
4670        }
4671
4672        case ACodec::kWhatFlush:
4673        {
4674            sp<AMessage> notify = mCodec->mNotify->dup();
4675            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
4676            notify->post();
4677
4678            handled = true;
4679            break;
4680        }
4681
4682        default:
4683            return BaseState::onMessageReceived(msg);
4684    }
4685
4686    return handled;
4687}
4688
4689bool ACodec::LoadedState::onConfigureComponent(
4690        const sp<AMessage> &msg) {
4691    ALOGV("onConfigureComponent");
4692
4693    CHECK(mCodec->mNode != NULL);
4694
4695    AString mime;
4696    CHECK(msg->findString("mime", &mime));
4697
4698    status_t err = mCodec->configureCodec(mime.c_str(), msg);
4699
4700    if (err != OK) {
4701        ALOGE("[%s] configureCodec returning error %d",
4702              mCodec->mComponentName.c_str(), err);
4703
4704        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
4705        return false;
4706    }
4707
4708    sp<RefBase> obj;
4709    if (msg->findObject("native-window", &obj)
4710            && strncmp("OMX.google.", mCodec->mComponentName.c_str(), 11)) {
4711        sp<NativeWindowWrapper> nativeWindow(
4712                static_cast<NativeWindowWrapper *>(obj.get()));
4713        CHECK(nativeWindow != NULL);
4714        mCodec->mNativeWindow = nativeWindow->getNativeWindow();
4715
4716        native_window_set_scaling_mode(
4717                mCodec->mNativeWindow.get(),
4718                NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
4719    }
4720    CHECK_EQ((status_t)OK, mCodec->initNativeWindow());
4721
4722    {
4723        sp<AMessage> notify = mCodec->mNotify->dup();
4724        notify->setInt32("what", CodecBase::kWhatComponentConfigured);
4725        notify->setMessage("input-format", mCodec->mInputFormat);
4726        notify->setMessage("output-format", mCodec->mOutputFormat);
4727        notify->post();
4728    }
4729
4730    return true;
4731}
4732
4733void ACodec::LoadedState::onCreateInputSurface(
4734        const sp<AMessage> & /* msg */) {
4735    ALOGV("onCreateInputSurface");
4736
4737    sp<AMessage> notify = mCodec->mNotify->dup();
4738    notify->setInt32("what", CodecBase::kWhatInputSurfaceCreated);
4739
4740    sp<IGraphicBufferProducer> bufferProducer;
4741    status_t err;
4742
4743    err = mCodec->mOMX->createInputSurface(mCodec->mNode, kPortIndexInput,
4744            &bufferProducer);
4745
4746    if (err == OK && mCodec->mRepeatFrameDelayUs > 0ll) {
4747        err = mCodec->mOMX->setInternalOption(
4748                mCodec->mNode,
4749                kPortIndexInput,
4750                IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY,
4751                &mCodec->mRepeatFrameDelayUs,
4752                sizeof(mCodec->mRepeatFrameDelayUs));
4753
4754        if (err != OK) {
4755            ALOGE("[%s] Unable to configure option to repeat previous "
4756                  "frames (err %d)",
4757                  mCodec->mComponentName.c_str(),
4758                  err);
4759        }
4760    }
4761
4762    if (err == OK && mCodec->mMaxPtsGapUs > 0ll) {
4763        err = mCodec->mOMX->setInternalOption(
4764                mCodec->mNode,
4765                kPortIndexInput,
4766                IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP,
4767                &mCodec->mMaxPtsGapUs,
4768                sizeof(mCodec->mMaxPtsGapUs));
4769
4770        if (err != OK) {
4771            ALOGE("[%s] Unable to configure max timestamp gap (err %d)",
4772                    mCodec->mComponentName.c_str(),
4773                    err);
4774        }
4775    }
4776
4777    if (err == OK && mCodec->mTimePerCaptureUs > 0ll
4778            && mCodec->mTimePerFrameUs > 0ll) {
4779        int64_t timeLapse[2];
4780        timeLapse[0] = mCodec->mTimePerFrameUs;
4781        timeLapse[1] = mCodec->mTimePerCaptureUs;
4782        err = mCodec->mOMX->setInternalOption(
4783                mCodec->mNode,
4784                kPortIndexInput,
4785                IOMX::INTERNAL_OPTION_TIME_LAPSE,
4786                &timeLapse[0],
4787                sizeof(timeLapse));
4788
4789        if (err != OK) {
4790            ALOGE("[%s] Unable to configure time lapse (err %d)",
4791                    mCodec->mComponentName.c_str(),
4792                    err);
4793        }
4794    }
4795
4796    if (err == OK && mCodec->mCreateInputBuffersSuspended) {
4797        bool suspend = true;
4798        err = mCodec->mOMX->setInternalOption(
4799                mCodec->mNode,
4800                kPortIndexInput,
4801                IOMX::INTERNAL_OPTION_SUSPEND,
4802                &suspend,
4803                sizeof(suspend));
4804
4805        if (err != OK) {
4806            ALOGE("[%s] Unable to configure option to suspend (err %d)",
4807                  mCodec->mComponentName.c_str(),
4808                  err);
4809        }
4810    }
4811
4812    if (err == OK) {
4813        notify->setObject("input-surface",
4814                new BufferProducerWrapper(bufferProducer));
4815    } else {
4816        // Can't use mCodec->signalError() here -- MediaCodec won't forward
4817        // the error through because it's in the "configured" state.  We
4818        // send a kWhatInputSurfaceCreated with an error value instead.
4819        ALOGE("[%s] onCreateInputSurface returning error %d",
4820                mCodec->mComponentName.c_str(), err);
4821        notify->setInt32("err", err);
4822    }
4823    notify->post();
4824}
4825
4826void ACodec::LoadedState::onStart() {
4827    ALOGV("onStart");
4828
4829    CHECK_EQ(mCodec->mOMX->sendCommand(
4830                mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
4831             (status_t)OK);
4832
4833    mCodec->changeState(mCodec->mLoadedToIdleState);
4834}
4835
4836////////////////////////////////////////////////////////////////////////////////
4837
4838ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec)
4839    : BaseState(codec) {
4840}
4841
4842void ACodec::LoadedToIdleState::stateEntered() {
4843    ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
4844
4845    status_t err;
4846    if ((err = allocateBuffers()) != OK) {
4847        ALOGE("Failed to allocate buffers after transitioning to IDLE state "
4848             "(error 0x%08x)",
4849             err);
4850
4851        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
4852
4853        mCodec->changeState(mCodec->mLoadedState);
4854    }
4855}
4856
4857status_t ACodec::LoadedToIdleState::allocateBuffers() {
4858    status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput);
4859
4860    if (err != OK) {
4861        return err;
4862    }
4863
4864    return mCodec->allocateBuffersOnPort(kPortIndexOutput);
4865}
4866
4867bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
4868    switch (msg->what()) {
4869        case kWhatSetParameters:
4870        case kWhatShutdown:
4871        {
4872            mCodec->deferMessage(msg);
4873            return true;
4874        }
4875
4876        case kWhatSignalEndOfInputStream:
4877        {
4878            mCodec->onSignalEndOfInputStream();
4879            return true;
4880        }
4881
4882        case kWhatResume:
4883        {
4884            // We'll be active soon enough.
4885            return true;
4886        }
4887
4888        case kWhatFlush:
4889        {
4890            // We haven't even started yet, so we're flushed alright...
4891            sp<AMessage> notify = mCodec->mNotify->dup();
4892            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
4893            notify->post();
4894            return true;
4895        }
4896
4897        default:
4898            return BaseState::onMessageReceived(msg);
4899    }
4900}
4901
4902bool ACodec::LoadedToIdleState::onOMXEvent(
4903        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
4904    switch (event) {
4905        case OMX_EventCmdComplete:
4906        {
4907            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
4908            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
4909
4910            CHECK_EQ(mCodec->mOMX->sendCommand(
4911                        mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting),
4912                     (status_t)OK);
4913
4914            mCodec->changeState(mCodec->mIdleToExecutingState);
4915
4916            return true;
4917        }
4918
4919        default:
4920            return BaseState::onOMXEvent(event, data1, data2);
4921    }
4922}
4923
4924////////////////////////////////////////////////////////////////////////////////
4925
4926ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec)
4927    : BaseState(codec) {
4928}
4929
4930void ACodec::IdleToExecutingState::stateEntered() {
4931    ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
4932}
4933
4934bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
4935    switch (msg->what()) {
4936        case kWhatSetParameters:
4937        case kWhatShutdown:
4938        {
4939            mCodec->deferMessage(msg);
4940            return true;
4941        }
4942
4943        case kWhatResume:
4944        {
4945            // We'll be active soon enough.
4946            return true;
4947        }
4948
4949        case kWhatFlush:
4950        {
4951            // We haven't even started yet, so we're flushed alright...
4952            sp<AMessage> notify = mCodec->mNotify->dup();
4953            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
4954            notify->post();
4955
4956            return true;
4957        }
4958
4959        case kWhatSignalEndOfInputStream:
4960        {
4961            mCodec->onSignalEndOfInputStream();
4962            return true;
4963        }
4964
4965        default:
4966            return BaseState::onMessageReceived(msg);
4967    }
4968}
4969
4970bool ACodec::IdleToExecutingState::onOMXEvent(
4971        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
4972    switch (event) {
4973        case OMX_EventCmdComplete:
4974        {
4975            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
4976            CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting);
4977
4978            mCodec->mExecutingState->resume();
4979            mCodec->changeState(mCodec->mExecutingState);
4980
4981            return true;
4982        }
4983
4984        default:
4985            return BaseState::onOMXEvent(event, data1, data2);
4986    }
4987}
4988
4989////////////////////////////////////////////////////////////////////////////////
4990
4991ACodec::ExecutingState::ExecutingState(ACodec *codec)
4992    : BaseState(codec),
4993      mActive(false) {
4994}
4995
4996ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode(
4997        OMX_U32 /* portIndex */) {
4998    return RESUBMIT_BUFFERS;
4999}
5000
5001void ACodec::ExecutingState::submitOutputMetaBuffers() {
5002    // submit as many buffers as there are input buffers with the codec
5003    // in case we are in port reconfiguring
5004    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
5005        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
5006
5007        if (info->mStatus == BufferInfo::OWNED_BY_COMPONENT) {
5008            if (mCodec->submitOutputMetaDataBuffer() != OK)
5009                break;
5010        }
5011    }
5012
5013    // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
5014    mCodec->signalSubmitOutputMetaDataBufferIfEOS_workaround();
5015}
5016
5017void ACodec::ExecutingState::submitRegularOutputBuffers() {
5018    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
5019        BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
5020
5021        if (mCodec->mNativeWindow != NULL) {
5022            CHECK(info->mStatus == BufferInfo::OWNED_BY_US
5023                    || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
5024
5025            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
5026                continue;
5027            }
5028        } else {
5029            CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
5030        }
5031
5032        ALOGV("[%s] calling fillBuffer %p",
5033             mCodec->mComponentName.c_str(), info->mBufferID);
5034
5035        CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
5036                 (status_t)OK);
5037
5038        info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
5039    }
5040}
5041
5042void ACodec::ExecutingState::submitOutputBuffers() {
5043    submitRegularOutputBuffers();
5044    if (mCodec->mStoreMetaDataInOutputBuffers) {
5045        submitOutputMetaBuffers();
5046    }
5047}
5048
5049void ACodec::ExecutingState::resume() {
5050    if (mActive) {
5051        ALOGV("[%s] We're already active, no need to resume.",
5052             mCodec->mComponentName.c_str());
5053
5054        return;
5055    }
5056
5057    submitOutputBuffers();
5058
5059    // Post all available input buffers
5060    CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u);
5061    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); i++) {
5062        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
5063        if (info->mStatus == BufferInfo::OWNED_BY_US) {
5064            postFillThisBuffer(info);
5065        }
5066    }
5067
5068    mActive = true;
5069}
5070
5071void ACodec::ExecutingState::stateEntered() {
5072    ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
5073
5074    mCodec->processDeferredMessages();
5075}
5076
5077bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) {
5078    bool handled = false;
5079
5080    switch (msg->what()) {
5081        case kWhatShutdown:
5082        {
5083            int32_t keepComponentAllocated;
5084            CHECK(msg->findInt32(
5085                        "keepComponentAllocated", &keepComponentAllocated));
5086
5087            mCodec->mShutdownInProgress = true;
5088            mCodec->mExplicitShutdown = true;
5089            mCodec->mKeepComponentAllocated = keepComponentAllocated;
5090
5091            mActive = false;
5092
5093            CHECK_EQ(mCodec->mOMX->sendCommand(
5094                        mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
5095                     (status_t)OK);
5096
5097            mCodec->changeState(mCodec->mExecutingToIdleState);
5098
5099            handled = true;
5100            break;
5101        }
5102
5103        case kWhatFlush:
5104        {
5105            ALOGV("[%s] ExecutingState flushing now "
5106                 "(codec owns %d/%d input, %d/%d output).",
5107                    mCodec->mComponentName.c_str(),
5108                    mCodec->countBuffersOwnedByComponent(kPortIndexInput),
5109                    mCodec->mBuffers[kPortIndexInput].size(),
5110                    mCodec->countBuffersOwnedByComponent(kPortIndexOutput),
5111                    mCodec->mBuffers[kPortIndexOutput].size());
5112
5113            mActive = false;
5114
5115            CHECK_EQ(mCodec->mOMX->sendCommand(
5116                        mCodec->mNode, OMX_CommandFlush, OMX_ALL),
5117                     (status_t)OK);
5118
5119            mCodec->changeState(mCodec->mFlushingState);
5120            handled = true;
5121            break;
5122        }
5123
5124        case kWhatResume:
5125        {
5126            resume();
5127
5128            handled = true;
5129            break;
5130        }
5131
5132        case kWhatRequestIDRFrame:
5133        {
5134            status_t err = mCodec->requestIDRFrame();
5135            if (err != OK) {
5136                ALOGW("Requesting an IDR frame failed.");
5137            }
5138
5139            handled = true;
5140            break;
5141        }
5142
5143        case kWhatSetParameters:
5144        {
5145            sp<AMessage> params;
5146            CHECK(msg->findMessage("params", &params));
5147
5148            status_t err = mCodec->setParameters(params);
5149
5150            sp<AMessage> reply;
5151            if (msg->findMessage("reply", &reply)) {
5152                reply->setInt32("err", err);
5153                reply->post();
5154            }
5155
5156            handled = true;
5157            break;
5158        }
5159
5160        case ACodec::kWhatSignalEndOfInputStream:
5161        {
5162            mCodec->onSignalEndOfInputStream();
5163            handled = true;
5164            break;
5165        }
5166
5167        // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
5168        case kWhatSubmitOutputMetaDataBufferIfEOS:
5169        {
5170            if (mCodec->mPortEOS[kPortIndexInput] &&
5171                    !mCodec->mPortEOS[kPortIndexOutput]) {
5172                status_t err = mCodec->submitOutputMetaDataBuffer();
5173                if (err == OK) {
5174                    mCodec->signalSubmitOutputMetaDataBufferIfEOS_workaround();
5175                }
5176            }
5177            return true;
5178        }
5179
5180        default:
5181            handled = BaseState::onMessageReceived(msg);
5182            break;
5183    }
5184
5185    return handled;
5186}
5187
5188status_t ACodec::setParameters(const sp<AMessage> &params) {
5189    int32_t videoBitrate;
5190    if (params->findInt32("video-bitrate", &videoBitrate)) {
5191        OMX_VIDEO_CONFIG_BITRATETYPE configParams;
5192        InitOMXParams(&configParams);
5193        configParams.nPortIndex = kPortIndexOutput;
5194        configParams.nEncodeBitrate = videoBitrate;
5195
5196        status_t err = mOMX->setConfig(
5197                mNode,
5198                OMX_IndexConfigVideoBitrate,
5199                &configParams,
5200                sizeof(configParams));
5201
5202        if (err != OK) {
5203            ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d",
5204                   videoBitrate, err);
5205
5206            return err;
5207        }
5208    }
5209
5210    int64_t skipFramesBeforeUs;
5211    if (params->findInt64("skip-frames-before", &skipFramesBeforeUs)) {
5212        status_t err =
5213            mOMX->setInternalOption(
5214                     mNode,
5215                     kPortIndexInput,
5216                     IOMX::INTERNAL_OPTION_START_TIME,
5217                     &skipFramesBeforeUs,
5218                     sizeof(skipFramesBeforeUs));
5219
5220        if (err != OK) {
5221            ALOGE("Failed to set parameter 'skip-frames-before' (err %d)", err);
5222            return err;
5223        }
5224    }
5225
5226    int32_t dropInputFrames;
5227    if (params->findInt32("drop-input-frames", &dropInputFrames)) {
5228        bool suspend = dropInputFrames != 0;
5229
5230        status_t err =
5231            mOMX->setInternalOption(
5232                     mNode,
5233                     kPortIndexInput,
5234                     IOMX::INTERNAL_OPTION_SUSPEND,
5235                     &suspend,
5236                     sizeof(suspend));
5237
5238        if (err != OK) {
5239            ALOGE("Failed to set parameter 'drop-input-frames' (err %d)", err);
5240            return err;
5241        }
5242    }
5243
5244    int32_t dummy;
5245    if (params->findInt32("request-sync", &dummy)) {
5246        status_t err = requestIDRFrame();
5247
5248        if (err != OK) {
5249            ALOGE("Requesting a sync frame failed w/ err %d", err);
5250            return err;
5251        }
5252    }
5253
5254    return OK;
5255}
5256
5257void ACodec::onSignalEndOfInputStream() {
5258    sp<AMessage> notify = mNotify->dup();
5259    notify->setInt32("what", CodecBase::kWhatSignaledInputEOS);
5260
5261    status_t err = mOMX->signalEndOfInputStream(mNode);
5262    if (err != OK) {
5263        notify->setInt32("err", err);
5264    }
5265    notify->post();
5266}
5267
5268bool ACodec::ExecutingState::onOMXEvent(
5269        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5270    switch (event) {
5271        case OMX_EventPortSettingsChanged:
5272        {
5273            CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
5274
5275            if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
5276                mCodec->mMetaDataBuffersToSubmit = 0;
5277                CHECK_EQ(mCodec->mOMX->sendCommand(
5278                            mCodec->mNode,
5279                            OMX_CommandPortDisable, kPortIndexOutput),
5280                         (status_t)OK);
5281
5282                mCodec->freeOutputBuffersNotOwnedByComponent();
5283
5284                mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
5285            } else if (data2 == OMX_IndexConfigCommonOutputCrop) {
5286                mCodec->mSentFormat = false;
5287            } else {
5288                ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx",
5289                     mCodec->mComponentName.c_str(), data2);
5290            }
5291
5292            return true;
5293        }
5294
5295        case OMX_EventBufferFlag:
5296        {
5297            return true;
5298        }
5299
5300        default:
5301            return BaseState::onOMXEvent(event, data1, data2);
5302    }
5303}
5304
5305////////////////////////////////////////////////////////////////////////////////
5306
5307ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState(
5308        ACodec *codec)
5309    : BaseState(codec) {
5310}
5311
5312ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode(
5313        OMX_U32 portIndex) {
5314    if (portIndex == kPortIndexOutput) {
5315        return FREE_BUFFERS;
5316    }
5317
5318    CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput);
5319
5320    return RESUBMIT_BUFFERS;
5321}
5322
5323bool ACodec::OutputPortSettingsChangedState::onMessageReceived(
5324        const sp<AMessage> &msg) {
5325    bool handled = false;
5326
5327    switch (msg->what()) {
5328        case kWhatFlush:
5329        case kWhatShutdown:
5330        case kWhatResume:
5331        case kWhatSetParameters:
5332        {
5333            if (msg->what() == kWhatResume) {
5334                ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
5335            }
5336
5337            mCodec->deferMessage(msg);
5338            handled = true;
5339            break;
5340        }
5341
5342        default:
5343            handled = BaseState::onMessageReceived(msg);
5344            break;
5345    }
5346
5347    return handled;
5348}
5349
5350void ACodec::OutputPortSettingsChangedState::stateEntered() {
5351    ALOGV("[%s] Now handling output port settings change",
5352         mCodec->mComponentName.c_str());
5353}
5354
5355bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
5356        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5357    switch (event) {
5358        case OMX_EventCmdComplete:
5359        {
5360            if (data1 == (OMX_U32)OMX_CommandPortDisable) {
5361                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
5362
5363                ALOGV("[%s] Output port now disabled.",
5364                        mCodec->mComponentName.c_str());
5365
5366                CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty());
5367                mCodec->mDealer[kPortIndexOutput].clear();
5368
5369                CHECK_EQ(mCodec->mOMX->sendCommand(
5370                            mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput),
5371                         (status_t)OK);
5372
5373                status_t err;
5374                if ((err = mCodec->allocateBuffersOnPort(
5375                                kPortIndexOutput)) != OK) {
5376                    ALOGE("Failed to allocate output port buffers after "
5377                         "port reconfiguration (error 0x%08x)",
5378                         err);
5379
5380                    mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5381
5382                    // This is technically not correct, but appears to be
5383                    // the only way to free the component instance.
5384                    // Controlled transitioning from excecuting->idle
5385                    // and idle->loaded seem impossible probably because
5386                    // the output port never finishes re-enabling.
5387                    mCodec->mShutdownInProgress = true;
5388                    mCodec->mKeepComponentAllocated = false;
5389                    mCodec->changeState(mCodec->mLoadedState);
5390                }
5391
5392                return true;
5393            } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
5394                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
5395
5396                mCodec->mSentFormat = false;
5397
5398                ALOGV("[%s] Output port now reenabled.",
5399                        mCodec->mComponentName.c_str());
5400
5401                if (mCodec->mExecutingState->active()) {
5402                    mCodec->mExecutingState->submitOutputBuffers();
5403                }
5404
5405                mCodec->changeState(mCodec->mExecutingState);
5406
5407                return true;
5408            }
5409
5410            return false;
5411        }
5412
5413        default:
5414            return false;
5415    }
5416}
5417
5418////////////////////////////////////////////////////////////////////////////////
5419
5420ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec)
5421    : BaseState(codec),
5422      mComponentNowIdle(false) {
5423}
5424
5425bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) {
5426    bool handled = false;
5427
5428    switch (msg->what()) {
5429        case kWhatFlush:
5430        {
5431            // Don't send me a flush request if you previously wanted me
5432            // to shutdown.
5433            TRESPASS();
5434            break;
5435        }
5436
5437        case kWhatShutdown:
5438        {
5439            // We're already doing that...
5440
5441            handled = true;
5442            break;
5443        }
5444
5445        default:
5446            handled = BaseState::onMessageReceived(msg);
5447            break;
5448    }
5449
5450    return handled;
5451}
5452
5453void ACodec::ExecutingToIdleState::stateEntered() {
5454    ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
5455
5456    mComponentNowIdle = false;
5457    mCodec->mSentFormat = false;
5458}
5459
5460bool ACodec::ExecutingToIdleState::onOMXEvent(
5461        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5462    switch (event) {
5463        case OMX_EventCmdComplete:
5464        {
5465            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
5466            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
5467
5468            mComponentNowIdle = true;
5469
5470            changeStateIfWeOwnAllBuffers();
5471
5472            return true;
5473        }
5474
5475        case OMX_EventPortSettingsChanged:
5476        case OMX_EventBufferFlag:
5477        {
5478            // We're shutting down and don't care about this anymore.
5479            return true;
5480        }
5481
5482        default:
5483            return BaseState::onOMXEvent(event, data1, data2);
5484    }
5485}
5486
5487void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
5488    if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) {
5489        CHECK_EQ(mCodec->mOMX->sendCommand(
5490                    mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded),
5491                 (status_t)OK);
5492
5493        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK);
5494        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK);
5495
5496        if ((mCodec->mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown)
5497                && mCodec->mNativeWindow != NULL) {
5498            // We push enough 1x1 blank buffers to ensure that one of
5499            // them has made it to the display.  This allows the OMX
5500            // component teardown to zero out any protected buffers
5501            // without the risk of scanning out one of those buffers.
5502            mCodec->pushBlankBuffersToNativeWindow();
5503        }
5504
5505        mCodec->changeState(mCodec->mIdleToLoadedState);
5506    }
5507}
5508
5509void ACodec::ExecutingToIdleState::onInputBufferFilled(
5510        const sp<AMessage> &msg) {
5511    BaseState::onInputBufferFilled(msg);
5512
5513    changeStateIfWeOwnAllBuffers();
5514}
5515
5516void ACodec::ExecutingToIdleState::onOutputBufferDrained(
5517        const sp<AMessage> &msg) {
5518    BaseState::onOutputBufferDrained(msg);
5519
5520    changeStateIfWeOwnAllBuffers();
5521}
5522
5523////////////////////////////////////////////////////////////////////////////////
5524
5525ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec)
5526    : BaseState(codec) {
5527}
5528
5529bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) {
5530    bool handled = false;
5531
5532    switch (msg->what()) {
5533        case kWhatShutdown:
5534        {
5535            // We're already doing that...
5536
5537            handled = true;
5538            break;
5539        }
5540
5541        case kWhatFlush:
5542        {
5543            // Don't send me a flush request if you previously wanted me
5544            // to shutdown.
5545            TRESPASS();
5546            break;
5547        }
5548
5549        default:
5550            handled = BaseState::onMessageReceived(msg);
5551            break;
5552    }
5553
5554    return handled;
5555}
5556
5557void ACodec::IdleToLoadedState::stateEntered() {
5558    ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
5559}
5560
5561bool ACodec::IdleToLoadedState::onOMXEvent(
5562        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5563    switch (event) {
5564        case OMX_EventCmdComplete:
5565        {
5566            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
5567            CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded);
5568
5569            mCodec->changeState(mCodec->mLoadedState);
5570
5571            return true;
5572        }
5573
5574        default:
5575            return BaseState::onOMXEvent(event, data1, data2);
5576    }
5577}
5578
5579////////////////////////////////////////////////////////////////////////////////
5580
5581ACodec::FlushingState::FlushingState(ACodec *codec)
5582    : BaseState(codec) {
5583}
5584
5585void ACodec::FlushingState::stateEntered() {
5586    ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());
5587
5588    mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
5589}
5590
5591bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) {
5592    bool handled = false;
5593
5594    switch (msg->what()) {
5595        case kWhatShutdown:
5596        {
5597            mCodec->deferMessage(msg);
5598            break;
5599        }
5600
5601        case kWhatFlush:
5602        {
5603            // We're already doing this right now.
5604            handled = true;
5605            break;
5606        }
5607
5608        default:
5609            handled = BaseState::onMessageReceived(msg);
5610            break;
5611    }
5612
5613    return handled;
5614}
5615
5616bool ACodec::FlushingState::onOMXEvent(
5617        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5618    ALOGV("[%s] FlushingState onOMXEvent(%d,%ld)",
5619            mCodec->mComponentName.c_str(), event, data1);
5620
5621    switch (event) {
5622        case OMX_EventCmdComplete:
5623        {
5624            CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush);
5625
5626            if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
5627                CHECK(!mFlushComplete[data2]);
5628                mFlushComplete[data2] = true;
5629
5630                if (mFlushComplete[kPortIndexInput]
5631                        && mFlushComplete[kPortIndexOutput]) {
5632                    changeStateIfWeOwnAllBuffers();
5633                }
5634            } else {
5635                CHECK_EQ(data2, OMX_ALL);
5636                CHECK(mFlushComplete[kPortIndexInput]);
5637                CHECK(mFlushComplete[kPortIndexOutput]);
5638
5639                changeStateIfWeOwnAllBuffers();
5640            }
5641
5642            return true;
5643        }
5644
5645        case OMX_EventPortSettingsChanged:
5646        {
5647            sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id());
5648            msg->setInt32("type", omx_message::EVENT);
5649            msg->setInt32("node", mCodec->mNode);
5650            msg->setInt32("event", event);
5651            msg->setInt32("data1", data1);
5652            msg->setInt32("data2", data2);
5653
5654            ALOGV("[%s] Deferring OMX_EventPortSettingsChanged",
5655                 mCodec->mComponentName.c_str());
5656
5657            mCodec->deferMessage(msg);
5658
5659            return true;
5660        }
5661
5662        default:
5663            return BaseState::onOMXEvent(event, data1, data2);
5664    }
5665
5666    return true;
5667}
5668
5669void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) {
5670    BaseState::onOutputBufferDrained(msg);
5671
5672    changeStateIfWeOwnAllBuffers();
5673}
5674
5675void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) {
5676    BaseState::onInputBufferFilled(msg);
5677
5678    changeStateIfWeOwnAllBuffers();
5679}
5680
5681void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() {
5682    if (mFlushComplete[kPortIndexInput]
5683            && mFlushComplete[kPortIndexOutput]
5684            && mCodec->allYourBuffersAreBelongToUs()) {
5685        // We now own all buffers except possibly those still queued with
5686        // the native window for rendering. Let's get those back as well.
5687        mCodec->waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs();
5688
5689        sp<AMessage> notify = mCodec->mNotify->dup();
5690        notify->setInt32("what", CodecBase::kWhatFlushCompleted);
5691        notify->post();
5692
5693        mCodec->mPortEOS[kPortIndexInput] =
5694            mCodec->mPortEOS[kPortIndexOutput] = false;
5695
5696        mCodec->mInputEOSResult = OK;
5697
5698        if (mCodec->mSkipCutBuffer != NULL) {
5699            mCodec->mSkipCutBuffer->clear();
5700        }
5701
5702        mCodec->changeState(mCodec->mExecutingState);
5703    }
5704}
5705
5706}  // namespace android
5707