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