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