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