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