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